Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

254 lines
6.2 KiB

  1. /* LzmaUtil.c -- Test application for LZMA compression
  2. 2014-12-31 : Igor Pavlov : Public domain */
  3. #include "../../Precomp.h"
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include "../../Alloc.h"
  8. #include "../../7zFile.h"
  9. #include "../../7zVersion.h"
  10. #include "../../LzmaDec.h"
  11. #include "../../LzmaEnc.h"
  12. const char *kCantReadMessage = "Can not read input file";
  13. const char *kCantWriteMessage = "Can not write output file";
  14. const char *kCantAllocateMessage = "Can not allocate memory";
  15. const char *kDataErrorMessage = "Data error";
  16. static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
  17. static void SzFree(void *p, void *address) { p = p; MyFree(address); }
  18. static ISzAlloc g_Alloc = { SzAlloc, SzFree };
  19. void PrintHelp(char *buffer)
  20. {
  21. strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n"
  22. "\nUsage: lzma <e|d> inputFile outputFile\n"
  23. " e: encode file\n"
  24. " d: decode file\n");
  25. }
  26. int PrintError(char *buffer, const char *message)
  27. {
  28. strcat(buffer, "\nError: ");
  29. strcat(buffer, message);
  30. strcat(buffer, "\n");
  31. return 1;
  32. }
  33. int PrintErrorNumber(char *buffer, SRes val)
  34. {
  35. sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);
  36. return 1;
  37. }
  38. int PrintUserError(char *buffer)
  39. {
  40. return PrintError(buffer, "Incorrect command");
  41. }
  42. #define IN_BUF_SIZE (1 << 16)
  43. #define OUT_BUF_SIZE (1 << 16)
  44. static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,
  45. UInt64 unpackSize)
  46. {
  47. int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
  48. Byte inBuf[IN_BUF_SIZE];
  49. Byte outBuf[OUT_BUF_SIZE];
  50. size_t inPos = 0, inSize = 0, outPos = 0;
  51. LzmaDec_Init(state);
  52. for (;;)
  53. {
  54. if (inPos == inSize)
  55. {
  56. inSize = IN_BUF_SIZE;
  57. RINOK(inStream->Read(inStream, inBuf, &inSize));
  58. inPos = 0;
  59. }
  60. {
  61. SRes res;
  62. SizeT inProcessed = inSize - inPos;
  63. SizeT outProcessed = OUT_BUF_SIZE - outPos;
  64. ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
  65. ELzmaStatus status;
  66. if (thereIsSize && outProcessed > unpackSize)
  67. {
  68. outProcessed = (SizeT)unpackSize;
  69. finishMode = LZMA_FINISH_END;
  70. }
  71. res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed,
  72. inBuf + inPos, &inProcessed, finishMode, &status);
  73. inPos += inProcessed;
  74. outPos += outProcessed;
  75. unpackSize -= outProcessed;
  76. if (outStream)
  77. if (outStream->Write(outStream, outBuf, outPos) != outPos)
  78. return SZ_ERROR_WRITE;
  79. outPos = 0;
  80. if (res != SZ_OK || (thereIsSize && unpackSize == 0))
  81. return res;
  82. if (inProcessed == 0 && outProcessed == 0)
  83. {
  84. if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
  85. return SZ_ERROR_DATA;
  86. return res;
  87. }
  88. }
  89. }
  90. }
  91. static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream)
  92. {
  93. UInt64 unpackSize;
  94. int i;
  95. SRes res = 0;
  96. CLzmaDec state;
  97. /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
  98. unsigned char header[LZMA_PROPS_SIZE + 8];
  99. /* Read and parse header */
  100. RINOK(SeqInStream_Read(inStream, header, sizeof(header)));
  101. unpackSize = 0;
  102. for (i = 0; i < 8; i++)
  103. unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);
  104. LzmaDec_Construct(&state);
  105. RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));
  106. res = Decode2(&state, outStream, inStream, unpackSize);
  107. LzmaDec_Free(&state, &g_Alloc);
  108. return res;
  109. }
  110. static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs)
  111. {
  112. CLzmaEncHandle enc;
  113. SRes res;
  114. CLzmaEncProps props;
  115. rs = rs;
  116. enc = LzmaEnc_Create(&g_Alloc);
  117. if (enc == 0)
  118. return SZ_ERROR_MEM;
  119. LzmaEncProps_Init(&props);
  120. res = LzmaEnc_SetProps(enc, &props);
  121. if (res == SZ_OK)
  122. {
  123. Byte header[LZMA_PROPS_SIZE + 8];
  124. size_t headerSize = LZMA_PROPS_SIZE;
  125. int i;
  126. res = LzmaEnc_WriteProperties(enc, header, &headerSize);
  127. for (i = 0; i < 8; i++)
  128. header[headerSize++] = (Byte)(fileSize >> (8 * i));
  129. if (outStream->Write(outStream, header, headerSize) != headerSize)
  130. res = SZ_ERROR_WRITE;
  131. else
  132. {
  133. if (res == SZ_OK)
  134. res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc);
  135. }
  136. }
  137. LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
  138. return res;
  139. }
  140. int main2(int numArgs, const char *args[], char *rs)
  141. {
  142. CFileSeqInStream inStream;
  143. CFileOutStream outStream;
  144. char c;
  145. int res;
  146. int encodeMode;
  147. Bool useOutFile = False;
  148. FileSeqInStream_CreateVTable(&inStream);
  149. File_Construct(&inStream.file);
  150. FileOutStream_CreateVTable(&outStream);
  151. File_Construct(&outStream.file);
  152. if (numArgs == 1)
  153. {
  154. PrintHelp(rs);
  155. return 0;
  156. }
  157. if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1)
  158. return PrintUserError(rs);
  159. c = args[1][0];
  160. encodeMode = (c == 'e' || c == 'E');
  161. if (!encodeMode && c != 'd' && c != 'D')
  162. return PrintUserError(rs);
  163. {
  164. size_t t4 = sizeof(UInt32);
  165. size_t t8 = sizeof(UInt64);
  166. if (t4 != 4 || t8 != 8)
  167. return PrintError(rs, "Incorrect UInt32 or UInt64");
  168. }
  169. if (InFile_Open(&inStream.file, args[2]) != 0)
  170. return PrintError(rs, "Can not open input file");
  171. if (numArgs > 3)
  172. {
  173. useOutFile = True;
  174. if (OutFile_Open(&outStream.file, args[3]) != 0)
  175. return PrintError(rs, "Can not open output file");
  176. }
  177. else if (encodeMode)
  178. PrintUserError(rs);
  179. if (encodeMode)
  180. {
  181. UInt64 fileSize;
  182. File_GetLength(&inStream.file, &fileSize);
  183. res = Encode(&outStream.s, &inStream.s, fileSize, rs);
  184. }
  185. else
  186. {
  187. res = Decode(&outStream.s, useOutFile ? &inStream.s : NULL);
  188. }
  189. if (useOutFile)
  190. File_Close(&outStream.file);
  191. File_Close(&inStream.file);
  192. if (res != SZ_OK)
  193. {
  194. if (res == SZ_ERROR_MEM)
  195. return PrintError(rs, kCantAllocateMessage);
  196. else if (res == SZ_ERROR_DATA)
  197. return PrintError(rs, kDataErrorMessage);
  198. else if (res == SZ_ERROR_WRITE)
  199. return PrintError(rs, kCantWriteMessage);
  200. else if (res == SZ_ERROR_READ)
  201. return PrintError(rs, kCantReadMessage);
  202. return PrintErrorNumber(rs, res);
  203. }
  204. return 0;
  205. }
  206. int MY_CDECL main(int numArgs, const char *args[])
  207. {
  208. char rs[800] = { 0 };
  209. int res = main2(numArgs, args, rs);
  210. fputs(rs, stdout);
  211. return res;
  212. }