pylzma_decompress.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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_decompress.c 104 2006-01-08 18:17:14Z jojo $
  23. *
  24. */
  25. #include <Python.h>
  26. #include <7zip/LzmaStateDecode.h>
  27. #include "pylzma.h"
  28. void free_lzma_state(CLzmaDecoderState *state)
  29. {
  30. if (state->Probs)
  31. free(state->Probs);
  32. state->Probs = NULL;
  33. if (state->Dictionary)
  34. free(state->Dictionary);
  35. state->Dictionary = NULL;
  36. }
  37. const char doc_decompress[] = \
  38. "decompress(data[, maxlength]) -- Decompress the data, returning a string containing the decompressed data. "\
  39. "If the string has been compressed without an EOS marker, you must provide the maximum length as keyword parameter.\n" \
  40. "decompress(data, bufsize[, maxlength]) -- Decompress the data using an initial output buffer of size bufsize. "\
  41. "If the string has been compressed without an EOS marker, you must provide the maximum length as keyword parameter.\n";
  42. PyObject *pylzma_decompress(PyObject *self, PyObject *args, PyObject *kwargs)
  43. {
  44. unsigned char *data, *tmp;
  45. int length, blocksize=BLOCK_SIZE, outsize, outavail, totallength=-1, bufsize;
  46. PyObject *result = NULL, *output=NULL;
  47. CLzmaDecoderState state;
  48. unsigned char properties[LZMA_PROPERTIES_SIZE];
  49. int res;
  50. // possible keywords for this function
  51. static char *kwlist[] = {"data", "bufsize", "maxlength", NULL};
  52. if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|ll", kwlist, &data, &length, &blocksize, &totallength))
  53. return NULL;
  54. memset(&state, 0, sizeof(state));
  55. if (!(output = PyString_FromStringAndSize(NULL, blocksize)))
  56. {
  57. PyErr_NoMemory();
  58. goto exit;
  59. }
  60. // Initialize LZMA state decoder
  61. memcpy(&properties, data, sizeof(properties));
  62. data += sizeof(properties);
  63. length -= sizeof(properties);
  64. if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
  65. {
  66. PyErr_SetString(PyExc_TypeError, "Incorrect stream properties");
  67. goto exit;
  68. }
  69. state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
  70. if (state.Probs == 0) {
  71. PyErr_NoMemory();
  72. goto exit;
  73. }
  74. if (state.Properties.DictionarySize == 0)
  75. state.Dictionary = 0;
  76. else {
  77. state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
  78. if (state.Dictionary == 0) {
  79. free(state.Probs);
  80. state.Probs = NULL;
  81. PyErr_NoMemory();
  82. goto exit;
  83. }
  84. }
  85. LzmaDecoderInit(&state);
  86. // decompress data
  87. tmp = (unsigned char *)PyString_AS_STRING(output);
  88. outsize = 0;
  89. outavail = blocksize;
  90. while (1)
  91. {
  92. SizeT inProcessed, outProcessed;
  93. int finishDecoding = 1;
  94. bufsize = outavail;
  95. Py_BEGIN_ALLOW_THREADS
  96. if (totallength != -1)
  97. // We know the total size of the decompressed string
  98. res = LzmaDecode(&state, data, length, &inProcessed,
  99. tmp, outavail > totallength ? totallength : outavail, &outProcessed, finishDecoding);
  100. else
  101. // Decompress until EOS marker is reached
  102. res = LzmaDecode(&state, data, length, &inProcessed,
  103. tmp, outavail, &outProcessed, finishDecoding);
  104. Py_END_ALLOW_THREADS
  105. if (res != 0) {
  106. PyErr_SetString(PyExc_ValueError, "data error during decompression");
  107. goto exit;
  108. }
  109. length -= inProcessed;
  110. data += inProcessed;
  111. outsize += outProcessed;
  112. tmp += outProcessed;
  113. outavail -= outProcessed;
  114. if (totallength != -1)
  115. totallength -= outProcessed;
  116. if (length > 0 || outProcessed == bufsize) {
  117. // Target block is full, increase size...
  118. if (_PyString_Resize(&output, outsize+outavail+BLOCK_SIZE) != 0)
  119. goto exit;
  120. outavail += BLOCK_SIZE;
  121. tmp = (unsigned char *)&PyString_AS_STRING(output)[outsize];
  122. } else
  123. // Finished decompressing
  124. break;
  125. }
  126. // Decrease length of result to total output size
  127. if (_PyString_Resize(&output, outsize) != 0)
  128. goto exit;
  129. result = output;
  130. output = NULL;
  131. exit:
  132. free_lzma_state(&state);
  133. Py_XDECREF(output);
  134. return result;
  135. }