/root/doris/be/src/util/zlib.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #include "util/zlib.h" |
19 | | |
20 | | #include <butil/macros.h> |
21 | | #include <zlib.h> |
22 | | |
23 | | #include <cstring> |
24 | | #include <memory> |
25 | | #include <ostream> |
26 | | #include <string> |
27 | | |
28 | | using std::ostream; |
29 | | using std::string; |
30 | | |
31 | 8 | #define ZRETURN_NOT_OK(call) RETURN_IF_ERROR(ZlibResultToStatus(call)) |
32 | | |
33 | | namespace doris { |
34 | | using namespace ErrorCode; |
35 | | namespace zlib { |
36 | | |
37 | | namespace { |
38 | 16 | Status ZlibResultToStatus(int rc) { |
39 | 16 | switch (rc) { |
40 | 10 | case Z_OK: |
41 | 10 | return Status::OK(); |
42 | 6 | case Z_STREAM_END: |
43 | 6 | return Status::EndOfFile("zlib EOF"); |
44 | 0 | case Z_NEED_DICT: |
45 | 0 | return Status::Corruption("zlib error: NEED_DICT"); |
46 | 0 | case Z_ERRNO: |
47 | 0 | return Status::IOError("zlib error: Z_ERRNO"); |
48 | 0 | case Z_STREAM_ERROR: |
49 | 0 | return Status::Corruption("zlib error: STREAM_ERROR"); |
50 | 0 | case Z_DATA_ERROR: |
51 | 0 | return Status::Corruption("zlib error: DATA_ERROR"); |
52 | 0 | case Z_MEM_ERROR: |
53 | 0 | return Status::RuntimeError("zlib error: MEM_ERROR"); |
54 | 0 | case Z_BUF_ERROR: |
55 | 0 | return Status::RuntimeError("zlib error: BUF_ERROR"); |
56 | 0 | case Z_VERSION_ERROR: |
57 | 0 | return Status::RuntimeError("zlib error: VERSION_ERROR"); |
58 | 0 | default: |
59 | 0 | return Status::RuntimeError("zlib error: unknown error {}", rc); |
60 | 16 | } |
61 | 16 | } |
62 | | } // anonymous namespace |
63 | | |
64 | 0 | Status Compress(Slice input, ostream* out) { |
65 | 0 | return CompressLevel(input, Z_DEFAULT_COMPRESSION, out); |
66 | 0 | } |
67 | | |
68 | 2 | Status CompressLevel(Slice input, int level, ostream* out) { |
69 | 2 | z_stream zs; |
70 | 2 | memset(&zs, 0, sizeof(zs)); |
71 | 2 | ZRETURN_NOT_OK(deflateInit2(&zs, level, Z_DEFLATED, 15 + 16 /* 15 window bits, enable gzip */, |
72 | 2 | 8 /* memory level, max is 9 */, Z_DEFAULT_STRATEGY)); |
73 | | |
74 | 2 | zs.avail_in = input.get_size(); |
75 | 2 | zs.next_in = (unsigned char*)(input.mutable_data()); |
76 | 2 | const int kChunkSize = 256 * 1024; |
77 | 2 | std::unique_ptr<unsigned char[]> chunk(new unsigned char[kChunkSize]); |
78 | 2 | int flush; |
79 | 4 | do { |
80 | 4 | zs.avail_out = kChunkSize; |
81 | 4 | zs.next_out = chunk.get(); |
82 | 4 | flush = (zs.avail_in == 0) ? Z_FINISH : Z_NO_FLUSH; |
83 | 4 | Status s = ZlibResultToStatus(deflate(&zs, flush)); |
84 | 4 | if (!s.ok() && !s.is<END_OF_FILE>()) { |
85 | 0 | return s; |
86 | 0 | } |
87 | 4 | int out_size = zs.next_out - chunk.get(); |
88 | 4 | if (out_size > 0) { |
89 | 4 | out->write(reinterpret_cast<char*>(chunk.get()), out_size); |
90 | 4 | } |
91 | 4 | } while (flush != Z_FINISH); |
92 | 2 | ZRETURN_NOT_OK(deflateEnd(&zs)); |
93 | 2 | return Status::OK(); |
94 | 2 | } |
95 | | |
96 | 2 | Status Uncompress(Slice compressed, std::ostream* out) { |
97 | 2 | z_stream zs; |
98 | 2 | memset(&zs, 0, sizeof(zs)); |
99 | 2 | zs.next_in = (unsigned char*)(compressed.mutable_data()); |
100 | 2 | zs.avail_in = compressed.get_size(); |
101 | 2 | ZRETURN_NOT_OK(inflateInit2(&zs, 15 + 16 /* 15 window bits, enable zlib */)); |
102 | 2 | int flush; |
103 | 2 | Status s; |
104 | 4 | do { |
105 | 4 | unsigned char buf[4096]; |
106 | 4 | zs.next_out = buf; |
107 | 4 | zs.avail_out = arraysize(buf); |
108 | 4 | flush = zs.avail_in > 0 ? Z_NO_FLUSH : Z_FINISH; |
109 | 4 | s = ZlibResultToStatus(inflate(&zs, flush)); |
110 | 4 | if (!s.ok() && !s.is<END_OF_FILE>()) { |
111 | 0 | return s; |
112 | 0 | } |
113 | 4 | out->write(reinterpret_cast<char*>(buf), zs.next_out - buf); |
114 | 4 | } while (flush == Z_NO_FLUSH); |
115 | 2 | ZRETURN_NOT_OK(inflateEnd(&zs)); |
116 | | |
117 | 2 | return Status::OK(); |
118 | 2 | } |
119 | | |
120 | | } // namespace zlib |
121 | | } // namespace doris |