LzmaTest.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. LzmaTest.c
  3. Test application for LZMA Decoder
  4. This file written and distributed to public domain by Igor Pavlov.
  5. This file is part of LZMA SDK 4.26 (2005-08-05)
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include "LzmaDecode.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. size_t MyReadFile(FILE *file, void *data, size_t size)
  15. {
  16. if (size == 0)
  17. return 0;
  18. return fread(data, 1, size, file);
  19. }
  20. int MyReadFileAndCheck(FILE *file, void *data, size_t size)
  21. { return (MyReadFile(file, data, size) == size);}
  22. size_t MyWriteFile(FILE *file, const void *data, size_t size)
  23. {
  24. if (size == 0)
  25. return 0;
  26. return fwrite(data, 1, size, file);
  27. }
  28. int MyWriteFileAndCheck(FILE *file, const void *data, size_t size)
  29. { return (MyWriteFile(file, data, size) == size); }
  30. #ifdef _LZMA_IN_CB
  31. #define kInBufferSize (1 << 15)
  32. typedef struct _CBuffer
  33. {
  34. ILzmaInCallback InCallback;
  35. FILE *File;
  36. unsigned char Buffer[kInBufferSize];
  37. } CBuffer;
  38. int LzmaReadCompressed(void *object, const unsigned char **buffer, SizeT *size)
  39. {
  40. CBuffer *b = (CBuffer *)object;
  41. *buffer = b->Buffer;
  42. *size = (SizeT)MyReadFile(b->File, b->Buffer, kInBufferSize);
  43. return LZMA_RESULT_OK;
  44. }
  45. CBuffer g_InBuffer;
  46. #endif
  47. #ifdef _LZMA_OUT_READ
  48. #define kOutBufferSize (1 << 15)
  49. unsigned char g_OutBuffer[kOutBufferSize];
  50. #endif
  51. int PrintError(char *buffer, const char *message)
  52. {
  53. sprintf(buffer + strlen(buffer), "\nError: ");
  54. sprintf(buffer + strlen(buffer), message);
  55. return 1;
  56. }
  57. int main3(FILE *inFile, FILE *outFile, char *rs)
  58. {
  59. /* We use two 32-bit integers to construct 64-bit integer for file size.
  60. You can remove outSizeHigh, if you don't need >= 4GB supporting,
  61. or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
  62. UInt32 outSize = 0;
  63. UInt32 outSizeHigh = 0;
  64. #ifndef _LZMA_OUT_READ
  65. SizeT outSizeFull;
  66. unsigned char *outStream;
  67. #endif
  68. int waitEOS = 1;
  69. /* waitEOS = 1, if there is no uncompressed size in headers,
  70. so decoder will wait EOS (End of Stream Marker) in compressed stream */
  71. #ifndef _LZMA_IN_CB
  72. SizeT compressedSize;
  73. unsigned char *inStream;
  74. #endif
  75. CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
  76. unsigned char properties[LZMA_PROPERTIES_SIZE];
  77. int res;
  78. #ifdef _LZMA_IN_CB
  79. g_InBuffer.File = inFile;
  80. #endif
  81. if (sizeof(UInt32) < 4)
  82. return PrintError(rs, "LZMA decoder needs correct UInt32");
  83. #ifndef _LZMA_IN_CB
  84. {
  85. long length;
  86. fseek(inFile, 0, SEEK_END);
  87. length = ftell(inFile);
  88. fseek(inFile, 0, SEEK_SET);
  89. if ((long)(SizeT)length != length)
  90. return PrintError(rs, "Too big compressed stream");
  91. compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8));
  92. }
  93. #endif
  94. /* Read LZMA properties for compressed stream */
  95. if (!MyReadFileAndCheck(inFile, properties, sizeof(properties)))
  96. return PrintError(rs, kCantReadMessage);
  97. /* Read uncompressed size */
  98. {
  99. int i;
  100. for (i = 0; i < 8; i++)
  101. {
  102. unsigned char b;
  103. if (!MyReadFileAndCheck(inFile, &b, 1))
  104. return PrintError(rs, kCantReadMessage);
  105. if (b != 0xFF)
  106. waitEOS = 0;
  107. if (i < 4)
  108. outSize += (UInt32)(b) << (i * 8);
  109. else
  110. outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
  111. }
  112. #ifndef _LZMA_OUT_READ
  113. if (waitEOS)
  114. return PrintError(rs, "Stream with EOS marker is not supported");
  115. outSizeFull = (SizeT)outSize;
  116. if (sizeof(SizeT) >= 8)
  117. outSizeFull |= (((SizeT)outSizeHigh << 16) << 16);
  118. else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize)
  119. return PrintError(rs, "Too big uncompressed stream");
  120. #endif
  121. }
  122. /* Decode LZMA properties and allocate memory */
  123. if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
  124. return PrintError(rs, "Incorrect stream properties");
  125. state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
  126. #ifdef _LZMA_OUT_READ
  127. if (state.Properties.DictionarySize == 0)
  128. state.Dictionary = 0;
  129. else
  130. state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
  131. #else
  132. if (outSizeFull == 0)
  133. outStream = 0;
  134. else
  135. outStream = (unsigned char *)malloc(outSizeFull);
  136. #endif
  137. #ifndef _LZMA_IN_CB
  138. if (compressedSize == 0)
  139. inStream = 0;
  140. else
  141. inStream = (unsigned char *)malloc(compressedSize);
  142. #endif
  143. if (state.Probs == 0
  144. #ifdef _LZMA_OUT_READ
  145. || (state.Dictionary == 0 && state.Properties.DictionarySize != 0)
  146. #else
  147. || (outStream == 0 && outSizeFull != 0)
  148. #endif
  149. #ifndef _LZMA_IN_CB
  150. || (inStream == 0 && compressedSize != 0)
  151. #endif
  152. )
  153. {
  154. free(state.Probs);
  155. #ifdef _LZMA_OUT_READ
  156. free(state.Dictionary);
  157. #else
  158. free(outStream);
  159. #endif
  160. #ifndef _LZMA_IN_CB
  161. free(inStream);
  162. #endif
  163. return PrintError(rs, kCantAllocateMessage);
  164. }
  165. /* Decompress */
  166. #ifdef _LZMA_IN_CB
  167. g_InBuffer.InCallback.Read = LzmaReadCompressed;
  168. #else
  169. if (!MyReadFileAndCheck(inFile, inStream, compressedSize))
  170. return PrintError(rs, kCantReadMessage);
  171. #endif
  172. #ifdef _LZMA_OUT_READ
  173. {
  174. #ifndef _LZMA_IN_CB
  175. SizeT inAvail = compressedSize;
  176. const unsigned char *inBuffer = inStream;
  177. #endif
  178. LzmaDecoderInit(&state);
  179. do
  180. {
  181. #ifndef _LZMA_IN_CB
  182. SizeT inProcessed;
  183. #endif
  184. SizeT outProcessed;
  185. SizeT outAvail = kOutBufferSize;
  186. if (!waitEOS && outSizeHigh == 0 && outAvail > outSize)
  187. outAvail = (SizeT)outSize;
  188. res = LzmaDecode(&state,
  189. #ifdef _LZMA_IN_CB
  190. &g_InBuffer.InCallback,
  191. #else
  192. inBuffer, inAvail, &inProcessed,
  193. #endif
  194. g_OutBuffer, outAvail, &outProcessed);
  195. if (res != 0)
  196. {
  197. sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
  198. res = 1;
  199. break;
  200. }
  201. #ifndef _LZMA_IN_CB
  202. inAvail -= inProcessed;
  203. inBuffer += inProcessed;
  204. #endif
  205. if (outFile != 0)
  206. if (!MyWriteFileAndCheck(outFile, g_OutBuffer, (size_t)outProcessed))
  207. {
  208. PrintError(rs, kCantWriteMessage);
  209. res = 1;
  210. break;
  211. }
  212. if (outSize < outProcessed)
  213. outSizeHigh--;
  214. outSize -= (UInt32)outProcessed;
  215. outSize &= 0xFFFFFFFF;
  216. if (outProcessed == 0)
  217. {
  218. if (!waitEOS && (outSize != 0 || outSizeHigh != 0))
  219. res = 1;
  220. break;
  221. }
  222. }
  223. while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS);
  224. }
  225. #else
  226. {
  227. #ifndef _LZMA_IN_CB
  228. SizeT inProcessed;
  229. #endif
  230. SizeT outProcessed;
  231. res = LzmaDecode(&state,
  232. #ifdef _LZMA_IN_CB
  233. &g_InBuffer.InCallback,
  234. #else
  235. inStream, compressedSize, &inProcessed,
  236. #endif
  237. outStream, outSizeFull, &outProcessed);
  238. if (res != 0)
  239. {
  240. sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
  241. res = 1;
  242. }
  243. else if (outFile != 0)
  244. {
  245. if (!MyWriteFileAndCheck(outFile, outStream, (size_t)outProcessed))
  246. {
  247. PrintError(rs, kCantWriteMessage);
  248. res = 1;
  249. }
  250. }
  251. }
  252. #endif
  253. free(state.Probs);
  254. #ifdef _LZMA_OUT_READ
  255. free(state.Dictionary);
  256. #else
  257. free(outStream);
  258. #endif
  259. #ifndef _LZMA_IN_CB
  260. free(inStream);
  261. #endif
  262. return res;
  263. }
  264. int main2(int numArgs, const char *args[], char *rs)
  265. {
  266. FILE *inFile = 0;
  267. FILE *outFile = 0;
  268. int res;
  269. sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-05\n");
  270. if (numArgs < 2 || numArgs > 3)
  271. {
  272. sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n");
  273. return 1;
  274. }
  275. inFile = fopen(args[1], "rb");
  276. if (inFile == 0)
  277. return PrintError(rs, "Can not open input file");
  278. if (numArgs > 2)
  279. {
  280. outFile = fopen(args[2], "wb+");
  281. if (outFile == 0)
  282. return PrintError(rs, "Can not open output file");
  283. }
  284. res = main3(inFile, outFile, rs);
  285. if (outFile != 0)
  286. fclose(outFile);
  287. fclose(inFile);
  288. return res;
  289. }
  290. int main(int numArgs, const char *args[])
  291. {
  292. char rs[800] = { 0 };
  293. int res = main2(numArgs, args, rs);
  294. printf(rs);
  295. return res;
  296. }