Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(202)

Side by Side Diff: third_party/brotli/tools/bro.c

Issue 2537133002: Update brotli to v1.0.0-snapshot. (Closed)
Patch Set: Fixed typo Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/brotli/include/brotli/types.h ('k') | third_party/brotli/tools/bro.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* Copyright 2014 Google Inc. All Rights Reserved. 1 /* Copyright 2014 Google Inc. All Rights Reserved.
2 2
3 Distributed under MIT license. 3 Distributed under MIT license.
4 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 4 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5 */ 5 */
6 6
7 /* Example main() function for Brotli library. */ 7 /* Example main() function for Brotli library. */
8 8
9 #include <fcntl.h> 9 #include <fcntl.h>
10 #include <stdio.h> 10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
11 #include <sys/stat.h> 13 #include <sys/stat.h>
12 #include <sys/types.h> 14 #include <sys/types.h>
15 #include <time.h>
13 16
14 #include <cstdlib> 17 #include <brotli/decode.h>
15 #include <cstring> 18 #include <brotli/encode.h>
16 #include <ctime>
17 #include <string>
18
19 #include "../dec/decode.h"
20 #include "../enc/compressor.h"
21 19
22 #if !defined(_WIN32) 20 #if !defined(_WIN32)
23 #include <unistd.h> 21 #include <unistd.h>
22 #include <utime.h>
24 #else 23 #else
25 #include <io.h> 24 #include <io.h>
25 #include <share.h>
26 #include <sys/utime.h>
26 27
27 #define STDIN_FILENO _fileno(stdin) 28 #define MAKE_BINARY(FILENO) (_setmode((FILENO), _O_BINARY), (FILENO))
28 #define STDOUT_FILENO _fileno(stdout) 29
30 #if !defined(__MINGW32__)
31 #define STDIN_FILENO MAKE_BINARY(_fileno(stdin))
32 #define STDOUT_FILENO MAKE_BINARY(_fileno(stdout))
29 #define S_IRUSR S_IREAD 33 #define S_IRUSR S_IREAD
30 #define S_IWUSR S_IWRITE 34 #define S_IWUSR S_IWRITE
35 #endif
36
31 #define fdopen _fdopen 37 #define fdopen _fdopen
32 #define unlink _unlink 38 #define unlink _unlink
39 #define utimbuf _utimbuf
40 #define utime _utime
33 41
34 #define fopen ms_fopen 42 #define fopen ms_fopen
35 #define open ms_open 43 #define open ms_open
36 44
45 #define chmod(F, P) (0)
46 #define chown(F, O, G) (0)
47
37 #if defined(_MSC_VER) && (_MSC_VER >= 1400) 48 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
38 #define fseek _fseeki64 49 #define fseek _fseeki64
39 #define ftell _ftelli64 50 #define ftell _ftelli64
40 #endif 51 #endif
41 52
42 static inline FILE* ms_fopen(const char *filename, const char *mode) { 53 static FILE* ms_fopen(const char *filename, const char *mode) {
43 FILE* result = 0; 54 FILE* result = 0;
44 fopen_s(&result, filename, mode); 55 fopen_s(&result, filename, mode);
45 return result; 56 return result;
46 } 57 }
47 58
48 static inline int ms_open(const char *filename, int oflag, int pmode) { 59 static int ms_open(const char *filename, int oflag, int pmode) {
49 int result = -1; 60 int result = -1;
50 _sopen_s(&result, filename, oflag | O_BINARY, _SH_DENYNO, pmode); 61 _sopen_s(&result, filename, oflag | O_BINARY, _SH_DENYNO, pmode);
51 return result; 62 return result;
52 } 63 }
53 #endif /* WIN32 */ 64 #endif /* WIN32 */
54 65
55 66 static int ParseQuality(const char* s, int* quality) {
56 static bool ParseQuality(const char* s, int* quality) {
57 if (s[0] >= '0' && s[0] <= '9') { 67 if (s[0] >= '0' && s[0] <= '9') {
58 *quality = s[0] - '0'; 68 *quality = s[0] - '0';
59 if (s[1] >= '0' && s[1] <= '9') { 69 if (s[1] >= '0' && s[1] <= '9') {
60 *quality = *quality * 10 + s[1] - '0'; 70 *quality = *quality * 10 + s[1] - '0';
61 return s[2] == 0; 71 return (s[2] == 0) ? 1 : 0;
62 } 72 }
63 return s[1] == 0; 73 return (s[1] == 0) ? 1 : 0;
64 } 74 }
65 return false; 75 return 0;
66 } 76 }
67 77
68 static void ParseArgv(int argc, char **argv, 78 static void ParseArgv(int argc, char **argv,
69 char **input_path, 79 char **input_path,
70 char **output_path, 80 char **output_path,
81 char **dictionary_path,
71 int *force, 82 int *force,
72 int *quality, 83 int *quality,
73 int *decompress, 84 int *decompress,
74 int *repeat, 85 int *repeat,
75 int *verbose, 86 int *verbose,
76 int *lgwin) { 87 int *lgwin,
88 int *copy_stat) {
89 int k;
77 *force = 0; 90 *force = 0;
78 *input_path = 0; 91 *input_path = 0;
79 *output_path = 0; 92 *output_path = 0;
80 *repeat = 1; 93 *repeat = 1;
81 *verbose = 0; 94 *verbose = 0;
82 *lgwin = 22; 95 *lgwin = 22;
96 *copy_stat = 1;
83 { 97 {
84 size_t argv0_len = strlen(argv[0]); 98 size_t argv0_len = strlen(argv[0]);
85 *decompress = 99 *decompress =
86 argv0_len >= 5 && strcmp(&argv[0][argv0_len - 5], "unbro") == 0; 100 argv0_len >= 5 && strcmp(&argv[0][argv0_len - 5], "unbro") == 0;
87 } 101 }
88 for (int k = 1; k < argc; ++k) { 102 for (k = 1; k < argc; ++k) {
89 if (!strcmp("--force", argv[k]) || 103 if (!strcmp("--force", argv[k]) ||
90 !strcmp("-f", argv[k])) { 104 !strcmp("-f", argv[k])) {
91 if (*force != 0) { 105 if (*force != 0) {
92 goto error; 106 goto error;
93 } 107 }
94 *force = 1; 108 *force = 1;
95 continue; 109 continue;
96 } else if (!strcmp("--decompress", argv[k]) || 110 } else if (!strcmp("--decompress", argv[k]) ||
97 !strcmp("--uncompress", argv[k]) || 111 !strcmp("--uncompress", argv[k]) ||
98 !strcmp("-d", argv[k])) { 112 !strcmp("-d", argv[k])) {
99 *decompress = 1; 113 *decompress = 1;
100 continue; 114 continue;
101 } else if (!strcmp("--verbose", argv[k]) || 115 } else if (!strcmp("--verbose", argv[k]) ||
102 !strcmp("-v", argv[k])) { 116 !strcmp("-v", argv[k])) {
103 if (*verbose != 0) { 117 if (*verbose != 0) {
104 goto error; 118 goto error;
105 } 119 }
106 *verbose = 1; 120 *verbose = 1;
107 continue; 121 continue;
122 } else if (!strcmp("--no-copy-stat", argv[k])) {
123 if (*copy_stat == 0) {
124 goto error;
125 }
126 *copy_stat = 0;
127 continue;
108 } 128 }
109 if (k < argc - 1) { 129 if (k < argc - 1) {
110 if (!strcmp("--input", argv[k]) || 130 if (!strcmp("--input", argv[k]) ||
111 !strcmp("--in", argv[k]) || 131 !strcmp("--in", argv[k]) ||
112 !strcmp("-i", argv[k])) { 132 !strcmp("-i", argv[k])) {
113 if (*input_path != 0) { 133 if (*input_path != 0) {
114 goto error; 134 goto error;
115 } 135 }
116 *input_path = argv[k + 1]; 136 *input_path = argv[k + 1];
117 ++k; 137 ++k;
118 continue; 138 continue;
119 } else if (!strcmp("--output", argv[k]) || 139 } else if (!strcmp("--output", argv[k]) ||
120 !strcmp("--out", argv[k]) || 140 !strcmp("--out", argv[k]) ||
121 !strcmp("-o", argv[k])) { 141 !strcmp("-o", argv[k])) {
122 if (*output_path != 0) { 142 if (*output_path != 0) {
123 goto error; 143 goto error;
124 } 144 }
125 *output_path = argv[k + 1]; 145 *output_path = argv[k + 1];
126 ++k; 146 ++k;
127 continue; 147 continue;
148 } else if (!strcmp("--custom-dictionary", argv[k])) {
149 if (*dictionary_path != 0) {
150 goto error;
151 }
152 *dictionary_path = argv[k + 1];
153 ++k;
154 continue;
128 } else if (!strcmp("--quality", argv[k]) || 155 } else if (!strcmp("--quality", argv[k]) ||
129 !strcmp("-q", argv[k])) { 156 !strcmp("-q", argv[k])) {
130 if (!ParseQuality(argv[k + 1], quality)) { 157 if (!ParseQuality(argv[k + 1], quality)) {
131 goto error; 158 goto error;
132 } 159 }
133 ++k; 160 ++k;
134 continue; 161 continue;
135 } else if (!strcmp("--repeat", argv[k]) || 162 } else if (!strcmp("--repeat", argv[k]) ||
136 !strcmp("-r", argv[k])) { 163 !strcmp("-r", argv[k])) {
137 if (!ParseQuality(argv[k + 1], repeat)) { 164 if (!ParseQuality(argv[k + 1], repeat)) {
138 goto error; 165 goto error;
139 } 166 }
140 ++k; 167 ++k;
141 continue; 168 continue;
142 } else if (!strcmp("--window", argv[k]) || 169 } else if (!strcmp("--window", argv[k]) ||
143 !strcmp("-w", argv[k])) { 170 !strcmp("-w", argv[k])) {
144 if (!ParseQuality(argv[k + 1], lgwin)) { 171 if (!ParseQuality(argv[k + 1], lgwin)) {
145 goto error; 172 goto error;
146 } 173 }
147 if (*lgwin < 10 || *lgwin >= 25) { 174 if (*lgwin < 10 || *lgwin >= 25) {
148 goto error; 175 goto error;
149 } 176 }
150 ++k; 177 ++k;
151 continue; 178 continue;
152 } 179 }
153 } 180 }
154 goto error; 181 goto error;
155 } 182 }
156 return; 183 return;
157 error: 184 error:
158 fprintf(stderr, 185 fprintf(stderr,
159 "Usage: %s [--force] [--quality n] [--decompress]" 186 "Usage: %s [--force] [--quality n] [--decompress]"
160 " [--input filename] [--output filename] [--repeat iters]" 187 " [--input filename] [--output filename] [--repeat iters]"
161 " [--verbose] [--window n]\n", 188 " [--verbose] [--window n] [--custom-dictionary filename]"
189 " [--no-copy-stat]\n",
162 argv[0]); 190 argv[0]);
163 exit(1); 191 exit(1);
164 } 192 }
165 193
166 static FILE* OpenInputFile(const char* input_path) { 194 static FILE* OpenInputFile(const char* input_path) {
195 FILE* f;
167 if (input_path == 0) { 196 if (input_path == 0) {
168 return fdopen(STDIN_FILENO, "rb"); 197 return fdopen(STDIN_FILENO, "rb");
169 } 198 }
170 FILE* f = fopen(input_path, "rb"); 199 f = fopen(input_path, "rb");
171 if (f == 0) { 200 if (f == 0) {
172 perror("fopen"); 201 perror("fopen");
173 exit(1); 202 exit(1);
174 } 203 }
175 return f; 204 return f;
176 } 205 }
177 206
178 static FILE *OpenOutputFile(const char *output_path, const int force) { 207 static FILE *OpenOutputFile(const char *output_path, const int force) {
208 int fd;
179 if (output_path == 0) { 209 if (output_path == 0) {
180 return fdopen(STDOUT_FILENO, "wb"); 210 return fdopen(STDOUT_FILENO, "wb");
181 } 211 }
182 int excl = force ? 0 : O_EXCL; 212 fd = open(output_path, O_CREAT | (force ? 0 : O_EXCL) | O_WRONLY | O_TRUNC,
183 int fd = open(output_path, O_CREAT | excl | O_WRONLY | O_TRUNC, 213 S_IRUSR | S_IWUSR);
184 S_IRUSR | S_IWUSR);
185 if (fd < 0) { 214 if (fd < 0) {
186 if (!force) { 215 if (!force) {
187 struct stat statbuf; 216 struct stat statbuf;
188 if (stat(output_path, &statbuf) == 0) { 217 if (stat(output_path, &statbuf) == 0) {
189 fprintf(stderr, "output file exists\n"); 218 fprintf(stderr, "output file exists\n");
190 exit(1); 219 exit(1);
191 } 220 }
192 } 221 }
193 perror("open"); 222 perror("open");
194 exit(1); 223 exit(1);
195 } 224 }
196 return fdopen(fd, "wb"); 225 return fdopen(fd, "wb");
197 } 226 }
198 227
199 static int64_t FileSize(char *path) { 228 static int64_t FileSize(const char *path) {
200 FILE *f = fopen(path, "rb"); 229 FILE *f = fopen(path, "rb");
230 int64_t retval;
201 if (f == NULL) { 231 if (f == NULL) {
202 return -1; 232 return -1;
203 } 233 }
204 if (fseek(f, 0L, SEEK_END) != 0) { 234 if (fseek(f, 0L, SEEK_END) != 0) {
205 fclose(f); 235 fclose(f);
206 return -1; 236 return -1;
207 } 237 }
208 int64_t retval = ftell(f); 238 retval = ftell(f);
209 if (fclose(f) != 0) { 239 if (fclose(f) != 0) {
210 return -1; 240 return -1;
211 } 241 }
212 return retval; 242 return retval;
213 } 243 }
214 244
245 /* Copy file times and permissions.
246 TODO: this is a "best effort" implementation; honest cross-platform
247 fully featured implementation is way too hacky; add more hacks by request. */
248 static void CopyStat(const char* input_path, const char* output_path) {
249 struct stat statbuf;
250 struct utimbuf times;
251 int res;
252 if (input_path == 0 || output_path == 0) {
253 return;
254 }
255 if (stat(input_path, &statbuf) != 0) {
256 return;
257 }
258 times.actime = statbuf.st_atime;
259 times.modtime = statbuf.st_mtime;
260 utime(output_path, &times);
261 res = chmod(output_path, statbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
262 if (res != 0)
263 perror("chmod failed");
264 res = chown(output_path, (uid_t)-1, statbuf.st_gid);
265 if (res != 0)
266 perror("chown failed");
267 res = chown(output_path, statbuf.st_uid, (gid_t)-1);
268 if (res != 0)
269 perror("chown failed");
270 }
271
272 /* Result ownersip is passed to caller.
273 |*dictionary_size| is set to resulting buffer size. */
274 static uint8_t* ReadDictionary(const char* path, size_t* dictionary_size) {
275 static const int kMaxDictionarySize = (1 << 24) - 16;
276 FILE *f = fopen(path, "rb");
277 int64_t file_size_64;
278 uint8_t* buffer;
279 size_t bytes_read;
280
281 if (f == NULL) {
282 perror("fopen");
283 exit(1);
284 }
285
286 file_size_64 = FileSize(path);
287 if (file_size_64 == -1) {
288 fprintf(stderr, "could not get size of dictionary file");
289 exit(1);
290 }
291
292 if (file_size_64 > kMaxDictionarySize) {
293 fprintf(stderr, "dictionary is larger than maximum allowed: %d\n",
294 kMaxDictionarySize);
295 exit(1);
296 }
297 *dictionary_size = (size_t)file_size_64;
298
299 buffer = (uint8_t*)malloc(*dictionary_size);
300 if (!buffer) {
301 fprintf(stderr, "could not read dictionary: out of memory\n");
302 exit(1);
303 }
304 bytes_read = fread(buffer, sizeof(uint8_t), *dictionary_size, f);
305 if (bytes_read != *dictionary_size) {
306 fprintf(stderr, "could not read dictionary\n");
307 exit(1);
308 }
309 fclose(f);
310 return buffer;
311 }
312
215 static const size_t kFileBufferSize = 65536; 313 static const size_t kFileBufferSize = 65536;
216 314
217 static void Decompresss(FILE* fin, FILE* fout) { 315 static int Decompress(FILE* fin, FILE* fout, const char* dictionary_path) {
218 BrotliState* s = BrotliCreateState(NULL, NULL, NULL); 316 /* Dictionary should be kept during first rounds of decompression. */
219 if (!s) { 317 uint8_t* dictionary = NULL;
220 fprintf(stderr, "out of memory\n"); 318 uint8_t* input;
221 exit(1); 319 uint8_t* output;
222 }
223 uint8_t* input = new uint8_t[kFileBufferSize];
224 uint8_t* output = new uint8_t[kFileBufferSize];
225 size_t total_out;
226 size_t available_in; 320 size_t available_in;
227 const uint8_t* next_in; 321 const uint8_t* next_in;
228 size_t available_out = kFileBufferSize; 322 size_t available_out = kFileBufferSize;
229 uint8_t* next_out = output; 323 uint8_t* next_out;
230 BrotliResult result = BROTLI_RESULT_NEEDS_MORE_INPUT; 324 BrotliDecoderResult result = BROTLI_DECODER_RESULT_ERROR;
325 BrotliDecoderState* s = BrotliDecoderCreateInstance(NULL, NULL, NULL);
326 if (!s) {
327 fprintf(stderr, "out of memory\n");
328 return 0;
329 }
330 if (dictionary_path != NULL) {
331 size_t dictionary_size = 0;
332 dictionary = ReadDictionary(dictionary_path, &dictionary_size);
333 BrotliDecoderSetCustomDictionary(s, dictionary_size, dictionary);
334 }
335 input = (uint8_t*)malloc(kFileBufferSize);
336 output = (uint8_t*)malloc(kFileBufferSize);
337 if (!input || !output) {
338 fprintf(stderr, "out of memory\n");
339 goto end;
340 }
341 next_out = output;
342 result = BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT;
231 while (1) { 343 while (1) {
232 if (result == BROTLI_RESULT_NEEDS_MORE_INPUT) { 344 if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) {
233 if (feof(fin)) { 345 if (feof(fin)) {
234 break; 346 break;
235 } 347 }
236 available_in = fread(input, 1, kFileBufferSize, fin); 348 available_in = fread(input, 1, kFileBufferSize, fin);
237 next_in = input; 349 next_in = input;
238 if (ferror(fin)) { 350 if (ferror(fin)) {
239 break; 351 break;
240 } 352 }
241 } else if (result == BROTLI_RESULT_NEEDS_MORE_OUTPUT) { 353 } else if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
242 fwrite(output, 1, kFileBufferSize, fout); 354 fwrite(output, 1, kFileBufferSize, fout);
243 if (ferror(fout)) { 355 if (ferror(fout)) {
244 break; 356 break;
245 } 357 }
246 available_out = kFileBufferSize; 358 available_out = kFileBufferSize;
247 next_out = output; 359 next_out = output;
248 } else { 360 } else {
249 break; /* Error or success. */ 361 break; /* Error or success. */
250 } 362 }
251 result = BrotliDecompressStream(&available_in, &next_in, 363 result = BrotliDecoderDecompressStream(
252 &available_out, &next_out, &total_out, s); 364 s, &available_in, &next_in, &available_out, &next_out, 0);
253 } 365 }
254 if (next_out != output) { 366 if (next_out != output) {
255 fwrite(output, 1, static_cast<size_t>(next_out - output), fout); 367 fwrite(output, 1, (size_t)(next_out - output), fout);
256 } 368 }
257 delete[] input; 369
258 delete[] output; 370 if ((result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) || ferror(fout)) {
259 BrotliDestroyState(s);
260 if ((result == BROTLI_RESULT_NEEDS_MORE_OUTPUT) || ferror(fout)) {
261 fprintf(stderr, "failed to write output\n"); 371 fprintf(stderr, "failed to write output\n");
262 exit(1); 372 } else if (result != BROTLI_DECODER_RESULT_SUCCESS) {
263 } else if (result != BROTLI_RESULT_SUCCESS) { /* Error or needs more input. */ 373 /* Error or needs more input. */
264 fprintf(stderr, "corrupt input\n"); 374 fprintf(stderr, "corrupt input\n");
265 exit(1);
266 } 375 }
376
377 end:
378 free(dictionary);
379 free(input);
380 free(output);
381 BrotliDecoderDestroyInstance(s);
382 return (result == BROTLI_DECODER_RESULT_SUCCESS) ? 1 : 0;
383 }
384
385 static int Compress(int quality, int lgwin, FILE* fin, FILE* fout,
386 const char *dictionary_path) {
387 BrotliEncoderState* s = BrotliEncoderCreateInstance(0, 0, 0);
388 uint8_t* buffer = (uint8_t*)malloc(kFileBufferSize << 1);
389 uint8_t* input = buffer;
390 uint8_t* output = buffer + kFileBufferSize;
391 size_t available_in = 0;
392 const uint8_t* next_in = NULL;
393 size_t available_out = kFileBufferSize;
394 uint8_t* next_out = output;
395 int is_eof = 0;
396 int is_ok = 1;
397
398 if (!s || !buffer) {
399 is_ok = 0;
400 goto finish;
401 }
402
403 BrotliEncoderSetParameter(s, BROTLI_PARAM_QUALITY, (uint32_t)quality);
404 BrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, (uint32_t)lgwin);
405 if (dictionary_path != NULL) {
406 size_t dictionary_size = 0;
407 uint8_t* dictionary = ReadDictionary(dictionary_path, &dictionary_size);
408 BrotliEncoderSetCustomDictionary(s, dictionary_size, dictionary);
409 free(dictionary);
410 }
411
412 while (1) {
413 if (available_in == 0 && !is_eof) {
414 available_in = fread(input, 1, kFileBufferSize, fin);
415 next_in = input;
416 if (ferror(fin)) break;
417 is_eof = feof(fin);
418 }
419
420 if (!BrotliEncoderCompressStream(s,
421 is_eof ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS,
422 &available_in, &next_in, &available_out, &next_out, NULL)) {
423 is_ok = 0;
424 break;
425 }
426
427 if (available_out != kFileBufferSize) {
428 size_t out_size = kFileBufferSize - available_out;
429 fwrite(output, 1, out_size, fout);
430 if (ferror(fout)) break;
431 available_out = kFileBufferSize;
432 next_out = output;
433 }
434
435 if (BrotliEncoderIsFinished(s)) break;
436 }
437
438 finish:
439 free(buffer);
440 BrotliEncoderDestroyInstance(s);
441
442 if (!is_ok) {
443 /* Should detect OOM? */
444 fprintf(stderr, "failed to compress data\n");
445 return 0;
446 } else if (ferror(fout)) {
447 fprintf(stderr, "failed to write output\n");
448 return 0;
449 } else if (ferror(fin)) {
450 fprintf(stderr, "failed to read input\n");
451 return 0;
452 }
453 return 1;
267 } 454 }
268 455
269 int main(int argc, char** argv) { 456 int main(int argc, char** argv) {
270 char *input_path = 0; 457 char *input_path = 0;
271 char *output_path = 0; 458 char *output_path = 0;
459 char *dictionary_path = 0;
272 int force = 0; 460 int force = 0;
273 int quality = 11; 461 int quality = 11;
274 int decompress = 0; 462 int decompress = 0;
275 int repeat = 1; 463 int repeat = 1;
276 int verbose = 0; 464 int verbose = 0;
277 int lgwin = 0; 465 int lgwin = 0;
278 ParseArgv(argc, argv, &input_path, &output_path, &force, 466 int copy_stat = 1;
279 &quality, &decompress, &repeat, &verbose, &lgwin); 467 clock_t clock_start;
280 const clock_t clock_start = clock(); 468 int i;
281 for (int i = 0; i < repeat; ++i) { 469 ParseArgv(argc, argv, &input_path, &output_path, &dictionary_path, &force,
470 &quality, &decompress, &repeat, &verbose, &lgwin, &copy_stat);
471 clock_start = clock();
472 for (i = 0; i < repeat; ++i) {
282 FILE* fin = OpenInputFile(input_path); 473 FILE* fin = OpenInputFile(input_path);
283 FILE* fout = OpenOutputFile(output_path, force); 474 FILE* fout = OpenOutputFile(output_path, force || (repeat > 1));
475 int is_ok = 0;
284 if (decompress) { 476 if (decompress) {
285 Decompresss(fin, fout); 477 is_ok = Decompress(fin, fout, dictionary_path);
286 } else { 478 } else {
287 brotli::BrotliParams params; 479 is_ok = Compress(quality, lgwin, fin, fout, dictionary_path);
288 params.lgwin = lgwin;
289 params.quality = quality;
290 brotli::BrotliFileIn in(fin, 1 << 16);
291 brotli::BrotliFileOut out(fout);
292 if (!BrotliCompress(params, &in, &out)) {
293 fprintf(stderr, "compression failed\n");
294 unlink(output_path);
295 exit(1);
296 }
297 } 480 }
298 if (fclose(fin) != 0) { 481 if (!is_ok) {
299 perror("fclose"); 482 unlink(output_path);
300 exit(1); 483 exit(1);
301 } 484 }
302 if (fclose(fout) != 0) { 485 if (fclose(fout) != 0) {
303 perror("fclose"); 486 perror("fclose");
304 exit(1); 487 exit(1);
305 } 488 }
489 /* TOCTOU violation, but otherwise it is impossible to set file times. */
490 if (copy_stat && (i + 1 == repeat)) {
491 CopyStat(input_path, output_path);
492 }
493 if (fclose(fin) != 0) {
494 perror("fclose");
495 exit(1);
496 }
306 } 497 }
307 if (verbose) { 498 if (verbose) {
308 const clock_t clock_end = clock(); 499 clock_t clock_end = clock();
309 double duration = 500 double duration = (double)(clock_end - clock_start) / CLOCKS_PER_SEC;
310 static_cast<double>(clock_end - clock_start) / CLOCKS_PER_SEC; 501 int64_t uncompressed_size;
502 double uncompressed_bytes_in_MB;
311 if (duration < 1e-9) { 503 if (duration < 1e-9) {
312 duration = 1e-9; 504 duration = 1e-9;
313 } 505 }
314 int64_t uncompressed_size = FileSize(decompress ? output_path : input_path); 506 uncompressed_size = FileSize(decompress ? output_path : input_path);
315 if (uncompressed_size == -1) { 507 if (uncompressed_size == -1) {
316 fprintf(stderr, "failed to determine uncompressed file size\n"); 508 fprintf(stderr, "failed to determine uncompressed file size\n");
317 exit(1); 509 exit(1);
318 } 510 }
319 double uncompressed_bytes_in_MB = 511 uncompressed_bytes_in_MB =
320 static_cast<double>(repeat * uncompressed_size) / (1024.0 * 1024.0); 512 (double)(repeat * uncompressed_size) / (1024.0 * 1024.0);
321 if (decompress) { 513 if (decompress) {
322 printf("Brotli decompression speed: "); 514 printf("Brotli decompression speed: ");
323 } else { 515 } else {
324 printf("Brotli compression speed: "); 516 printf("Brotli compression speed: ");
325 } 517 }
326 printf("%g MB/s\n", uncompressed_bytes_in_MB / duration); 518 printf("%g MB/s\n", uncompressed_bytes_in_MB / duration);
327 } 519 }
328 return 0; 520 return 0;
329 } 521 }
OLDNEW
« no previous file with comments | « third_party/brotli/include/brotli/types.h ('k') | third_party/brotli/tools/bro.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698