OLD | NEW |
| (Empty) |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/metrics/compression_utils.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "base/basictypes.h" | |
10 #include "third_party/zlib/zlib.h" | |
11 | |
12 namespace { | |
13 | |
14 // The difference in bytes between a zlib header and a gzip header. | |
15 const size_t kGzipZlibHeaderDifferenceBytes = 16; | |
16 | |
17 // Pass an integer greater than the following get a gzip header instead of a | |
18 // zlib header when calling deflateInit2_. | |
19 const int kWindowBitsToGetGzipHeader = 16; | |
20 | |
21 // This describes the amount of memory zlib uses to compress data. It can go | |
22 // from 1 to 9, with 8 being the default. For details, see: | |
23 // http://www.zlib.net/manual.html (search for memLevel). | |
24 const int kZlibMemoryLevel = 8; | |
25 | |
26 // This code is taken almost verbatim from third_party/zlib/compress.c. The only | |
27 // difference is deflateInit2_ is called which sets the window bits to be > 16. | |
28 // That causes a gzip header to be emitted rather than a zlib header. | |
29 int GzipCompressHelper(Bytef* dest, | |
30 uLongf* dest_length, | |
31 const Bytef* source, | |
32 uLong source_length) { | |
33 z_stream stream; | |
34 | |
35 stream.next_in = bit_cast<Bytef*>(source); | |
36 stream.avail_in = static_cast<uInt>(source_length); | |
37 stream.next_out = dest; | |
38 stream.avail_out = static_cast<uInt>(*dest_length); | |
39 if (static_cast<uLong>(stream.avail_out) != *dest_length) | |
40 return Z_BUF_ERROR; | |
41 | |
42 stream.zalloc = static_cast<alloc_func>(0); | |
43 stream.zfree = static_cast<free_func>(0); | |
44 stream.opaque = static_cast<voidpf>(0); | |
45 | |
46 gz_header gzip_header; | |
47 memset(&gzip_header, 0, sizeof(gzip_header)); | |
48 int err = deflateInit2_(&stream, | |
49 Z_DEFAULT_COMPRESSION, | |
50 Z_DEFLATED, | |
51 MAX_WBITS + kWindowBitsToGetGzipHeader, | |
52 kZlibMemoryLevel, | |
53 Z_DEFAULT_STRATEGY, | |
54 ZLIB_VERSION, | |
55 sizeof(z_stream)); | |
56 if (err != Z_OK) | |
57 return err; | |
58 | |
59 err = deflateSetHeader(&stream, &gzip_header); | |
60 if (err != Z_OK) | |
61 return err; | |
62 | |
63 err = deflate(&stream, Z_FINISH); | |
64 if (err != Z_STREAM_END) { | |
65 deflateEnd(&stream); | |
66 return err == Z_OK ? Z_BUF_ERROR : err; | |
67 } | |
68 *dest_length = stream.total_out; | |
69 | |
70 err = deflateEnd(&stream); | |
71 return err; | |
72 } | |
73 } // namespace | |
74 | |
75 namespace chrome { | |
76 | |
77 bool GzipCompress(const std::string& input, std::string* output) { | |
78 std::vector<Bytef> compressed_data(kGzipZlibHeaderDifferenceBytes + | |
79 compressBound(input.size())); | |
80 | |
81 uLongf compressed_size = compressed_data.size(); | |
82 if (GzipCompressHelper(&compressed_data.front(), | |
83 &compressed_size, | |
84 bit_cast<const Bytef*>(input.data()), | |
85 input.size()) != Z_OK) | |
86 return false; | |
87 | |
88 compressed_data.resize(compressed_size); | |
89 output->assign(compressed_data.begin(), compressed_data.end()); | |
90 return true; | |
91 } | |
92 } // namespace chrome | |
OLD | NEW |