pylzma_compress.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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_compress.cpp 104 2006-01-08 18:17:14Z jojo $
  23. *
  24. */
  25. #include <Python.h>
  26. #include <7zip/Common/MyWindows.h>
  27. #include <7zip/7zip/IStream.h>
  28. #include <7zip/7zip/Compress/LZMA/LZMAEncoder.h>
  29. #include "pylzma.h"
  30. #include "pylzma_streams.h"
  31. int set_encoder_properties(NCompress::NLZMA::CEncoder *encoder, int dictionary, int posBits,
  32. int literalContextBits, int literalPosBits, int algorithm, int fastBytes, int eos,
  33. int multithreading, const char *matchfinder)
  34. {
  35. wchar_t tmp[10];
  36. unsigned int i;
  37. encoder->SetWriteEndMarkerMode(eos ? true : false);
  38. PROPID propIDs[] =
  39. {
  40. NCoderPropID::kDictionarySize,
  41. NCoderPropID::kPosStateBits,
  42. NCoderPropID::kLitContextBits,
  43. NCoderPropID::kLitPosBits,
  44. NCoderPropID::kAlgorithm,
  45. NCoderPropID::kNumFastBytes,
  46. NCoderPropID::kMatchFinder
  47. #ifdef COMPRESS_MF_MT
  48. , NCoderPropID::kMultiThread
  49. #endif
  50. };
  51. const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
  52. PROPVARIANT props[kNumProps];
  53. // NCoderProp::kDictionarySize;
  54. props[0].vt = VT_UI4;
  55. props[0].ulVal = 1 << dictionary;
  56. // NCoderProp::kPosStateBits;
  57. props[1].vt = VT_UI4;
  58. props[1].ulVal = posBits;
  59. // NCoderProp::kLitContextBits;
  60. props[2].vt = VT_UI4;
  61. props[2].ulVal = literalContextBits;
  62. // NCoderProp::kLitPosBits;
  63. props[3].vt = VT_UI4;
  64. props[3].ulVal = literalPosBits;
  65. // NCoderProp::kAlgorithm;
  66. props[4].vt = VT_UI4;
  67. props[4].ulVal = algorithm;
  68. // NCoderProp::kNumFastBytes;
  69. props[5].vt = VT_UI4;
  70. props[5].ulVal = fastBytes;
  71. // NCoderProp::kMatchFinder;
  72. if (strlen(matchfinder) > (sizeof(tmp)/2)-1)
  73. return 1;
  74. props[6].vt = VT_BSTR;
  75. for (i=0; i<strlen(matchfinder); i++)
  76. tmp[i] = matchfinder[i];
  77. tmp[i] = 0;
  78. props[6].bstrVal = (BSTR)(const wchar_t *)&tmp;
  79. #ifdef COMPRESS_MF_MT
  80. // NCoderPropID::kMultiThread
  81. props[7].vt = VT_BOOL;
  82. props[7].boolVal = (multithreading != 0) ? VARIANT_TRUE : VARIANT_FALSE;
  83. #endif
  84. return encoder->SetCoderProperties(propIDs, props, kNumProps);
  85. }
  86. #ifdef __cplusplus
  87. extern "C"
  88. #endif
  89. const char doc_compress[] = \
  90. "compress(string, dictionary=23, fastBytes=128, literalContextBits=3, literalPosBits=0, posBits=2, algorithm=2, eos=1, multithreading=1, matchfinder='bt4') -- Compress the data in string using the given parameters, returning a string containing the compressed data.";
  91. #ifdef __cplusplus
  92. extern "C" {
  93. #endif
  94. PyObject *pylzma_compress(PyObject *self, PyObject *args, PyObject *kwargs)
  95. {
  96. PyObject *result = NULL;
  97. NCompress::NLZMA::CEncoder *encoder = NULL;
  98. CInStream *inStream = NULL;
  99. COutStream *outStream = NULL;
  100. int res;
  101. // possible keywords for this function
  102. static char *kwlist[] = {"data", "dictionary", "fastBytes", "literalContextBits",
  103. "literalPosBits", "posBits", "algorithm", "eos", "multithreading", "matchfinder", NULL};
  104. int dictionary = 23; // [0,28], default 23 (8MB)
  105. int fastBytes = 128; // [5,255], default 128
  106. int literalContextBits = 3; // [0,8], default 3
  107. int literalPosBits = 0; // [0,4], default 0
  108. int posBits = 2; // [0,4], default 2
  109. int eos = 1; // write "end of stream" marker?
  110. int multithreading = 1; // use multithreading if available?
  111. char *matchfinder = "bt4"; // matchfinder algorithm
  112. int algorithm = 2;
  113. char *data;
  114. int length;
  115. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|iiiiiiiis", kwlist, &data, &length, &dictionary, &fastBytes,
  116. &literalContextBits, &literalPosBits, &posBits, &algorithm, &eos, &multithreading, &matchfinder))
  117. return NULL;
  118. CHECK_RANGE(dictionary, 0, 28, "dictionary must be between 0 and 28");
  119. CHECK_RANGE(fastBytes, 5, 255, "fastBytes must be between 5 and 255");
  120. CHECK_RANGE(literalContextBits, 0, 8, "literalContextBits must be between 0 and 8");
  121. CHECK_RANGE(literalPosBits, 0, 4, "literalPosBits must be between 0 and 4");
  122. CHECK_RANGE(posBits, 0, 4, "posBits must be between 0 and 4");
  123. CHECK_RANGE(algorithm, 0, 2, "algorithm must be between 0 and 2");
  124. encoder = new NCompress::NLZMA::CEncoder();
  125. CHECK_NULL(encoder);
  126. if ((res = set_encoder_properties(encoder, dictionary, posBits, literalContextBits, literalPosBits, algorithm, fastBytes, eos, multithreading, matchfinder) != 0))
  127. {
  128. PyErr_SetString(PyExc_TypeError, "can't set coder properties");
  129. goto exit;
  130. }
  131. inStream = new CInStream((BYTE *)data, length);
  132. CHECK_NULL(inStream);
  133. outStream = new COutStream();
  134. CHECK_NULL(outStream);
  135. Py_BEGIN_ALLOW_THREADS
  136. encoder->SetStreams(inStream, outStream, 0, 0);
  137. encoder->WriteCoderProperties(outStream);
  138. while(true)
  139. {
  140. UInt64 processedInSize;
  141. UInt64 processedOutSize;
  142. Int32 finished;
  143. if ((res = encoder->CodeOneBlock(&processedInSize, &processedOutSize, &finished)) != S_OK)
  144. {
  145. PyErr_Format(PyExc_TypeError, "Error during compressing: %d", res);
  146. goto exit;
  147. }
  148. if (finished != 0)
  149. break;
  150. }
  151. Py_END_ALLOW_THREADS
  152. result = PyString_FromStringAndSize((const char *)outStream->getData(), outStream->getLength());
  153. exit:
  154. DELETE_AND_NULL(encoder);
  155. DELETE_AND_NULL(inStream);
  156. return result;
  157. }
  158. #ifdef __cplusplus
  159. }
  160. #endif