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