Coverage Report

Created: 2025-04-23 23:23

/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
8
#define ZRETURN_NOT_OK(call) RETURN_IF_ERROR(ZlibResultToStatus(call))
29
30
namespace doris {
31
using namespace ErrorCode;
32
namespace zlib {
33
34
namespace {
35
16
Status ZlibResultToStatus(int rc) {
36
16
    switch (rc) {
37
10
    case Z_OK:
38
10
        return Status::OK();
39
6
    case Z_STREAM_END:
40
6
        return Status::EndOfFile("zlib EOF");
41
0
    case Z_NEED_DICT:
42
0
        return Status::Corruption("zlib error: NEED_DICT");
43
0
    case Z_ERRNO:
44
0
        return Status::IOError("zlib error: Z_ERRNO");
45
0
    case Z_STREAM_ERROR:
46
0
        return Status::Corruption("zlib error: STREAM_ERROR");
47
0
    case Z_DATA_ERROR:
48
0
        return Status::Corruption("zlib error: DATA_ERROR");
49
0
    case Z_MEM_ERROR:
50
0
        return Status::RuntimeError("zlib error: MEM_ERROR");
51
0
    case Z_BUF_ERROR:
52
0
        return Status::RuntimeError("zlib error: BUF_ERROR");
53
0
    case Z_VERSION_ERROR:
54
0
        return Status::RuntimeError("zlib error: VERSION_ERROR");
55
0
    default:
56
0
        return Status::RuntimeError("zlib error: unknown error {}", rc);
57
16
    }
58
16
}
59
} // anonymous namespace
60
61
0
Status Compress(Slice input, std::ostream* out) {
62
0
    return CompressLevel(input, Z_DEFAULT_COMPRESSION, out);
63
0
}
64
65
2
Status CompressLevel(Slice input, int level, std::ostream* out) {
66
2
    z_stream zs;
67
2
    memset(&zs, 0, sizeof(zs));
68
2
    ZRETURN_NOT_OK(deflateInit2(&zs, level, Z_DEFLATED, 15 + 16 /* 15 window bits, enable gzip */,
69
2
                                8 /* memory level, max is 9 */, Z_DEFAULT_STRATEGY));
70
71
2
    zs.avail_in = input.get_size();
72
2
    zs.next_in = (unsigned char*)(input.mutable_data());
73
2
    const int kChunkSize = 256 * 1024;
74
2
    std::unique_ptr<unsigned char[]> chunk(new unsigned char[kChunkSize]);
75
2
    int flush;
76
4
    do {
77
4
        zs.avail_out = kChunkSize;
78
4
        zs.next_out = chunk.get();
79
4
        flush = (zs.avail_in == 0) ? Z_FINISH : Z_NO_FLUSH;
80
4
        Status s = ZlibResultToStatus(deflate(&zs, flush));
81
4
        if (!s.ok() && !s.is<END_OF_FILE>()) {
82
0
            return s;
83
0
        }
84
4
        int out_size = zs.next_out - chunk.get();
85
4
        if (out_size > 0) {
86
4
            out->write(reinterpret_cast<char*>(chunk.get()), out_size);
87
4
        }
88
4
    } while (flush != Z_FINISH);
89
2
    ZRETURN_NOT_OK(deflateEnd(&zs));
90
2
    return Status::OK();
91
2
}
92
93
2
Status Uncompress(Slice compressed, std::ostream* out) {
94
2
    z_stream zs;
95
2
    memset(&zs, 0, sizeof(zs));
96
2
    zs.next_in = (unsigned char*)(compressed.mutable_data());
97
2
    zs.avail_in = compressed.get_size();
98
2
    ZRETURN_NOT_OK(inflateInit2(&zs, 15 + 16 /* 15 window bits, enable zlib */));
99
2
    int flush;
100
2
    Status s;
101
4
    do {
102
4
        unsigned char buf[4096];
103
4
        zs.next_out = buf;
104
4
        zs.avail_out = arraysize(buf);
105
4
        flush = zs.avail_in > 0 ? Z_NO_FLUSH : Z_FINISH;
106
4
        s = ZlibResultToStatus(inflate(&zs, flush));
107
4
        if (!s.ok() && !s.is<END_OF_FILE>()) {
108
0
            return s;
109
0
        }
110
4
        out->write(reinterpret_cast<char*>(buf), zs.next_out - buf);
111
4
    } while (flush == Z_NO_FLUSH);
112
2
    ZRETURN_NOT_OK(inflateEnd(&zs));
113
114
2
    return Status::OK();
115
2
}
116
117
} // namespace zlib
118
} // namespace doris