LzmaStateTest.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*
  2. LzmaStateTest.c
  3. Test application for LZMA Decoder (State version)
  4. This file written and distributed to public domain by Igor Pavlov.
  5. This file is part of LZMA SDK 4.26 (2005-08-02)
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include "LzmaStateDecode.h"
  11. const char *kCantReadMessage = "Can not read input file";
  12. const char *kCantWriteMessage = "Can not write output file";
  13. const char *kCantAllocateMessage = "Can not allocate memory";
  14. #define kInBufferSize (1 << 15)
  15. #define kOutBufferSize (1 << 15)
  16. unsigned char g_InBuffer[kInBufferSize];
  17. unsigned char g_OutBuffer[kOutBufferSize];
  18. size_t MyReadFile(FILE *file, void *data, size_t size)
  19. { return fread(data, 1, size, file); }
  20. int MyReadFileAndCheck(FILE *file, void *data, size_t size)
  21. { return (MyReadFile(file, data, size) == size); }
  22. int PrintError(char *buffer, const char *message)
  23. {
  24. sprintf(buffer + strlen(buffer), "\nError: ");
  25. sprintf(buffer + strlen(buffer), message);
  26. return 1;
  27. }
  28. int main3(FILE *inFile, FILE *outFile, char *rs)
  29. {
  30. /* We use two 32-bit integers to construct 64-bit integer for file size.
  31. You can remove outSizeHigh, if you don't need >= 4GB supporting,
  32. or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
  33. UInt32 outSize = 0;
  34. UInt32 outSizeHigh = 0;
  35. int waitEOS = 1;
  36. /* waitEOS = 1, if there is no uncompressed size in headers,
  37. so decoder will wait EOS (End of Stream Marker) in compressed stream */
  38. int i;
  39. int res = 0;
  40. CLzmaDecoderState state; /* it's about 140 bytes structure, if int is 32-bit */
  41. unsigned char properties[LZMA_PROPERTIES_SIZE];
  42. SizeT inAvail = 0;
  43. unsigned char *inBuffer = 0;
  44. if (sizeof(UInt32) < 4)
  45. return PrintError(rs, "LZMA decoder needs correct UInt32");
  46. /* Read LZMA properties for compressed stream */
  47. if (!MyReadFileAndCheck(inFile, properties, sizeof(properties)))
  48. return PrintError(rs, kCantReadMessage);
  49. /* Read uncompressed size */
  50. for (i = 0; i < 8; i++)
  51. {
  52. unsigned char b;
  53. if (!MyReadFileAndCheck(inFile, &b, 1))
  54. return PrintError(rs, kCantReadMessage);
  55. if (b != 0xFF)
  56. waitEOS = 0;
  57. if (i < 4)
  58. outSize += (UInt32)(b) << (i * 8);
  59. else
  60. outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
  61. }
  62. /* Decode LZMA properties and allocate memory */
  63. if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
  64. return PrintError(rs, "Incorrect stream properties");
  65. state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
  66. if (state.Probs == 0)
  67. return PrintError(rs, kCantAllocateMessage);
  68. if (state.Properties.DictionarySize == 0)
  69. state.Dictionary = 0;
  70. else
  71. {
  72. state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
  73. if (state.Dictionary == 0)
  74. {
  75. free(state.Probs);
  76. return PrintError(rs, kCantAllocateMessage);
  77. }
  78. }
  79. /* Decompress */
  80. LzmaDecoderInit(&state);
  81. do
  82. {
  83. SizeT inProcessed, outProcessed;
  84. int finishDecoding;
  85. UInt32 outAvail = kOutBufferSize;
  86. if (!waitEOS && outSizeHigh == 0 && outAvail > outSize)
  87. outAvail = outSize;
  88. if (inAvail == 0)
  89. {
  90. inAvail = (SizeT)MyReadFile(inFile, g_InBuffer, kInBufferSize);
  91. inBuffer = g_InBuffer;
  92. }
  93. finishDecoding = (inAvail == 0);
  94. res = LzmaDecode(&state,
  95. inBuffer, inAvail, &inProcessed,
  96. g_OutBuffer, outAvail, &outProcessed,
  97. finishDecoding);
  98. if (res != 0)
  99. {
  100. sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
  101. res = 1;
  102. break;
  103. }
  104. inAvail -= inProcessed;
  105. inBuffer += inProcessed;
  106. if (outFile != 0)
  107. if (fwrite(g_OutBuffer, 1, outProcessed, outFile) != outProcessed)
  108. {
  109. PrintError(rs, kCantWriteMessage);
  110. res = 1;
  111. break;
  112. }
  113. if (outSize < outProcessed)
  114. outSizeHigh--;
  115. outSize -= (UInt32)outProcessed;
  116. outSize &= 0xFFFFFFFF;
  117. if (outProcessed == 0 && finishDecoding)
  118. {
  119. if (!waitEOS && (outSize != 0 || outSizeHigh != 0))
  120. res = 1;
  121. break;
  122. }
  123. }
  124. while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS);
  125. free(state.Dictionary);
  126. free(state.Probs);
  127. return res;
  128. }
  129. int main2(int numArgs, const char *args[], char *rs)
  130. {
  131. FILE *inFile = 0;
  132. FILE *outFile = 0;
  133. int res;
  134. sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-02\n");
  135. if (numArgs < 2 || numArgs > 3)
  136. {
  137. sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n");
  138. return 1;
  139. }
  140. inFile = fopen(args[1], "rb");
  141. if (inFile == 0)
  142. return PrintError(rs, "Can not open input file");
  143. if (numArgs > 2)
  144. {
  145. outFile = fopen(args[2], "wb+");
  146. if (outFile == 0)
  147. return PrintError(rs, "Can not open output file");
  148. }
  149. res = main3(inFile, outFile, rs);
  150. if (outFile != 0)
  151. fclose(outFile);
  152. fclose(inFile);
  153. return res;
  154. }
  155. int main(int numArgs, const char *args[])
  156. {
  157. char rs[800] = { 0 };
  158. int res = main2(numArgs, args, rs);
  159. printf(rs);
  160. return res;
  161. }