1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "CompressionEngine.h"
18
19 #include <limits>
20
21 #include <android-base/logging.h>
22 #include <zlib.h>
23 #include <zstd.h>
24
GetInstance()25 CompressionEngine& CompressionEngine::GetInstance() {
26 static CompressionEngine* engine = new ZstdCompressionEngine();
27 return *engine;
28 }
29
Compress(SerializedData & in,size_t data_length,SerializedData & out)30 bool ZlibCompressionEngine::Compress(SerializedData& in, size_t data_length, SerializedData& out) {
31 z_stream strm;
32 strm.zalloc = Z_NULL;
33 strm.zfree = Z_NULL;
34 strm.opaque = Z_NULL;
35 int ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION);
36 if (ret != Z_OK) {
37 LOG(FATAL) << "deflateInit() failed";
38 }
39
40 CHECK_LE(data_length, in.size());
41 CHECK_LE(in.size(), std::numeric_limits<uint32_t>::max());
42 uint32_t deflate_bound = deflateBound(&strm, in.size());
43
44 out.Resize(deflate_bound);
45
46 strm.avail_in = data_length;
47 strm.next_in = in.data();
48 strm.avail_out = out.size();
49 strm.next_out = out.data();
50 ret = deflate(&strm, Z_FINISH);
51 CHECK_EQ(ret, Z_STREAM_END);
52
53 uint32_t compressed_size = strm.total_out;
54 deflateEnd(&strm);
55
56 out.Resize(compressed_size);
57
58 return true;
59 }
60
Decompress(SerializedData & in,SerializedData & out)61 bool ZlibCompressionEngine::Decompress(SerializedData& in, SerializedData& out) {
62 z_stream strm;
63 strm.zalloc = Z_NULL;
64 strm.zfree = Z_NULL;
65 strm.opaque = Z_NULL;
66 strm.avail_in = in.size();
67 strm.next_in = in.data();
68 strm.avail_out = out.size();
69 strm.next_out = out.data();
70
71 inflateInit(&strm);
72 int ret = inflate(&strm, Z_NO_FLUSH);
73
74 CHECK_EQ(strm.avail_in, 0U);
75 CHECK_EQ(strm.avail_out, 0U);
76 CHECK_EQ(ret, Z_STREAM_END);
77 inflateEnd(&strm);
78
79 return true;
80 }
81
Compress(SerializedData & in,size_t data_length,SerializedData & out)82 bool ZstdCompressionEngine::Compress(SerializedData& in, size_t data_length, SerializedData& out) {
83 CHECK_LE(data_length, in.size());
84
85 size_t compress_bound = ZSTD_compressBound(data_length);
86 out.Resize(compress_bound);
87
88 size_t out_size = ZSTD_compress(out.data(), out.size(), in.data(), data_length, 1);
89 if (ZSTD_isError(out_size)) {
90 LOG(FATAL) << "ZSTD_compress failed: " << ZSTD_getErrorName(out_size);
91 }
92 out.Resize(out_size);
93
94 return true;
95 }
96
Decompress(SerializedData & in,SerializedData & out)97 bool ZstdCompressionEngine::Decompress(SerializedData& in, SerializedData& out) {
98 size_t result = ZSTD_decompress(out.data(), out.size(), in.data(), in.size());
99 if (ZSTD_isError(result)) {
100 LOG(FATAL) << "ZSTD_decompress failed: " << ZSTD_getErrorName(result);
101 }
102 CHECK_EQ(result, out.size());
103 return true;
104 }
105