Coverage Report

Created: 2024-11-21 23:52

/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