]>
Commit | Line | Data |
---|---|---|
662b42db YF |
1 | /** @file\r |
2 | BrotliCompress Compress/Decompress tool (BrotliCompress)\r | |
3 | \r | |
4 | Copyright (c) 2020, ByoSoft Corporation. All rights reserved.<BR>\r | |
5 | SPDX-License-Identifier: BSD-2-Clause-Patent\r | |
6 | \r | |
7 | **/\r | |
8 | \r | |
9 | /* Command line interface for Brotli library. */\r | |
10 | \r | |
11 | #include <errno.h>\r | |
12 | #include <fcntl.h>\r | |
13 | #include <stdio.h>\r | |
14 | #include <stdlib.h>\r | |
15 | #include <string.h>\r | |
16 | #include <sys/stat.h>\r | |
17 | #include <sys/types.h>\r | |
18 | #include <time.h>\r | |
19 | \r | |
20 | #include "./brotli/c/common/constants.h"\r | |
21 | #include "./brotli/c/common/version.h"\r | |
22 | #include <brotli/decode.h>\r | |
23 | #include <brotli/encode.h>\r | |
24 | \r | |
25 | #if !defined(_WIN32)\r | |
26 | #include <unistd.h>\r | |
27 | #include <utime.h>\r | |
28 | #else\r | |
29 | #include <io.h>\r | |
30 | #include <share.h>\r | |
31 | #include <sys/utime.h>\r | |
32 | \r | |
33 | #if !defined(__MINGW32__)\r | |
34 | #define STDIN_FILENO _fileno(stdin)\r | |
35 | #define STDOUT_FILENO _fileno(stdout)\r | |
36 | #define S_IRUSR S_IREAD\r | |
37 | #define S_IWUSR S_IWRITE\r | |
38 | #endif\r | |
39 | \r | |
40 | #define fopen ms_fopen\r | |
41 | #define open ms_open\r | |
42 | \r | |
43 | #if defined(_MSC_VER) && (_MSC_VER >= 1400)\r | |
44 | #define fseek _fseeki64\r | |
45 | #define ftell _ftelli64\r | |
46 | #endif\r | |
47 | \r | |
48 | static FILE* ms_fopen(const char* FileName, const char* Mode) {\r | |
49 | FILE* Result;\r | |
50 | Result = NULL;\r | |
51 | fopen_s(&Result, FileName, Mode);\r | |
52 | return Result;\r | |
53 | }\r | |
54 | \r | |
55 | static int ms_open(const char* FileName, int Oflag, int Pmode) {\r | |
56 | int Result;\r | |
57 | Result = -1;\r | |
58 | _sopen_s(&Result, FileName, Oflag | O_BINARY, _SH_DENYNO, Pmode);\r | |
59 | return Result;\r | |
60 | }\r | |
61 | #endif /* WIN32 */\r | |
62 | \r | |
63 | \r | |
64 | #ifndef _MAX_PATH\r | |
65 | #define _MAX_PATH 500\r | |
66 | #endif\r | |
67 | \r | |
68 | #define DEFAULT_LGWIN 22\r | |
69 | #define DECODE_HEADER_SIZE 0x10\r | |
70 | #define GAP_MEM_BLOCK 0x1000\r | |
71 | size_t ScratchBufferSize = 0;\r | |
72 | static const size_t kFileBufferSize = 1 << 19;\r | |
73 | \r | |
74 | static void Version(void) {\r | |
75 | int Major;\r | |
76 | int Minor;\r | |
77 | int Patch;\r | |
78 | Major = BROTLI_VERSION >> 24;\r | |
79 | Minor = (BROTLI_VERSION >> 12) & 0xFFF;\r | |
80 | Patch = BROTLI_VERSION & 0xFFF;\r | |
81 | printf("BrotliCompress %d.%d.%d\n", Major, Minor, Patch);\r | |
82 | }\r | |
83 | \r | |
84 | static void Usage() {\r | |
85 | printf("Usage: %s [OPTION]... [FILE]...\n", __FILE__);\r | |
86 | printf(\r | |
87 | "Options:\n"\r | |
88 | " -e, --compress compress\n"\r | |
89 | " -d, --decompress decompress\n"\r | |
90 | " -h, --help display this help and exit\n");\r | |
91 | printf(\r | |
92 | " -o FILE, --output=FILE output file (only if 1 input file)\n");\r | |
93 | printf(\r | |
94 | " -g NUM, --gap=NUM scratch memory gap level (1-16)\n");\r | |
95 | printf(\r | |
96 | " -q NUM, --quality=NUM compression level (%d-%d)\n",\r | |
97 | BROTLI_MIN_QUALITY, BROTLI_MAX_QUALITY);\r | |
98 | printf(\r | |
99 | " -v, --version display version and exit\n");\r | |
100 | }\r | |
101 | \r | |
102 | static int64_t FileSize(const char* Path) {\r | |
103 | FILE *FileHandle;\r | |
104 | int64_t RetVal;\r | |
105 | FileHandle = fopen(Path, "rb");\r | |
106 | \r | |
107 | if (FileHandle == NULL) {\r | |
108 | printf ("Failed to open file [%s]\n", Path);\r | |
109 | return -1;\r | |
110 | }\r | |
111 | if (fseek(FileHandle, 0L, SEEK_END) != 0) {\r | |
112 | printf ("Failed to seek file [%s]\n", Path);\r | |
113 | fclose(FileHandle);\r | |
114 | return -1;\r | |
115 | }\r | |
116 | RetVal = ftell(FileHandle);\r | |
117 | if (fclose(FileHandle) != 0) {\r | |
118 | printf ("Failed to close file [%s]\n", Path);\r | |
119 | return -1;\r | |
120 | }\r | |
121 | return RetVal;\r | |
122 | }\r | |
123 | \r | |
124 | static BROTLI_BOOL HasMoreInput(FILE *FileHandle) {\r | |
125 | return feof(FileHandle) ? BROTLI_FALSE : BROTLI_TRUE;\r | |
126 | }\r | |
127 | \r | |
128 | int OpenFiles(char *InputFile, FILE **InHandle, char *OutputFile, FILE **OutHandle) {\r | |
129 | *InHandle = NULL;\r | |
130 | *OutHandle = NULL;\r | |
131 | *InHandle = fopen(InputFile, "rb");\r | |
132 | if (*InHandle == NULL) {\r | |
133 | printf("Failed to open input file [%s]\n", InputFile);\r | |
134 | return BROTLI_FALSE;\r | |
135 | }\r | |
136 | \r | |
137 | *OutHandle = fopen(OutputFile, "wb+");\r | |
138 | if (*OutHandle == NULL) {\r | |
139 | printf("Failed to open output file [%s]\n", OutputFile);\r | |
140 | fclose(*InHandle);\r | |
141 | return BROTLI_FALSE;\r | |
142 | }\r | |
143 | return BROTLI_TRUE;\r | |
144 | }\r | |
145 | \r | |
146 | int CompressFile(char *InputFile, uint8_t *InputBuffer, char *OutputFile, uint8_t *OutputBuffer, int Quality, int Gap) {\r | |
147 | int64_t InputFileSize;\r | |
148 | FILE *InputFileHandle;\r | |
149 | FILE *OutputFileHandle;\r | |
150 | BrotliEncoderState *EncodeState;\r | |
151 | uint32_t LgWin;\r | |
152 | BROTLI_BOOL IsEof;\r | |
153 | size_t AvailableIn;\r | |
154 | const uint8_t *NextIn;\r | |
155 | size_t AvailableOut;\r | |
156 | uint8_t *NextOut;\r | |
157 | uint8_t *Input;\r | |
158 | uint8_t *Output;\r | |
9cd854e1 | 159 | size_t TotalOut;\r |
662b42db YF |
160 | size_t OutSize;\r |
161 | uint32_t SizeHint;\r | |
162 | BROTLI_BOOL IsOk;\r | |
163 | AvailableIn = 0;\r | |
164 | IsEof = BROTLI_FALSE;\r | |
165 | Input = InputBuffer;\r | |
166 | Output = OutputBuffer;\r | |
167 | IsOk = BROTLI_TRUE;\r | |
168 | LgWin = DEFAULT_LGWIN;\r | |
169 | \r | |
170 | InputFileSize = FileSize(InputFile);\r | |
171 | \r | |
172 | IsOk = OpenFiles(InputFile, &InputFileHandle, OutputFile, &OutputFileHandle);\r | |
173 | if (!IsOk) {\r | |
174 | return IsOk;\r | |
175 | }\r | |
176 | \r | |
177 | fseek (OutputFileHandle, DECODE_HEADER_SIZE, SEEK_SET);\r | |
178 | \r | |
179 | EncodeState = BrotliEncoderCreateInstance(NULL, NULL, NULL);\r | |
180 | if (!EncodeState) {\r | |
181 | printf("Out of memory\n");\r | |
182 | IsOk = BROTLI_FALSE;\r | |
183 | goto Finish;\r | |
184 | }\r | |
185 | BrotliEncoderSetParameter(EncodeState, BROTLI_PARAM_QUALITY, (uint32_t)Quality);\r | |
186 | \r | |
187 | if (InputFileSize >= 0) {\r | |
188 | LgWin = BROTLI_MIN_WINDOW_BITS;\r | |
189 | while (BROTLI_MAX_BACKWARD_LIMIT(LgWin) < InputFileSize) {\r | |
190 | LgWin++;\r | |
191 | if (LgWin == BROTLI_MAX_WINDOW_BITS) {\r | |
192 | break;\r | |
193 | }\r | |
194 | }\r | |
195 | }\r | |
196 | BrotliEncoderSetParameter(EncodeState, BROTLI_PARAM_LGWIN, LgWin);\r | |
197 | if (InputFileSize > 0) {\r | |
198 | SizeHint = InputFileSize < (1 << 30)? (uint32_t)InputFileSize : (1u << 30);\r | |
199 | BrotliEncoderSetParameter(EncodeState, BROTLI_PARAM_SIZE_HINT, SizeHint);\r | |
200 | }\r | |
201 | \r | |
202 | AvailableIn = 0;\r | |
203 | NextIn = NULL;\r | |
204 | AvailableOut = kFileBufferSize;\r | |
205 | NextOut = Output;\r | |
206 | for (;;) {\r | |
207 | if (AvailableIn == 0 && !IsEof) {\r | |
208 | AvailableIn = fread(Input, 1, kFileBufferSize, InputFileHandle);\r | |
209 | NextIn = Input;\r | |
210 | if (ferror(InputFileHandle)) {\r | |
211 | printf("Failed to read input [%s]\n", InputFile);\r | |
212 | IsOk = BROTLI_FALSE;\r | |
213 | goto Finish;\r | |
214 | }\r | |
215 | IsEof = !HasMoreInput(InputFileHandle);\r | |
216 | }\r | |
217 | \r | |
9cd854e1 CC |
218 | if (!IsEof){\r |
219 | do{\r | |
220 | if (!BrotliEncoderCompressStream(EncodeState,\r | |
221 | BROTLI_OPERATION_FLUSH,\r | |
222 | &AvailableIn, &NextIn, &AvailableOut, &NextOut, &TotalOut)) {\r | |
223 | printf("Failed to compress data [%s]\n", InputFile);\r | |
662b42db YF |
224 | IsOk = BROTLI_FALSE;\r |
225 | goto Finish;\r | |
226 | }\r | |
9cd854e1 CC |
227 | OutSize = (size_t)(NextOut - Output);\r |
228 | if (OutSize > 0) {\r | |
229 | fwrite(Output, 1, OutSize, OutputFileHandle);\r | |
230 | if (ferror(OutputFileHandle)) {\r | |
231 | printf("Failed to write output [%s]\n", OutputFile);\r | |
232 | IsOk = BROTLI_FALSE;\r | |
233 | goto Finish;\r | |
234 | }\r | |
235 | }\r | |
236 | NextOut = Output;\r | |
237 | AvailableOut = kFileBufferSize;\r | |
662b42db | 238 | }\r |
9cd854e1 | 239 | while (AvailableIn > 0 || BrotliEncoderHasMoreOutput(EncodeState));\r |
662b42db | 240 | }\r |
9cd854e1 CC |
241 | else{\r |
242 | do{\r | |
243 | if (!BrotliEncoderCompressStream(EncodeState,\r | |
244 | BROTLI_OPERATION_FINISH,\r | |
245 | &AvailableIn, &NextIn, &AvailableOut, &NextOut, &TotalOut)) {\r | |
246 | printf("Failed to compress data [%s]\n", InputFile);\r | |
662b42db YF |
247 | IsOk = BROTLI_FALSE;\r |
248 | goto Finish;\r | |
249 | }\r | |
9cd854e1 CC |
250 | OutSize = (size_t)(NextOut - Output);\r |
251 | if (OutSize > 0) {\r | |
252 | fwrite(Output, 1, OutSize, OutputFileHandle);\r | |
253 | if (ferror(OutputFileHandle)) {\r | |
254 | printf("Failed to write output [%s]\n", OutputFile);\r | |
255 | IsOk = BROTLI_FALSE;\r | |
256 | goto Finish;\r | |
257 | }\r | |
258 | }\r | |
259 | NextOut = Output;\r | |
260 | AvailableOut = kFileBufferSize;\r | |
662b42db | 261 | }\r |
9cd854e1 | 262 | while (AvailableIn > 0 || BrotliEncoderHasMoreOutput(EncodeState));\r |
662b42db | 263 | }\r |
9cd854e1 | 264 | if (BrotliEncoderIsFinished(EncodeState)){\r |
662b42db YF |
265 | break;\r |
266 | }\r | |
267 | }\r | |
268 | \r | |
269 | Finish:\r | |
270 | if (EncodeState) {\r | |
271 | BrotliEncoderDestroyInstance(EncodeState);\r | |
272 | }\r | |
273 | if (InputFileHandle) {\r | |
274 | fclose(InputFileHandle);\r | |
275 | }\r | |
276 | if (OutputFileHandle) {\r | |
277 | fclose(OutputFileHandle);\r | |
278 | }\r | |
279 | return IsOk;\r | |
280 | }\r | |
281 | \r | |
282 | /* Default BrotliAllocFunc */\r | |
283 | void* BrotliAllocFunc(void* Opaque, size_t Size) {\r | |
284 | *(size_t *)Opaque = *(size_t *) Opaque + Size;\r | |
285 | return malloc(Size);\r | |
286 | }\r | |
287 | \r | |
288 | /* Default BrotliFreeFunc */\r | |
289 | void BrotliFreeFunc(void* Opaque, void* Address) {\r | |
290 | free(Address);\r | |
291 | }\r | |
292 | \r | |
293 | int DecompressFile(char *InputFile, uint8_t *InputBuffer, char *OutputFile, uint8_t *OutputBuffer, int Quality, int Gap) {\r | |
294 | FILE *InputFileHandle;\r | |
295 | FILE *OutputFileHandle;\r | |
296 | BrotliDecoderState *DecoderState;\r | |
297 | BrotliDecoderResult Result;\r | |
298 | size_t AvailableIn;\r | |
299 | const uint8_t *NextIn;\r | |
300 | size_t AvailableOut;\r | |
301 | uint8_t *NextOut;\r | |
302 | uint8_t *Input;\r | |
303 | uint8_t *Output;\r | |
304 | size_t OutSize;\r | |
305 | BROTLI_BOOL IsOk;\r | |
306 | AvailableIn = 0;\r | |
307 | Input = InputBuffer;\r | |
308 | Output = OutputBuffer;\r | |
309 | IsOk = BROTLI_TRUE;\r | |
310 | \r | |
311 | IsOk = OpenFiles(InputFile, &InputFileHandle, OutputFile, &OutputFileHandle);\r | |
312 | if (!IsOk) {\r | |
313 | return IsOk;\r | |
314 | }\r | |
315 | fseek(InputFileHandle, DECODE_HEADER_SIZE, SEEK_SET);\r | |
316 | \r | |
317 | DecoderState = BrotliDecoderCreateInstance(BrotliAllocFunc, BrotliFreeFunc, &ScratchBufferSize);\r | |
318 | if (!DecoderState) {\r | |
319 | printf("Out of memory\n");\r | |
320 | IsOk = BROTLI_FALSE;\r | |
321 | goto Finish;\r | |
322 | }\r | |
323 | /* This allows decoding "large-window" streams. Though it creates\r | |
324 | fragmentation (new builds decode streams that old builds don't),\r | |
325 | it is better from used experience perspective. */\r | |
326 | BrotliDecoderSetParameter(DecoderState, BROTLI_DECODER_PARAM_LARGE_WINDOW, 1u);\r | |
327 | \r | |
328 | AvailableIn = 0;\r | |
329 | NextIn = NULL;\r | |
330 | AvailableOut = kFileBufferSize;\r | |
331 | NextOut = Output;\r | |
332 | Result = BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT;\r | |
333 | for (;;) {\r | |
334 | if (Result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) {\r | |
335 | if (!HasMoreInput(InputFileHandle)) {\r | |
336 | printf("Corrupt input [%s]\n", InputFile);\r | |
337 | IsOk = BROTLI_FALSE;\r | |
338 | goto Finish;\r | |
339 | }\r | |
340 | AvailableIn = fread(Input, 1, kFileBufferSize, InputFileHandle);\r | |
341 | NextIn = Input;\r | |
342 | if (ferror(InputFileHandle)) {\r | |
343 | printf("Failed to read input [%s]\n", InputFile);\r | |
344 | IsOk = BROTLI_FALSE;\r | |
345 | goto Finish;\r | |
346 | }\r | |
347 | } else if (Result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {\r | |
348 | OutSize = (size_t) (NextOut - Output);\r | |
349 | if (OutSize > 0) {\r | |
350 | fwrite(Output, 1, OutSize, OutputFileHandle);\r | |
351 | if (ferror(OutputFileHandle)) {\r | |
352 | printf("Failed to write output [%s]\n", OutputFile);\r | |
353 | IsOk = BROTLI_FALSE;\r | |
354 | goto Finish;\r | |
355 | }\r | |
356 | }\r | |
357 | AvailableOut = kFileBufferSize;\r | |
358 | NextOut = Output;\r | |
359 | } else if (Result == BROTLI_DECODER_RESULT_SUCCESS) {\r | |
360 | OutSize = (size_t) (NextOut - Output);\r | |
361 | if (OutSize > 0) {\r | |
362 | fwrite(Output, 1, OutSize, OutputFileHandle);\r | |
363 | if (ferror(OutputFileHandle)) {\r | |
364 | printf("Failed to write output [%s]\n", OutputFile);\r | |
365 | IsOk = BROTLI_FALSE;\r | |
366 | goto Finish;\r | |
367 | }\r | |
368 | }\r | |
369 | AvailableOut = 0;\r | |
370 | if (AvailableIn != 0 || HasMoreInput(InputFileHandle)) {\r | |
371 | printf("Corrupt input [%s]\n", InputFile);\r | |
372 | IsOk = BROTLI_FALSE;\r | |
373 | goto Finish;\r | |
374 | }\r | |
375 | } else {\r | |
376 | printf("Corrupt input [%s]\n", InputFile);\r | |
377 | IsOk = BROTLI_FALSE;\r | |
378 | goto Finish;\r | |
379 | }\r | |
380 | if (!HasMoreInput(InputFileHandle) && Result == BROTLI_DECODER_RESULT_SUCCESS ) {\r | |
381 | break;\r | |
382 | }\r | |
383 | Result = BrotliDecoderDecompressStream(DecoderState, &AvailableIn, &NextIn, &AvailableOut, &NextOut, 0);\r | |
384 | }\r | |
385 | Finish:\r | |
386 | if (DecoderState) {\r | |
387 | BrotliDecoderDestroyInstance(DecoderState);\r | |
388 | }\r | |
389 | if (InputFileHandle) {\r | |
390 | fclose(InputFileHandle);\r | |
391 | }\r | |
392 | if (OutputFileHandle) {\r | |
393 | fclose(OutputFileHandle);\r | |
394 | }\r | |
395 | return IsOk;\r | |
396 | }\r | |
397 | \r | |
398 | int main(int argc, char** argv) {\r | |
399 | BROTLI_BOOL CompressBool;\r | |
400 | BROTLI_BOOL DecompressBool;\r | |
401 | char *OutputFile;\r | |
402 | char *InputFile;\r | |
403 | char OutputTmpFile[_MAX_PATH];\r | |
404 | FILE *OutputHandle;\r | |
405 | int Quality;\r | |
406 | int Gap;\r | |
407 | int OutputFileLength;\r | |
408 | int InputFileLength;\r | |
409 | int Ret;\r | |
410 | size_t InputFileSize;\r | |
411 | uint8_t *Buffer;\r | |
412 | uint8_t *InputBuffer;\r | |
413 | uint8_t *OutputBuffer;\r | |
414 | int64_t Size;\r | |
415 | \r | |
416 | InputFile = NULL;\r | |
417 | OutputFile = NULL;\r | |
418 | CompressBool = BROTLI_FALSE;\r | |
419 | DecompressBool = BROTLI_FALSE;\r | |
420 | //\r | |
421 | //Set default Quality and Gap\r | |
422 | //\r | |
423 | Quality = 9;\r | |
424 | Gap = 1;\r | |
425 | InputFileSize = 0;\r | |
426 | Ret = 0;\r | |
427 | \r | |
428 | if (argc < 2) {\r | |
429 | Usage();\r | |
430 | return 1;\r | |
431 | }\r | |
432 | if (strcmp(argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0 ) {\r | |
433 | Usage();\r | |
434 | return 0;\r | |
435 | }\r | |
436 | if (strcmp(argv[1], "-v") == 0 || strcmp (argv[1], "--version") == 0 ) {\r | |
437 | Version();\r | |
438 | return 0;\r | |
439 | }\r | |
440 | while (argc > 1) {\r | |
441 | if (strcmp(argv[1], "-e") == 0 || strcmp(argv[1], "--compress") == 0 ) {\r | |
442 | CompressBool = BROTLI_TRUE;\r | |
443 | if (DecompressBool) {\r | |
444 | printf("Can't use -e/--compress with -d/--decompess on the same time\n");\r | |
445 | return 1;\r | |
446 | }\r | |
447 | argc--;\r | |
448 | argv++;\r | |
449 | continue;\r | |
450 | }\r | |
451 | if (strcmp(argv[1], "-d") == 0 || strcmp(argv[1], "--decompress") == 0 ) {\r | |
452 | DecompressBool = BROTLI_TRUE;\r | |
453 | if (CompressBool) {\r | |
454 | printf("Can't use -e/--compress with -d/--decompess on the same time\n");\r | |
455 | return 1;\r | |
456 | }\r | |
457 | argc--;\r | |
458 | argv++;\r | |
459 | continue;\r | |
460 | }\r | |
461 | if (strcmp(argv[1], "-o") == 0 || strncmp(argv[1], "--output", 8) == 0) {\r | |
462 | if (strcmp(argv[1], "-o") == 0) {\r | |
463 | OutputFileLength = strlen(argv[2]);\r | |
464 | if (OutputFileLength > _MAX_PATH) {\r | |
465 | printf ("The file path %s is too long\n", argv[2]);\r | |
466 | return 1;\r | |
467 | }\r | |
468 | OutputFile = argv[2];\r | |
469 | if (OutputFile == NULL) {\r | |
470 | fprintf(stderr, "Input file can't be null\n");\r | |
471 | return 1;\r | |
472 | }\r | |
473 | argc--;\r | |
474 | argv++;\r | |
475 | } else {\r | |
476 | OutputFileLength = strlen(argv[1] - 9);\r | |
477 | OutputFile = (char *)argv[1] + 9;\r | |
478 | }\r | |
479 | argc--;\r | |
480 | argv++;\r | |
481 | continue;\r | |
482 | }\r | |
483 | if (strcmp(argv[1], "-q") == 0 || strncmp(argv[1], "--quality", 9) == 0) {\r | |
484 | if (strcmp(argv[1], "-q") == 0) {\r | |
485 | Quality = strtol(argv[2], NULL, 16);\r | |
486 | argc--;\r | |
487 | argv++;\r | |
488 | } else {\r | |
489 | Quality = strtol((char *)argv[1] + 10, NULL, 16);\r | |
490 | }\r | |
491 | argc--;\r | |
492 | argv++;\r | |
493 | continue;\r | |
494 | }\r | |
495 | if (strcmp(argv[1], "-g") == 0 || strncmp(argv[1], "--gap", 5) == 0) {\r | |
496 | if (strcmp(argv[1], "-g") == 0) {\r | |
497 | Gap = strtol(argv[2], NULL, 16);\r | |
498 | argc--;\r | |
499 | argv++;\r | |
500 | } else {\r | |
501 | Gap = strtol((char *)argv[1] + 6, NULL, 16);\r | |
502 | }\r | |
503 | argc--;\r | |
504 | argv++;\r | |
505 | continue;\r | |
506 | }\r | |
507 | if (argc > 1) {\r | |
508 | InputFileLength = strlen(argv[1]);\r | |
509 | if (InputFileLength > _MAX_PATH - 1) {\r | |
510 | printf ("The file path %s is too long\n", argv[2]);\r | |
511 | return 1;\r | |
512 | }\r | |
513 | InputFile = argv[1];\r | |
514 | if (InputFile == NULL) {\r | |
515 | printf("Input file can't be null\n");\r | |
516 | return 1;\r | |
517 | }\r | |
518 | argc--;\r | |
519 | argv++;\r | |
520 | }\r | |
521 | }\r | |
522 | \r | |
523 | Buffer = (uint8_t*)malloc(kFileBufferSize * 2);\r | |
524 | if (!Buffer) {\r | |
525 | printf("Out of memory\n");\r | |
526 | goto Finish;\r | |
527 | }\r | |
528 | memset(Buffer, 0, kFileBufferSize*2);\r | |
529 | InputBuffer = Buffer;\r | |
530 | OutputBuffer = Buffer + kFileBufferSize;\r | |
531 | if (CompressBool) {\r | |
532 | //\r | |
533 | // Compress file\r | |
534 | //\r | |
535 | Ret = CompressFile(InputFile, InputBuffer, OutputFile, OutputBuffer, Quality, Gap);\r | |
536 | if (!Ret) {\r | |
537 | printf ("Failed to compress file [%s]\n", InputFile);\r | |
538 | goto Finish;\r | |
539 | }\r | |
540 | //\r | |
541 | // Decompress file for get Outputfile size\r | |
542 | //\r | |
543 | strcpy (OutputTmpFile, OutputFile);\r | |
544 | if (strlen(InputFile) + strlen(".tmp") < _MAX_PATH) {\r | |
545 | strcat(OutputTmpFile, ".tmp");\r | |
546 | } else {\r | |
547 | printf ("Output file path is too long[%s]\n", OutputFile);\r | |
548 | Ret = BROTLI_FALSE;\r | |
549 | goto Finish;\r | |
550 | }\r | |
551 | memset(Buffer, 0, kFileBufferSize*2);\r | |
552 | Ret = DecompressFile(OutputFile, InputBuffer, OutputTmpFile, OutputBuffer, Quality, Gap);\r | |
553 | if (!Ret) {\r | |
554 | printf ("Failed to decompress file [%s]\n", OutputFile);\r | |
555 | goto Finish;\r | |
556 | }\r | |
557 | remove (OutputTmpFile);\r | |
558 | \r | |
559 | //\r | |
560 | // fill decoder header\r | |
561 | //\r | |
562 | InputFileSize = FileSize(InputFile);\r | |
563 | Size = (int64_t)InputFileSize;\r | |
564 | OutputHandle = fopen(OutputFile, "rb+"); /* open output_path file and add in head info */\r | |
565 | fwrite(&Size, 1, sizeof(int64_t), OutputHandle);\r | |
566 | ScratchBufferSize += Gap * GAP_MEM_BLOCK; /* there is a memory gap between IA32 and X64 environment*/\r | |
567 | ScratchBufferSize += kFileBufferSize * 2;\r | |
568 | Size = (int64_t) ScratchBufferSize;\r | |
569 | fwrite(&Size, 1, sizeof(int64_t), OutputHandle);\r | |
570 | if (fclose(OutputHandle) != 0) {\r | |
571 | printf("Failed to close output file [%s]\n", OutputFile);\r | |
572 | Ret = BROTLI_FALSE;\r | |
573 | goto Finish;\r | |
574 | }\r | |
575 | } else {\r | |
576 | Ret = DecompressFile(InputFile, InputBuffer, OutputFile, OutputBuffer, Quality, Gap);\r | |
577 | if (!Ret) {\r | |
578 | printf ("Failed to decompress file [%s]\n", InputFile);\r | |
579 | goto Finish;\r | |
580 | }\r | |
581 | }\r | |
582 | Finish:\r | |
583 | if (Buffer != NULL) {\r | |
584 | free (Buffer);\r | |
585 | }\r | |
586 | return !Ret;\r | |
587 | }\r |