1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
6 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
10 #include "port/win/xpress_win.h"
20 // Put this under ifdef so windows systems w/o this
22 #include <compressapi.h>
31 auto CloseCompressorFun
= [](void* h
) {
33 ::CloseCompressor(reinterpret_cast<COMPRESSOR_HANDLE
>(h
));
37 auto CloseDecompressorFun
= [](void* h
) {
39 ::CloseDecompressor(reinterpret_cast<DECOMPRESSOR_HANDLE
>(h
));
44 bool Compress(const char* input
, size_t length
, std::string
* output
) {
46 assert(input
!= nullptr);
47 assert(output
!= nullptr);
54 COMPRESS_ALLOCATION_ROUTINES
* allocRoutinesPtr
= nullptr;
56 COMPRESSOR_HANDLE compressor
= NULL
;
58 BOOL success
= CreateCompressor(
59 COMPRESS_ALGORITHM_XPRESS
, // Compression Algorithm
60 allocRoutinesPtr
, // Optional allocation routine
61 &compressor
); // Handle
65 std::cerr
<< "XPRESS: Failed to create Compressor LastError: " <<
66 GetLastError() << std::endl
;
71 std::unique_ptr
<void, decltype(CloseCompressorFun
)>
72 compressorGuard(compressor
, CloseCompressorFun
);
74 SIZE_T compressedBufferSize
= 0;
76 // Query compressed buffer size.
78 compressor
, // Compressor Handle
79 const_cast<char*>(input
), // Input buffer
80 length
, // Uncompressed data size
81 NULL
, // Compressed Buffer
82 0, // Compressed Buffer size
83 &compressedBufferSize
); // Compressed Data size
87 auto lastError
= GetLastError();
89 if (lastError
!= ERROR_INSUFFICIENT_BUFFER
) {
92 "XPRESS: Failed to estimate compressed buffer size LastError " <<
93 lastError
<< std::endl
;
99 assert(compressedBufferSize
> 0);
102 result
.resize(compressedBufferSize
);
104 SIZE_T compressedDataSize
= 0;
107 success
= ::Compress(
108 compressor
, // Compressor Handle
109 const_cast<char*>(input
), // Input buffer
110 length
, // Uncompressed data size
111 &result
[0], // Compressed Buffer
112 compressedBufferSize
, // Compressed Buffer size
113 &compressedDataSize
); // Compressed Data size
117 std::cerr
<< "XPRESS: Failed to compress LastError " <<
118 GetLastError() << std::endl
;
123 result
.resize(compressedDataSize
);
124 output
->swap(result
);
129 char* Decompress(const char* input_data
, size_t input_length
,
130 int* decompress_size
) {
132 assert(input_data
!= nullptr);
133 assert(decompress_size
!= nullptr);
135 if (input_length
== 0) {
139 COMPRESS_ALLOCATION_ROUTINES
* allocRoutinesPtr
= nullptr;
141 DECOMPRESSOR_HANDLE decompressor
= NULL
;
143 BOOL success
= CreateDecompressor(
144 COMPRESS_ALGORITHM_XPRESS
, // Compression Algorithm
145 allocRoutinesPtr
, // Optional allocation routine
146 &decompressor
); // Handle
151 std::cerr
<< "XPRESS: Failed to create Decompressor LastError "
152 << GetLastError() << std::endl
;
157 std::unique_ptr
<void, decltype(CloseDecompressorFun
)>
158 compressorGuard(decompressor
, CloseDecompressorFun
);
160 SIZE_T decompressedBufferSize
= 0;
162 success
= ::Decompress(
163 decompressor
, // Compressor Handle
164 const_cast<char*>(input_data
), // Compressed data
165 input_length
, // Compressed data size
166 NULL
, // Buffer set to NULL
167 0, // Buffer size set to 0
168 &decompressedBufferSize
); // Decompressed Data size
172 auto lastError
= GetLastError();
174 if (lastError
!= ERROR_INSUFFICIENT_BUFFER
) {
177 << "XPRESS: Failed to estimate decompressed buffer size LastError "
178 << lastError
<< std::endl
;
184 assert(decompressedBufferSize
> 0);
186 // On Windows we are limited to a 32-bit int for the
187 // output data size argument
188 // so we hopefully never get here
189 if (decompressedBufferSize
> std::numeric_limits
<int>::max()) {
194 // The callers are deallocating using delete[]
195 // thus we must allocate with new[]
196 std::unique_ptr
<char[]> outputBuffer(new char[decompressedBufferSize
]);
198 SIZE_T decompressedDataSize
= 0;
200 success
= ::Decompress(
202 const_cast<char*>(input_data
),
205 decompressedBufferSize
,
206 &decompressedDataSize
);
211 "XPRESS: Failed to decompress LastError " <<
212 GetLastError() << std::endl
;
217 *decompress_size
= static_cast<int>(decompressedDataSize
);
219 // Return the raw buffer to the caller supporting the tradition
220 return outputBuffer
.release();