pylzma_streams.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * Python Bindings for LZMA
  3. *
  4. * Copyright (c) 2004-2006 by Joachim Bauch, mail@joachim-bauch.de
  5. * 7-Zip Copyright (C) 1999-2005 Igor Pavlov
  6. * LZMA SDK Copyright (C) 1999-2005 Igor Pavlov
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. *
  22. * $Id: pylzma_streams.h 104 2006-01-08 18:17:14Z jojo $
  23. *
  24. */
  25. #ifndef ___PYLZMA_STREAMS__H___
  26. #define ___PYLZMA_STREAMS__H___
  27. #include <Python.h>
  28. #include <7zip/Common/MyWindows.h>
  29. #include <7zip/7zip/IStream.h>
  30. #include <7zip/Common/MyCom.h>
  31. class CInStream :
  32. public ISequentialInStream,
  33. public CMyUnknownImp
  34. {
  35. private:
  36. BYTE *next_in;
  37. UINT32 avail_in;
  38. BYTE *origin;
  39. UINT32 original_size;
  40. UINT32 free_space;
  41. bool allocated;
  42. PyObject *sourceFile;
  43. public:
  44. MY_UNKNOWN_IMP
  45. CInStream(BYTE *data, UINT32 length)
  46. {
  47. SetData(data, length);
  48. allocated = false;
  49. }
  50. CInStream()
  51. {
  52. SetData(NULL, 0);
  53. }
  54. CInStream(PyObject *source)
  55. {
  56. SetData(NULL, 0);
  57. sourceFile = source;
  58. }
  59. virtual ~CInStream()
  60. {
  61. if (allocated)
  62. free(origin);
  63. }
  64. void SetData(BYTE *data, UINT32 length)
  65. {
  66. sourceFile = NULL;
  67. origin = data;
  68. next_in = data;
  69. avail_in = length;
  70. original_size = length;
  71. free_space = 0;
  72. }
  73. int getAvailIn() { return avail_in; }
  74. bool AppendData(BYTE *data, UINT32 length)
  75. {
  76. void *insert;
  77. if (origin == NULL || free_space < (UINT32)length) {
  78. // we need to resize the temporary buffer
  79. int add = length - free_space;
  80. int ofs = next_in - origin;
  81. origin = (BYTE *)realloc(origin, original_size + add);
  82. if (origin == NULL)
  83. return false;
  84. allocated = true;
  85. free_space += add;
  86. original_size += add;
  87. next_in = &origin[ofs];
  88. insert = &origin[avail_in];
  89. } else
  90. insert = &next_in[avail_in];
  91. memcpy(insert, data, length);
  92. avail_in += length;
  93. free_space -= length;
  94. return true;
  95. }
  96. STDMETHOD(Read)(void *data, UINT32 size, UINT32 *processedSize)
  97. {
  98. return ReadPart(data, size, processedSize);
  99. }
  100. STDMETHOD(ReadPart)(void *data, UINT32 size, UINT32 *processedSize)
  101. {
  102. if (sourceFile)
  103. {
  104. // read from file-like object
  105. HRESULT res = E_FAIL;
  106. // we might be calling into Python code from outside the main thread, so block threads...
  107. START_BLOCK_THREADS
  108. PyObject *result = PyObject_CallMethod(sourceFile, "read", "l", size);
  109. if (result == NULL)
  110. goto exit;
  111. if (!PyString_Check(result))
  112. {
  113. PyObject *str = PyObject_Str(result);
  114. Py_XDECREF(result);
  115. if (str == NULL)
  116. goto exit;
  117. result = str;
  118. }
  119. memcpy(data, PyString_AS_STRING(result), PyString_Size(result));
  120. if (processedSize)
  121. *processedSize = PyString_Size(result);
  122. Py_XDECREF(result);
  123. res = S_OK;
  124. exit:
  125. END_BLOCK_THREADS
  126. return res;
  127. }
  128. if (processedSize)
  129. *processedSize = 0;
  130. while (size)
  131. {
  132. if (!avail_in)
  133. return S_OK;
  134. UINT32 len = size < avail_in ? size : avail_in;
  135. memcpy(data, next_in, len);
  136. avail_in -= len;
  137. size -= len;
  138. next_in += len;
  139. if (allocated)
  140. {
  141. memmove(origin, next_in, avail_in);
  142. next_in = origin;
  143. free_space += len;
  144. }
  145. data = (BYTE *)(data) + len;
  146. if (processedSize)
  147. *processedSize += len;
  148. }
  149. return S_OK;
  150. }
  151. };
  152. class COutStream :
  153. public ISequentialOutStream,
  154. public CMyUnknownImp
  155. {
  156. private:
  157. BYTE *buffer;
  158. BYTE *next_out;
  159. UINT32 avail_out;
  160. UINT32 count;
  161. UINT32 readpos;
  162. public:
  163. MY_UNKNOWN_IMP
  164. COutStream()
  165. {
  166. buffer = (BYTE *)malloc(BLOCK_SIZE);
  167. next_out = buffer;
  168. avail_out = BLOCK_SIZE;
  169. count = 0;
  170. readpos = 0;
  171. }
  172. virtual ~COutStream()
  173. {
  174. if (buffer)
  175. free(buffer);
  176. buffer = NULL;
  177. }
  178. char *getData()
  179. {
  180. return (char *)buffer;
  181. }
  182. int getLength()
  183. {
  184. return count;
  185. }
  186. int getMaxRead()
  187. {
  188. return count - readpos;
  189. }
  190. void Read(void *dest, UINT32 size)
  191. {
  192. memcpy(dest, &buffer[readpos], size);
  193. increaseReadPos(size);
  194. }
  195. void *getReadPtr()
  196. {
  197. return &buffer[readpos];
  198. }
  199. void increaseReadPos(UINT32 count)
  200. {
  201. readpos += count;
  202. }
  203. STDMETHOD(Write)(const void *data, UINT32 size, UINT32 *processedSize)
  204. {
  205. return WritePart(data, size, processedSize);
  206. }
  207. STDMETHOD(WritePart)(const void *data, UINT32 size, UINT32 *processedSize)
  208. {
  209. if (processedSize)
  210. *processedSize = 0;
  211. while (size)
  212. {
  213. if (!avail_out)
  214. {
  215. buffer = (BYTE *)realloc(buffer, count + BLOCK_SIZE);
  216. avail_out += BLOCK_SIZE;
  217. next_out = &buffer[count];
  218. }
  219. UINT32 len = size < avail_out ? size : avail_out;
  220. memcpy(next_out, data, len);
  221. avail_out -= len;
  222. size -= len;
  223. next_out += len;
  224. count += len;
  225. data = (BYTE *)(data) + len;
  226. if (processedSize)
  227. *processedSize += len;
  228. }
  229. return S_OK;
  230. }
  231. };
  232. #endif