pylzma_decompress_compat.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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_compat.c 104 2006-01-08 18:17:14Z jojo $
  23. *
  24. */
  25. #include <Python.h>
  26. #include <7zip/LzmaCompatDecode.h>
  27. #include "pylzma.h"
  28. void free_lzma_stream(lzma_stream *stream)
  29. {
  30. if (stream->dynamicData)
  31. lzmafree(stream->dynamicData);
  32. stream->dynamicData = NULL;
  33. if (stream->dictionary)
  34. lzmafree(stream->dictionary);
  35. stream->dictionary = NULL;
  36. }
  37. const char doc_decompress_compat[] = \
  38. "decompress_compat(string) -- Decompress the data in string, returning a string containing the decompressed data.\n" \
  39. "decompress_compat(string, bufsize) -- Decompress the data in string using an initial output buffer of size bufsize.\n";
  40. PyObject *pylzma_decompress_compat(PyObject *self, PyObject *args)
  41. {
  42. char *data;
  43. int length, blocksize=BLOCK_SIZE;
  44. PyObject *result = NULL;
  45. lzma_stream stream;
  46. int res;
  47. char *output;
  48. if (!PyArg_ParseTuple(args, "s#|l", &data, &length, &blocksize))
  49. return NULL;
  50. memset(&stream, 0, sizeof(stream));
  51. if (!(output = (char *)malloc(blocksize)))
  52. {
  53. PyErr_NoMemory();
  54. goto exit;
  55. }
  56. lzmaCompatInit(&stream);
  57. stream.next_in = (Byte *)data;
  58. stream.avail_in = length;
  59. stream.next_out = (Byte *)output;
  60. stream.avail_out = blocksize;
  61. // decompress data
  62. while (1)
  63. {
  64. Py_BEGIN_ALLOW_THREADS
  65. res = lzmaCompatDecode(&stream);
  66. Py_END_ALLOW_THREADS
  67. if (res == LZMA_STREAM_END) {
  68. break;
  69. } else if (res == LZMA_NOT_ENOUGH_MEM) {
  70. // out of memory during decompression
  71. PyErr_NoMemory();
  72. goto exit;
  73. } else if (res == LZMA_DATA_ERROR) {
  74. PyErr_SetString(PyExc_ValueError, "data error during decompression");
  75. goto exit;
  76. } else if (res == LZMA_OK) {
  77. // check if we need to adjust the output buffer
  78. if (stream.avail_out == 0)
  79. {
  80. output = (char *)realloc(output, blocksize+BLOCK_SIZE);
  81. stream.avail_out = BLOCK_SIZE;
  82. stream.next_out = (Byte *)&output[blocksize];
  83. blocksize += BLOCK_SIZE;
  84. };
  85. } else {
  86. PyErr_Format(PyExc_ValueError, "unknown return code from lzmaDecode: %d", res);
  87. goto exit;
  88. }
  89. // if we exit here, decompression finished without returning LZMA_STREAM_END
  90. // XXX: why is this sometimes?
  91. if (stream.avail_in == 0)
  92. break;
  93. }
  94. result = PyString_FromStringAndSize(output, stream.totalOut);
  95. exit:
  96. free_lzma_stream(&stream);
  97. if (output != NULL)
  98. free(output);
  99. return result;
  100. }