koffi 2.3.10-beta.2 → 2.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/build/2.3.10/koffi_darwin_arm64/koffi.node +0 -0
- package/build/2.3.10/koffi_darwin_x64/koffi.node +0 -0
- package/build/2.3.10/koffi_freebsd_arm64/koffi.node +0 -0
- package/build/2.3.10/koffi_freebsd_ia32/koffi.node +0 -0
- package/build/2.3.10/koffi_freebsd_x64/koffi.node +0 -0
- package/build/2.3.10/koffi_linux_arm32hf/koffi.node +0 -0
- package/build/2.3.10/koffi_linux_arm64/koffi.node +0 -0
- package/build/2.3.10/koffi_linux_ia32/koffi.node +0 -0
- package/build/2.3.10/koffi_linux_riscv64hf64/koffi.node +0 -0
- package/build/2.3.10/koffi_linux_x64/koffi.node +0 -0
- package/build/2.3.10/koffi_openbsd_ia32/koffi.node +0 -0
- package/build/2.3.10/koffi_openbsd_x64/koffi.node +0 -0
- package/build/2.3.10/koffi_win32_arm64/koffi.node +0 -0
- package/build/2.3.10/koffi_win32_ia32/koffi.node +0 -0
- package/build/2.3.10/koffi_win32_x64/koffi.node +0 -0
- package/package.json +2 -2
- package/src/cnoke/package.json +2 -8
- package/src/cnoke/src/builder.js +5 -7
- package/src/core/libcc/brotli.cc +194 -0
- package/src/core/libcc/libcc.cc +111 -615
- package/src/core/libcc/libcc.hh +102 -28
- package/src/core/libcc/lz4.cc +204 -0
- package/src/core/libcc/miniz.cc +361 -0
- package/src/koffi/CMakeLists.txt +1 -1
- package/src/koffi/src/call.cc +18 -0
- package/build/2.3.10-beta.2/koffi_darwin_arm64/koffi.node +0 -0
- package/build/2.3.10-beta.2/koffi_darwin_x64/koffi.node +0 -0
- package/build/2.3.10-beta.2/koffi_freebsd_arm64/koffi.node +0 -0
- package/build/2.3.10-beta.2/koffi_freebsd_ia32/koffi.node +0 -0
- package/build/2.3.10-beta.2/koffi_freebsd_x64/koffi.node +0 -0
- package/build/2.3.10-beta.2/koffi_linux_arm32hf/koffi.node +0 -0
- package/build/2.3.10-beta.2/koffi_linux_arm64/koffi.node +0 -0
- package/build/2.3.10-beta.2/koffi_linux_ia32/koffi.node +0 -0
- package/build/2.3.10-beta.2/koffi_linux_riscv64hf64/koffi.node +0 -0
- package/build/2.3.10-beta.2/koffi_linux_x64/koffi.node +0 -0
- package/build/2.3.10-beta.2/koffi_openbsd_ia32/koffi.node +0 -0
- package/build/2.3.10-beta.2/koffi_openbsd_x64/koffi.node +0 -0
- package/build/2.3.10-beta.2/koffi_win32_arm64/koffi.node +0 -0
- package/build/2.3.10-beta.2/koffi_win32_ia32/koffi.node +0 -0
- package/build/2.3.10-beta.2/koffi_win32_x64/koffi.node +0 -0
- /package/build/{2.3.10-beta.2 → 2.3.10}/koffi_win32_arm64/koffi.exp +0 -0
- /package/build/{2.3.10-beta.2 → 2.3.10}/koffi_win32_arm64/koffi.lib +0 -0
- /package/build/{2.3.10-beta.2 → 2.3.10}/koffi_win32_ia32/koffi.exp +0 -0
- /package/build/{2.3.10-beta.2 → 2.3.10}/koffi_win32_ia32/koffi.lib +0 -0
- /package/build/{2.3.10-beta.2 → 2.3.10}/koffi_win32_x64/koffi.exp +0 -0
- /package/build/{2.3.10-beta.2 → 2.3.10}/koffi_win32_x64/koffi.lib +0 -0
package/src/core/libcc/libcc.cc
CHANGED
|
@@ -20,14 +20,7 @@
|
|
|
20
20
|
// OTHER DEALINGS IN THE SOFTWARE.
|
|
21
21
|
|
|
22
22
|
#include "libcc.hh"
|
|
23
|
-
|
|
24
|
-
#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
|
|
25
|
-
#include "vendor/miniz/miniz.h"
|
|
26
|
-
#endif
|
|
27
|
-
#if !defined(LIBCC_NO_BROTLI) && __has_include("vendor/brotli/c/include/brotli/decode.h")
|
|
28
|
-
#include "vendor/brotli/c/include/brotli/decode.h"
|
|
29
|
-
#include "vendor/brotli/c/include/brotli/encode.h"
|
|
30
|
-
#endif
|
|
23
|
+
|
|
31
24
|
#if __has_include("vendor/dragonbox/include/dragonbox/dragonbox.h") && __cplusplus >= 201703L
|
|
32
25
|
#include "vendor/dragonbox/include/dragonbox/dragonbox.h"
|
|
33
26
|
#endif
|
|
@@ -2142,6 +2135,8 @@ StatResult StatFile(const char *filename, unsigned int flags, FileInfo *out_info
|
|
|
2142
2135
|
out_info->mtime = FileTimeToUnixTime(attr.ftLastWriteTime);
|
|
2143
2136
|
out_info->btime = FileTimeToUnixTime(attr.ftCreationTime);
|
|
2144
2137
|
out_info->mode = (out_info->type == FileType::Directory) ? 0755 : 0644;
|
|
2138
|
+
out_info->uid = 0;
|
|
2139
|
+
out_info->gid = 0;
|
|
2145
2140
|
|
|
2146
2141
|
return StatResult::Success;
|
|
2147
2142
|
}
|
|
@@ -2150,24 +2145,30 @@ bool RenameFile(const char *src_filename, const char *dest_filename, unsigned in
|
|
|
2150
2145
|
{
|
|
2151
2146
|
DWORD move_flags = (flags & (int)RenameFlag::Overwrite) ? MOVEFILE_REPLACE_EXISTING : 0;
|
|
2152
2147
|
|
|
2153
|
-
|
|
2154
|
-
if (
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2148
|
+
for (int i = 0; i < 10; i++) {
|
|
2149
|
+
if (win32_utf8) {
|
|
2150
|
+
if (MoveFileExA(src_filename, dest_filename, move_flags))
|
|
2151
|
+
return true;
|
|
2152
|
+
} else {
|
|
2153
|
+
wchar_t src_filename_w[4096];
|
|
2154
|
+
wchar_t dest_filename_w[4096];
|
|
2155
|
+
if (ConvertUtf8ToWin32Wide(src_filename, src_filename_w) < 0)
|
|
2156
|
+
return false;
|
|
2157
|
+
if (ConvertUtf8ToWin32Wide(dest_filename, dest_filename_w) < 0)
|
|
2158
|
+
return false;
|
|
2163
2159
|
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2160
|
+
if (MoveFileExW(src_filename_w, dest_filename_w, move_flags))
|
|
2161
|
+
return true;
|
|
2162
|
+
}
|
|
2167
2163
|
|
|
2168
|
-
|
|
2164
|
+
if (GetLastError() != ERROR_ACCESS_DENIED)
|
|
2165
|
+
break;
|
|
2166
|
+
|
|
2167
|
+
// If two threads are trying to rename to the same destination or the FS is
|
|
2168
|
+
// very busy, we get spurious ERROR_ACCESS_DENIED errors. Wait a bit and retry :)
|
|
2169
|
+
Sleep(1);
|
|
2170
|
+
}
|
|
2169
2171
|
|
|
2170
|
-
error:
|
|
2171
2172
|
LogError("Failed to rename file '%1' to '%2': %3", src_filename, dest_filename, GetWin32ErrorString());
|
|
2172
2173
|
return false;
|
|
2173
2174
|
}
|
|
@@ -2291,7 +2292,7 @@ static FileType FileModeToType(mode_t mode)
|
|
|
2291
2292
|
|
|
2292
2293
|
StatResult StatFile(const char *filename, unsigned int flags, FileInfo *out_info)
|
|
2293
2294
|
{
|
|
2294
|
-
#
|
|
2295
|
+
#if defined(__linux__) && !defined(LIBCC_NO_STATX)
|
|
2295
2296
|
int stat_flags = (flags & (int)StatFlag::FollowSymlink) ? 0 : AT_SYMLINK_NOFOLLOW;
|
|
2296
2297
|
int stat_mask = STATX_TYPE | STATX_MODE | STATX_MTIME | STATX_BTIME | STATX_SIZE;
|
|
2297
2298
|
|
|
@@ -2326,6 +2327,8 @@ StatResult StatFile(const char *filename, unsigned int flags, FileInfo *out_info
|
|
|
2326
2327
|
out_info->btime = out_info->mtime;
|
|
2327
2328
|
}
|
|
2328
2329
|
out_info->mode = (unsigned int)sxb.stx_mode & ~S_IFMT;
|
|
2330
|
+
out_info->uid = sxb.stx_uid;
|
|
2331
|
+
out_info->gid = sxb.stx_gid;
|
|
2329
2332
|
#else
|
|
2330
2333
|
int stat_flags = (flags & (int)StatFlag::FollowSymlink) ? 0 : AT_SYMLINK_NOFOLLOW;
|
|
2331
2334
|
|
|
@@ -2351,7 +2354,12 @@ StatResult StatFile(const char *filename, unsigned int flags, FileInfo *out_info
|
|
|
2351
2354
|
|
|
2352
2355
|
out_info->type = FileModeToType(sb.st_mode);
|
|
2353
2356
|
out_info->size = (int64_t)sb.st_size;
|
|
2354
|
-
#if defined(
|
|
2357
|
+
#if defined(__linux__)
|
|
2358
|
+
out_info->mtime = (int64_t)sb.st_mtim.tv_sec * 1000 +
|
|
2359
|
+
(int64_t)sb.st_mtim.tv_nsec / 1000000;
|
|
2360
|
+
out_info->btime = (int64_t)sb.st_ctim.tv_sec * 1000 +
|
|
2361
|
+
(int64_t)sb.st_ctim.tv_nsec / 1000000;
|
|
2362
|
+
#elif defined(__APPLE__)
|
|
2355
2363
|
out_info->mtime = (int64_t)sb.st_mtimespec.tv_sec * 1000 +
|
|
2356
2364
|
(int64_t)sb.st_mtimespec.tv_nsec / 1000000;
|
|
2357
2365
|
out_info->btime = (int64_t)sb.st_birthtimespec.tv_sec * 1000 +
|
|
@@ -2368,6 +2376,8 @@ StatResult StatFile(const char *filename, unsigned int flags, FileInfo *out_info
|
|
|
2368
2376
|
(int64_t)sb.st_birthtim.tv_nsec / 1000000;
|
|
2369
2377
|
#endif
|
|
2370
2378
|
out_info->mode = (unsigned int)sb.st_mode;
|
|
2379
|
+
out_info->uid = (uint32_t)sb.st_uid;
|
|
2380
|
+
out_info->gid = (uint32_t)sb.st_gid;
|
|
2371
2381
|
#endif
|
|
2372
2382
|
|
|
2373
2383
|
return StatResult::Success;
|
|
@@ -2997,9 +3007,13 @@ Span<const char> GetPathExtension(Span<const char> filename, CompressionType *ou
|
|
|
2997
3007
|
};
|
|
2998
3008
|
|
|
2999
3009
|
consume_next_extension();
|
|
3010
|
+
|
|
3000
3011
|
if (out_compression_type) {
|
|
3001
|
-
|
|
3002
|
-
|
|
3012
|
+
const char *const *it = std::find_if(std::begin(CompressionTypeExtensions), std::end(CompressionTypeExtensions),
|
|
3013
|
+
[&](const char *it) { return it && TestStr(it, extension); });
|
|
3014
|
+
|
|
3015
|
+
if (it != std::end(CompressionTypeExtensions)) {
|
|
3016
|
+
*out_compression_type = (CompressionType)(it - CompressionTypeExtensions);
|
|
3003
3017
|
consume_next_extension();
|
|
3004
3018
|
} else {
|
|
3005
3019
|
*out_compression_type = CompressionType::None;
|
|
@@ -5324,7 +5338,6 @@ class AsyncPool {
|
|
|
5324
5338
|
HeapArray<bool> workers_state;
|
|
5325
5339
|
|
|
5326
5340
|
HeapArray<TaskQueue> queues;
|
|
5327
|
-
int next_queue_idx = 0;
|
|
5328
5341
|
std::atomic_int pending_tasks { 0 };
|
|
5329
5342
|
|
|
5330
5343
|
public:
|
|
@@ -5466,11 +5479,8 @@ void AsyncPool::AddTask(Async *async, const std::function<bool()> &func)
|
|
|
5466
5479
|
{
|
|
5467
5480
|
if (async_running_pool != async->pool) {
|
|
5468
5481
|
for (;;) {
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
if (--next_queue_idx < 0) {
|
|
5472
|
-
next_queue_idx = (int)workers_state.len - 1;
|
|
5473
|
-
}
|
|
5482
|
+
int idx = GetRandomIntSafe(0, queues.len);
|
|
5483
|
+
TaskQueue *queue = &queues[idx];
|
|
5474
5484
|
|
|
5475
5485
|
std::unique_lock<std::mutex> lock_queue(queue->queue_mutex, std::try_to_lock);
|
|
5476
5486
|
if (lock_queue.owns_lock()) {
|
|
@@ -5870,39 +5880,8 @@ StreamReader stdin_st(stdin, "<stdin>");
|
|
|
5870
5880
|
StreamWriter stdout_st(stdout, "<stdout>");
|
|
5871
5881
|
StreamWriter stderr_st(stderr, "<stderr>");
|
|
5872
5882
|
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
tinfl_decompressor inflator;
|
|
5876
|
-
bool done;
|
|
5877
|
-
|
|
5878
|
-
uint8_t in[256 * 1024];
|
|
5879
|
-
uint8_t *in_ptr;
|
|
5880
|
-
Size in_len;
|
|
5881
|
-
|
|
5882
|
-
uint8_t out[256 * 1024];
|
|
5883
|
-
uint8_t *out_ptr;
|
|
5884
|
-
Size out_len;
|
|
5885
|
-
|
|
5886
|
-
// Gzip support
|
|
5887
|
-
bool header_done;
|
|
5888
|
-
uint32_t crc32;
|
|
5889
|
-
Size uncompressed_size;
|
|
5890
|
-
};
|
|
5891
|
-
RG_STATIC_ASSERT(RG_SIZE(MinizInflateContext::out) >= TINFL_LZ_DICT_SIZE);
|
|
5892
|
-
#endif
|
|
5893
|
-
|
|
5894
|
-
#ifdef BROTLI_DEFAULT_MODE
|
|
5895
|
-
struct BrotliDecompressContext {
|
|
5896
|
-
BrotliDecoderState *state;
|
|
5897
|
-
bool done;
|
|
5898
|
-
|
|
5899
|
-
uint8_t in[256 * 1024];
|
|
5900
|
-
Size in_len;
|
|
5901
|
-
|
|
5902
|
-
uint8_t out[256 * 1024];
|
|
5903
|
-
Size out_len;
|
|
5904
|
-
};
|
|
5905
|
-
#endif
|
|
5883
|
+
static CreateDecompressorFunc *DecompressorFunctions[RG_LEN(CompressionTypeNames)];
|
|
5884
|
+
static CreateCompressorFunc *CompressorFunctions[RG_LEN(CompressionTypeNames)];
|
|
5906
5885
|
|
|
5907
5886
|
bool StreamReader::Open(Span<const uint8_t> buf, const char *filename,
|
|
5908
5887
|
CompressionType compression_type)
|
|
@@ -6000,35 +5979,9 @@ bool StreamReader::Close(bool implicit)
|
|
|
6000
5979
|
{
|
|
6001
5980
|
RG_ASSERT(implicit || this != &stdin_st);
|
|
6002
5981
|
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
case CompressionType::Gzip:
|
|
6007
|
-
case CompressionType::Zlib: {
|
|
6008
|
-
#ifdef MZ_VERSION
|
|
6009
|
-
ReleaseOne(nullptr, compression.u.miniz);
|
|
6010
|
-
compression.u.miniz = nullptr;
|
|
6011
|
-
#else
|
|
6012
|
-
RG_UNREACHABLE();
|
|
6013
|
-
#endif
|
|
6014
|
-
} break;
|
|
6015
|
-
|
|
6016
|
-
case CompressionType::Brotli: {
|
|
6017
|
-
#ifdef BROTLI_DEFAULT_MODE
|
|
6018
|
-
BrotliDecompressContext *ctx = compression.u.brotli;
|
|
6019
|
-
|
|
6020
|
-
if (ctx) {
|
|
6021
|
-
if (ctx->state) {
|
|
6022
|
-
BrotliDecoderDestroyInstance(ctx->state);
|
|
6023
|
-
}
|
|
6024
|
-
|
|
6025
|
-
ReleaseOne(nullptr, ctx);
|
|
6026
|
-
compression.u.brotli = nullptr;
|
|
6027
|
-
}
|
|
6028
|
-
#else
|
|
6029
|
-
RG_UNREACHABLE();
|
|
6030
|
-
#endif
|
|
6031
|
-
} break;
|
|
5982
|
+
if (decompressor) {
|
|
5983
|
+
RG_ASSERT(compression_type != CompressionType::None);
|
|
5984
|
+
delete decompressor;
|
|
6032
5985
|
}
|
|
6033
5986
|
|
|
6034
5987
|
switch (source.type) {
|
|
@@ -6048,7 +6001,7 @@ bool StreamReader::Close(bool implicit)
|
|
|
6048
6001
|
|
|
6049
6002
|
filename = nullptr;
|
|
6050
6003
|
error = true;
|
|
6051
|
-
|
|
6004
|
+
compression_type = CompressionType::None;
|
|
6052
6005
|
source.type = SourceType::Memory;
|
|
6053
6006
|
source.eof = false;
|
|
6054
6007
|
eof = false;
|
|
@@ -6079,31 +6032,12 @@ bool StreamReader::Rewind()
|
|
|
6079
6032
|
} break;
|
|
6080
6033
|
}
|
|
6081
6034
|
|
|
6082
|
-
|
|
6083
|
-
|
|
6084
|
-
|
|
6085
|
-
case CompressionType::Gzip:
|
|
6086
|
-
case CompressionType::Zlib: {
|
|
6087
|
-
#ifdef MZ_VERSION
|
|
6088
|
-
memset(compression.u.miniz, 0, sizeof(*compression.u.miniz));
|
|
6089
|
-
tinfl_init(&compression.u.miniz->inflator);
|
|
6090
|
-
compression.u.miniz->crc32 = MZ_CRC32_INIT;
|
|
6091
|
-
#else
|
|
6092
|
-
RG_UNREACHABLE();
|
|
6093
|
-
#endif
|
|
6094
|
-
} break;
|
|
6035
|
+
if (decompressor) {
|
|
6036
|
+
RG_ASSERT(compression_type != CompressionType::None);
|
|
6037
|
+
delete decompressor;
|
|
6095
6038
|
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
if (compression.u.brotli->state) {
|
|
6099
|
-
BrotliDecoderDestroyInstance(compression.u.brotli->state);
|
|
6100
|
-
compression.u.brotli->state = nullptr;
|
|
6101
|
-
}
|
|
6102
|
-
compression.u.brotli->state = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);
|
|
6103
|
-
#else
|
|
6104
|
-
RG_UNREACHABLE();
|
|
6105
|
-
#endif
|
|
6106
|
-
} break;
|
|
6039
|
+
if (!InitDecompressor(compression_type))
|
|
6040
|
+
return false;
|
|
6107
6041
|
}
|
|
6108
6042
|
|
|
6109
6043
|
source.eof = false;
|
|
@@ -6135,28 +6069,16 @@ Size StreamReader::Read(Span<uint8_t> out_buf)
|
|
|
6135
6069
|
return -1;
|
|
6136
6070
|
|
|
6137
6071
|
Size read_len = 0;
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
read_len = ReadRaw(out_buf.len, out_buf.ptr);
|
|
6141
|
-
eof = source.eof;
|
|
6142
|
-
} break;
|
|
6072
|
+
if (decompressor) {
|
|
6073
|
+
RG_ASSERT(compression_type != CompressionType::None);
|
|
6143
6074
|
|
|
6144
|
-
|
|
6145
|
-
|
|
6146
|
-
|
|
6147
|
-
|
|
6148
|
-
#else
|
|
6149
|
-
RG_UNREACHABLE();
|
|
6150
|
-
#endif
|
|
6151
|
-
} break;
|
|
6075
|
+
read_len = decompressor->Read(out_buf.len, out_buf.ptr);
|
|
6076
|
+
error |= (read_len < 0);
|
|
6077
|
+
} else {
|
|
6078
|
+
RG_ASSERT(compression_type == CompressionType::None);
|
|
6152
6079
|
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
read_len = ReadBrotli(out_buf.len, out_buf.ptr);
|
|
6156
|
-
#else
|
|
6157
|
-
RG_UNREACHABLE();
|
|
6158
|
-
#endif
|
|
6159
|
-
} break;
|
|
6080
|
+
read_len = ReadRaw(out_buf.len, out_buf.ptr);
|
|
6081
|
+
eof = source.eof;
|
|
6160
6082
|
}
|
|
6161
6083
|
|
|
6162
6084
|
return read_len;
|
|
@@ -6185,7 +6107,7 @@ Size StreamReader::ReadAll(Size max_len, HeapArray<uint8_t> *out_buf)
|
|
|
6185
6107
|
// For some files (such as in /proc), the file size is reported as 0 even though there
|
|
6186
6108
|
// is content inside, because these files are generated on demand. So we need to take
|
|
6187
6109
|
// the slow path for apparently empty files.
|
|
6188
|
-
if (
|
|
6110
|
+
if (compression_type == CompressionType::None && ComputeRawLen() > 0) {
|
|
6189
6111
|
if (raw_len > max_len) {
|
|
6190
6112
|
LogError("File '%1' is too large (limit = %2)", filename, FmtDiskSize(max_len));
|
|
6191
6113
|
return -1;
|
|
@@ -6265,253 +6187,30 @@ int64_t StreamReader::ComputeRawLen()
|
|
|
6265
6187
|
|
|
6266
6188
|
bool StreamReader::InitDecompressor(CompressionType type)
|
|
6267
6189
|
{
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
case CompressionType::Gzip:
|
|
6272
|
-
case CompressionType::Zlib: {
|
|
6273
|
-
#ifdef MZ_VERSION
|
|
6274
|
-
compression.u.miniz = AllocateOne<MinizInflateContext>(nullptr, (int)AllocFlag::Zero);
|
|
6275
|
-
tinfl_init(&compression.u.miniz->inflator);
|
|
6276
|
-
compression.u.miniz->crc32 = MZ_CRC32_INIT;
|
|
6277
|
-
#else
|
|
6278
|
-
LogError("Deflate decompression not available for '%1'", filename);
|
|
6279
|
-
error = true;
|
|
6280
|
-
return false;
|
|
6281
|
-
#endif
|
|
6282
|
-
} break;
|
|
6190
|
+
if (type != CompressionType::None) {
|
|
6191
|
+
CreateDecompressorFunc *func = DecompressorFunctions[(int)type];
|
|
6283
6192
|
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
compression.u.brotli = AllocateOne<BrotliDecompressContext>(nullptr, (int)AllocFlag::Zero);
|
|
6287
|
-
compression.u.brotli->state = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);
|
|
6288
|
-
#else
|
|
6289
|
-
LogError("Brotli decompression not available for '%1'", filename);
|
|
6193
|
+
if (!func) {
|
|
6194
|
+
LogError("%1 decompression is not available for '%2'", CompressionTypeNames[(int)type], filename);
|
|
6290
6195
|
error = true;
|
|
6291
6196
|
return false;
|
|
6292
|
-
#endif
|
|
6293
|
-
} break;
|
|
6294
|
-
}
|
|
6295
|
-
compression.type = type;
|
|
6296
|
-
|
|
6297
|
-
return true;
|
|
6298
|
-
}
|
|
6299
|
-
|
|
6300
|
-
#ifdef MZ_VERSION
|
|
6301
|
-
Size StreamReader::ReadInflate(Size max_len, void *out_buf)
|
|
6302
|
-
{
|
|
6303
|
-
MinizInflateContext *ctx = compression.u.miniz;
|
|
6304
|
-
|
|
6305
|
-
// Gzip header is not directly supported by miniz. Currently this
|
|
6306
|
-
// will fail if the header is longer than 4096 bytes, which is
|
|
6307
|
-
// probably quite rare.
|
|
6308
|
-
if (compression.type == CompressionType::Gzip && !ctx->header_done) {
|
|
6309
|
-
uint8_t header[4096];
|
|
6310
|
-
Size header_len;
|
|
6311
|
-
|
|
6312
|
-
header_len = ReadRaw(RG_SIZE(header), header);
|
|
6313
|
-
if (header_len < 0) {
|
|
6314
|
-
return -1;
|
|
6315
|
-
} else if (header_len < 10 || header[0] != 0x1F || header[1] != 0x8B) {
|
|
6316
|
-
LogError("File '%1' does not look like a Gzip stream", filename);
|
|
6317
|
-
error = true;
|
|
6318
|
-
return -1;
|
|
6319
|
-
}
|
|
6320
|
-
|
|
6321
|
-
Size header_offset = 10;
|
|
6322
|
-
if (header[3] & 0x4) { // FEXTRA
|
|
6323
|
-
if (header_len - header_offset < 2)
|
|
6324
|
-
goto truncated_error;
|
|
6325
|
-
uint16_t extra_len = (uint16_t)((header[11] << 8) | header[10]);
|
|
6326
|
-
if (extra_len > header_len - header_offset)
|
|
6327
|
-
goto truncated_error;
|
|
6328
|
-
header_offset += extra_len;
|
|
6329
|
-
}
|
|
6330
|
-
if (header[3] & 0x8) { // FNAME
|
|
6331
|
-
uint8_t *end_ptr = (uint8_t *)memchr(header + header_offset, '\0',
|
|
6332
|
-
(size_t)(header_len - header_offset));
|
|
6333
|
-
if (!end_ptr)
|
|
6334
|
-
goto truncated_error;
|
|
6335
|
-
header_offset = end_ptr - header + 1;
|
|
6336
|
-
}
|
|
6337
|
-
if (header[3] & 0x10) { // FCOMMENT
|
|
6338
|
-
uint8_t *end_ptr = (uint8_t *)memchr(header + header_offset, '\0',
|
|
6339
|
-
(size_t)(header_len - header_offset));
|
|
6340
|
-
if (!end_ptr)
|
|
6341
|
-
goto truncated_error;
|
|
6342
|
-
header_offset = end_ptr - header + 1;
|
|
6343
|
-
}
|
|
6344
|
-
if (header[3] & 0x2) { // FHCRC
|
|
6345
|
-
if (header_len - header_offset < 2)
|
|
6346
|
-
goto truncated_error;
|
|
6347
|
-
uint16_t crc16 = (uint16_t)(header[1] << 8 | header[0]);
|
|
6348
|
-
if ((mz_crc32(MZ_CRC32_INIT, header, (size_t)header_offset) & 0xFFFF) == crc16) {
|
|
6349
|
-
LogError("Failed header CRC16 check in '%s'", filename);
|
|
6350
|
-
error = true;
|
|
6351
|
-
return -1;
|
|
6352
|
-
}
|
|
6353
|
-
header_offset += 2;
|
|
6354
|
-
}
|
|
6355
|
-
|
|
6356
|
-
// Put back remaining data in the buffer
|
|
6357
|
-
memcpy_safe(ctx->in, header + header_offset, (size_t)(header_len - header_offset));
|
|
6358
|
-
ctx->in_ptr = ctx->in;
|
|
6359
|
-
ctx->in_len = header_len - header_offset;
|
|
6360
|
-
|
|
6361
|
-
ctx->header_done = true;
|
|
6362
|
-
}
|
|
6363
|
-
|
|
6364
|
-
// Inflate (with miniz)
|
|
6365
|
-
{
|
|
6366
|
-
Size read_len = 0;
|
|
6367
|
-
for (;;) {
|
|
6368
|
-
if (max_len < ctx->out_len) {
|
|
6369
|
-
memcpy_safe(out_buf, ctx->out_ptr, (size_t)max_len);
|
|
6370
|
-
read_len += max_len;
|
|
6371
|
-
ctx->out_ptr += max_len;
|
|
6372
|
-
ctx->out_len -= max_len;
|
|
6373
|
-
|
|
6374
|
-
return read_len;
|
|
6375
|
-
} else {
|
|
6376
|
-
memcpy_safe(out_buf, ctx->out_ptr, (size_t)ctx->out_len);
|
|
6377
|
-
read_len += ctx->out_len;
|
|
6378
|
-
out_buf = (uint8_t *)out_buf + ctx->out_len;
|
|
6379
|
-
max_len -= ctx->out_len;
|
|
6380
|
-
ctx->out_ptr = ctx->out;
|
|
6381
|
-
ctx->out_len = 0;
|
|
6382
|
-
|
|
6383
|
-
if (ctx->done) {
|
|
6384
|
-
eof = true;
|
|
6385
|
-
return read_len;
|
|
6386
|
-
}
|
|
6387
|
-
}
|
|
6388
|
-
|
|
6389
|
-
while (ctx->out_len < RG_SIZE(ctx->out)) {
|
|
6390
|
-
if (!ctx->in_len) {
|
|
6391
|
-
ctx->in_ptr = ctx->in;
|
|
6392
|
-
ctx->in_len = ReadRaw(RG_SIZE(ctx->in), ctx->in);
|
|
6393
|
-
if (ctx->in_len < 0)
|
|
6394
|
-
return read_len ? read_len : ctx->in_len;
|
|
6395
|
-
}
|
|
6396
|
-
|
|
6397
|
-
size_t in_arg = (size_t)ctx->in_len;
|
|
6398
|
-
size_t out_arg = (size_t)(RG_SIZE(ctx->out) - ctx->out_len);
|
|
6399
|
-
uint32_t flags = (uint32_t)
|
|
6400
|
-
((compression.type == CompressionType::Zlib ? TINFL_FLAG_PARSE_ZLIB_HEADER : 0) |
|
|
6401
|
-
(source.eof ? 0 : TINFL_FLAG_HAS_MORE_INPUT));
|
|
6402
|
-
|
|
6403
|
-
tinfl_status status = tinfl_decompress(&ctx->inflator, ctx->in_ptr, &in_arg,
|
|
6404
|
-
ctx->out, ctx->out + ctx->out_len,
|
|
6405
|
-
&out_arg, flags);
|
|
6406
|
-
|
|
6407
|
-
if (compression.type == CompressionType::Gzip) {
|
|
6408
|
-
ctx->crc32 = (uint32_t)mz_crc32(ctx->crc32, ctx->out + ctx->out_len, out_arg);
|
|
6409
|
-
ctx->uncompressed_size += (Size)out_arg;
|
|
6410
|
-
}
|
|
6411
|
-
|
|
6412
|
-
ctx->in_ptr += (Size)in_arg;
|
|
6413
|
-
ctx->in_len -= (Size)in_arg;
|
|
6414
|
-
ctx->out_len += (Size)out_arg;
|
|
6415
|
-
|
|
6416
|
-
if (status == TINFL_STATUS_DONE) {
|
|
6417
|
-
// Gzip footer (CRC and size check)
|
|
6418
|
-
if (compression.type == CompressionType::Gzip) {
|
|
6419
|
-
uint32_t footer[2];
|
|
6420
|
-
RG_STATIC_ASSERT(RG_SIZE(footer) == 8);
|
|
6421
|
-
|
|
6422
|
-
if (ctx->in_len < RG_SIZE(footer)) {
|
|
6423
|
-
memcpy_safe(footer, ctx->in_ptr, (size_t)ctx->in_len);
|
|
6424
|
-
|
|
6425
|
-
Size missing_len = RG_SIZE(footer) - ctx->in_len;
|
|
6426
|
-
if (ReadRaw(missing_len, footer + ctx->in_len) < missing_len) {
|
|
6427
|
-
if (error) {
|
|
6428
|
-
return -1;
|
|
6429
|
-
} else {
|
|
6430
|
-
goto truncated_error;
|
|
6431
|
-
}
|
|
6432
|
-
}
|
|
6433
|
-
} else {
|
|
6434
|
-
memcpy_safe(footer, ctx->in_ptr, RG_SIZE(footer));
|
|
6435
|
-
}
|
|
6436
|
-
footer[0] = LittleEndian(footer[0]);
|
|
6437
|
-
footer[1] = LittleEndian(footer[1]);
|
|
6438
|
-
|
|
6439
|
-
if (ctx->crc32 != footer[0] ||
|
|
6440
|
-
(uint32_t)ctx->uncompressed_size != footer[1]) {
|
|
6441
|
-
LogError("Failed CRC32 or size check in GZip stream '%1'", filename);
|
|
6442
|
-
error = true;
|
|
6443
|
-
return -1;
|
|
6444
|
-
}
|
|
6445
|
-
}
|
|
6446
|
-
|
|
6447
|
-
ctx->done = true;
|
|
6448
|
-
break;
|
|
6449
|
-
} else if (status < TINFL_STATUS_DONE) {
|
|
6450
|
-
LogError("Failed to decompress '%1' (Deflate)", filename);
|
|
6451
|
-
error = true;
|
|
6452
|
-
return -1;
|
|
6453
|
-
}
|
|
6454
|
-
}
|
|
6455
6197
|
}
|
|
6456
|
-
}
|
|
6457
6198
|
|
|
6458
|
-
|
|
6459
|
-
LogError("Truncated Gzip header in '%1'", filename);
|
|
6460
|
-
error = true;
|
|
6461
|
-
return -1;
|
|
6462
|
-
}
|
|
6463
|
-
#endif
|
|
6199
|
+
decompressor = func(this);
|
|
6464
6200
|
|
|
6465
|
-
|
|
6466
|
-
Size StreamReader::ReadBrotli(Size max_len, void *out_buf)
|
|
6467
|
-
{
|
|
6468
|
-
BrotliDecompressContext *ctx = compression.u.brotli;
|
|
6469
|
-
|
|
6470
|
-
for (;;) {
|
|
6471
|
-
if (ctx->out_len || ctx->done) {
|
|
6472
|
-
Size copy_len = std::min(max_len, ctx->out_len);
|
|
6473
|
-
|
|
6474
|
-
ctx->out_len -= copy_len;
|
|
6475
|
-
memcpy(out_buf, ctx->out, copy_len);
|
|
6476
|
-
memmove(ctx->out, ctx->out + copy_len, ctx->out_len);
|
|
6477
|
-
|
|
6478
|
-
eof = !ctx->out_len && ctx->done;
|
|
6479
|
-
return copy_len;
|
|
6480
|
-
}
|
|
6481
|
-
|
|
6482
|
-
if (ctx->in_len < RG_SIZE(ctx->in)) {
|
|
6483
|
-
Size raw_len = ReadRaw(RG_SIZE(ctx->in) - ctx->in_len, ctx->in + ctx->in_len);
|
|
6484
|
-
if (raw_len < 0)
|
|
6485
|
-
return -1;
|
|
6486
|
-
ctx->in_len += raw_len;
|
|
6487
|
-
}
|
|
6488
|
-
|
|
6489
|
-
const uint8_t *next_in = ctx->in;
|
|
6490
|
-
uint8_t *next_out = ctx->out + ctx->out_len;
|
|
6491
|
-
size_t avail_in = (size_t)ctx->in_len;
|
|
6492
|
-
size_t avail_out = (size_t)(RG_SIZE(ctx->out) - ctx->out_len);
|
|
6493
|
-
|
|
6494
|
-
BrotliDecoderResult ret = BrotliDecoderDecompressStream(ctx->state, &avail_in, &next_in,
|
|
6495
|
-
&avail_out, &next_out, nullptr);
|
|
6496
|
-
|
|
6497
|
-
if (ret == BROTLI_DECODER_RESULT_SUCCESS) {
|
|
6498
|
-
ctx->done = true;
|
|
6499
|
-
} else if (ret == BROTLI_DECODER_RESULT_ERROR) {
|
|
6500
|
-
LogError("Malformed Brotli stream in '%1'", filename);
|
|
6201
|
+
if (!decompressor) {
|
|
6501
6202
|
error = true;
|
|
6502
|
-
return
|
|
6503
|
-
}
|
|
6504
|
-
|
|
6203
|
+
return false;
|
|
6204
|
+
}
|
|
6205
|
+
if (!decompressor->Init(type)) {
|
|
6505
6206
|
error = true;
|
|
6506
|
-
return
|
|
6207
|
+
return false;
|
|
6507
6208
|
}
|
|
6508
|
-
|
|
6509
|
-
ctx->out_len = next_out - ctx->out - ctx->out_len;
|
|
6510
6209
|
}
|
|
6511
6210
|
|
|
6512
|
-
|
|
6211
|
+
compression_type = type;
|
|
6212
|
+
return true;
|
|
6513
6213
|
}
|
|
6514
|
-
#endif
|
|
6515
6214
|
|
|
6516
6215
|
Size StreamReader::ReadRaw(Size max_len, void *out_buf)
|
|
6517
6216
|
{
|
|
@@ -6559,6 +6258,11 @@ restart:
|
|
|
6559
6258
|
return read_len;
|
|
6560
6259
|
}
|
|
6561
6260
|
|
|
6261
|
+
StreamDecompressorHelper::StreamDecompressorHelper(CompressionType compression_type, CreateDecompressorFunc *func)
|
|
6262
|
+
{
|
|
6263
|
+
DecompressorFunctions[(int)compression_type] = func;
|
|
6264
|
+
}
|
|
6265
|
+
|
|
6562
6266
|
// XXX: Maximum line length
|
|
6563
6267
|
bool LineReader::Next(Span<char> *out_line)
|
|
6564
6268
|
{
|
|
@@ -6612,16 +6316,12 @@ void LineReader::PushLogFilter()
|
|
|
6612
6316
|
});
|
|
6613
6317
|
}
|
|
6614
6318
|
|
|
6615
|
-
#ifdef
|
|
6616
|
-
struct
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
// Gzip support
|
|
6620
|
-
uint32_t crc32;
|
|
6621
|
-
Size uncompressed_size;
|
|
6319
|
+
#ifdef LZ4_VERSION_MAJOR
|
|
6320
|
+
struct LZ4CompressContext {
|
|
6321
|
+
LZ4F_cctx *encoder;
|
|
6322
|
+
LZ4F_preferences_t prefs = {};
|
|
6622
6323
|
|
|
6623
|
-
|
|
6624
|
-
LocalArray<uint8_t, 1024> buf;
|
|
6324
|
+
HeapArray<uint8_t> buf;
|
|
6625
6325
|
};
|
|
6626
6326
|
#endif
|
|
6627
6327
|
|
|
@@ -6788,51 +6488,14 @@ bool StreamWriter::Write(Span<const uint8_t> buf)
|
|
|
6788
6488
|
if (RG_UNLIKELY(error))
|
|
6789
6489
|
return false;
|
|
6790
6490
|
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
return WriteRaw(buf);
|
|
6794
|
-
} break;
|
|
6795
|
-
|
|
6796
|
-
case CompressionType::Gzip:
|
|
6797
|
-
case CompressionType::Zlib: {
|
|
6798
|
-
#ifdef MZ_VERSION
|
|
6799
|
-
MinizDeflateContext *ctx = compression.u.miniz;
|
|
6800
|
-
|
|
6801
|
-
if (ctx->buf.len) {
|
|
6802
|
-
Size copy_len = std::min(buf.len, ctx->buf.Available());
|
|
6803
|
-
|
|
6804
|
-
memcpy_safe(ctx->buf.end(), buf.ptr, copy_len);
|
|
6805
|
-
ctx->buf.len += copy_len;
|
|
6806
|
-
buf.ptr += copy_len;
|
|
6807
|
-
buf.len -= copy_len;
|
|
6808
|
-
}
|
|
6809
|
-
|
|
6810
|
-
if (buf.len) {
|
|
6811
|
-
if (ctx->buf.len && !WriteDeflate(ctx->buf))
|
|
6812
|
-
return false;
|
|
6813
|
-
ctx->buf.Clear();
|
|
6814
|
-
|
|
6815
|
-
if (buf.len >= RG_SIZE(ctx->buf.data) / 2) {
|
|
6816
|
-
if (!WriteDeflate(buf))
|
|
6817
|
-
return false;
|
|
6818
|
-
} else {
|
|
6819
|
-
memcpy_safe(ctx->buf.data, buf.ptr, buf.len);
|
|
6820
|
-
ctx->buf.len = buf.len;
|
|
6821
|
-
}
|
|
6822
|
-
}
|
|
6823
|
-
|
|
6824
|
-
return true;
|
|
6825
|
-
#endif
|
|
6826
|
-
} break;
|
|
6491
|
+
if (compressor) {
|
|
6492
|
+
RG_ASSERT(compression_type != CompressionType::None);
|
|
6827
6493
|
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
} break;
|
|
6494
|
+
error |= !compressor->Write(buf);
|
|
6495
|
+
return !error;
|
|
6496
|
+
} else {
|
|
6497
|
+
return WriteRaw(buf);
|
|
6833
6498
|
}
|
|
6834
|
-
|
|
6835
|
-
RG_UNREACHABLE();
|
|
6836
6499
|
}
|
|
6837
6500
|
|
|
6838
6501
|
bool StreamWriter::Close(bool implicit)
|
|
@@ -6840,82 +6503,11 @@ bool StreamWriter::Close(bool implicit)
|
|
|
6840
6503
|
RG_ASSERT(implicit || this != &stdout_st);
|
|
6841
6504
|
RG_ASSERT(implicit || this != &stderr_st);
|
|
6842
6505
|
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
case CompressionType::Gzip:
|
|
6847
|
-
case CompressionType::Zlib: {
|
|
6848
|
-
#ifdef MZ_VERSION
|
|
6849
|
-
MinizDeflateContext *ctx = compression.u.miniz;
|
|
6850
|
-
|
|
6851
|
-
RG_DEFER {
|
|
6852
|
-
ReleaseOne(nullptr, ctx);
|
|
6853
|
-
compression.u.miniz = nullptr;
|
|
6854
|
-
};
|
|
6855
|
-
|
|
6856
|
-
if (IsValid() && ctx) {
|
|
6857
|
-
if (ctx->buf.len && !WriteDeflate(ctx->buf)) {
|
|
6858
|
-
error = true;
|
|
6859
|
-
break;
|
|
6860
|
-
}
|
|
6861
|
-
|
|
6862
|
-
uint8_t dummy; // Avoid UB in miniz
|
|
6863
|
-
tdefl_status status = tdefl_compress_buffer(&ctx->deflator, &dummy, 0, TDEFL_FINISH);
|
|
6864
|
-
if (status != TDEFL_STATUS_DONE) {
|
|
6865
|
-
if (status != TDEFL_STATUS_PUT_BUF_FAILED) {
|
|
6866
|
-
LogError("Failed to end Deflate stream for '%1", filename);
|
|
6867
|
-
}
|
|
6868
|
-
|
|
6869
|
-
error = true;
|
|
6870
|
-
break;
|
|
6871
|
-
}
|
|
6872
|
-
|
|
6873
|
-
if (compression.type == CompressionType::Gzip) {
|
|
6874
|
-
uint32_t gzip_footer[] = {
|
|
6875
|
-
LittleEndian(ctx->crc32),
|
|
6876
|
-
LittleEndian((uint32_t)ctx->uncompressed_size)
|
|
6877
|
-
};
|
|
6506
|
+
if (compressor && !error) {
|
|
6507
|
+
RG_ASSERT(compression_type != CompressionType::None);
|
|
6508
|
+
error |= !compressor->Finalize();
|
|
6878
6509
|
|
|
6879
|
-
|
|
6880
|
-
error = true;
|
|
6881
|
-
break;
|
|
6882
|
-
}
|
|
6883
|
-
}
|
|
6884
|
-
}
|
|
6885
|
-
#endif
|
|
6886
|
-
} break;
|
|
6887
|
-
|
|
6888
|
-
case CompressionType::Brotli: {
|
|
6889
|
-
#ifdef BROTLI_DEFAULT_MODE
|
|
6890
|
-
BrotliEncoderState *state = compression.u.brotli;
|
|
6891
|
-
uint8_t output_buf[2048];
|
|
6892
|
-
|
|
6893
|
-
if (state) {
|
|
6894
|
-
RG_DEFER {
|
|
6895
|
-
BrotliEncoderDestroyInstance(state);
|
|
6896
|
-
compression.u.brotli = nullptr;
|
|
6897
|
-
};
|
|
6898
|
-
|
|
6899
|
-
do {
|
|
6900
|
-
const uint8_t *next_in = nullptr;
|
|
6901
|
-
uint8_t *next_out = output_buf;
|
|
6902
|
-
size_t avail_in = 0;
|
|
6903
|
-
size_t avail_out = RG_SIZE(output_buf);
|
|
6904
|
-
|
|
6905
|
-
if (!BrotliEncoderCompressStream(state, BROTLI_OPERATION_FINISH,
|
|
6906
|
-
&avail_in, &next_in, &avail_out, &next_out, nullptr)) {
|
|
6907
|
-
LogError("Failed to compress '%1' with Brotli", filename);
|
|
6908
|
-
error = true;
|
|
6909
|
-
break;
|
|
6910
|
-
}
|
|
6911
|
-
if (!WriteRaw(MakeSpan(output_buf, next_out - output_buf))) {
|
|
6912
|
-
error = true;
|
|
6913
|
-
break;
|
|
6914
|
-
}
|
|
6915
|
-
} while (BrotliEncoderHasMoreOutput(state));
|
|
6916
|
-
}
|
|
6917
|
-
#endif
|
|
6918
|
-
} break;
|
|
6510
|
+
delete compressor;
|
|
6919
6511
|
}
|
|
6920
6512
|
|
|
6921
6513
|
switch (dest.type) {
|
|
@@ -6974,7 +6566,7 @@ bool StreamWriter::Close(bool implicit)
|
|
|
6974
6566
|
|
|
6975
6567
|
filename = nullptr;
|
|
6976
6568
|
error = true;
|
|
6977
|
-
|
|
6569
|
+
compression_type = CompressionType::None;
|
|
6978
6570
|
dest.type = DestinationType::Memory;
|
|
6979
6571
|
str_alloc.ReleaseAll();
|
|
6980
6572
|
|
|
@@ -6983,133 +6575,32 @@ bool StreamWriter::Close(bool implicit)
|
|
|
6983
6575
|
|
|
6984
6576
|
bool StreamWriter::InitCompressor(CompressionType type, CompressionSpeed speed)
|
|
6985
6577
|
{
|
|
6986
|
-
|
|
6987
|
-
|
|
6578
|
+
if (type != CompressionType::None) {
|
|
6579
|
+
CreateCompressorFunc *func = CompressorFunctions[(int)type];
|
|
6988
6580
|
|
|
6989
|
-
|
|
6990
|
-
|
|
6991
|
-
#ifdef MZ_VERSION
|
|
6992
|
-
compression.u.miniz = AllocateOne<MinizDeflateContext>(nullptr, (int)AllocFlag::Zero);
|
|
6993
|
-
compression.u.miniz->crc32 = MZ_CRC32_INIT;
|
|
6994
|
-
|
|
6995
|
-
int flags = 0;
|
|
6996
|
-
switch (speed) {
|
|
6997
|
-
case CompressionSpeed::Default: { flags = 32 | TDEFL_GREEDY_PARSING_FLAG; } break;
|
|
6998
|
-
case CompressionSpeed::Slow: { flags = 512; } break;
|
|
6999
|
-
case CompressionSpeed::Fast: { flags = 1 | TDEFL_GREEDY_PARSING_FLAG; } break;
|
|
7000
|
-
}
|
|
7001
|
-
flags |= (type == CompressionType::Zlib ? TDEFL_WRITE_ZLIB_HEADER : 0);
|
|
7002
|
-
|
|
7003
|
-
tdefl_status status = tdefl_init(&compression.u.miniz->deflator,
|
|
7004
|
-
[](const void *buf, int len, void *udata) {
|
|
7005
|
-
StreamWriter *st = (StreamWriter *)udata;
|
|
7006
|
-
return (int)st->WriteRaw(MakeSpan((uint8_t *)buf, len));
|
|
7007
|
-
}, this, flags);
|
|
7008
|
-
if (status != TDEFL_STATUS_OKAY) {
|
|
7009
|
-
LogError("Failed to initialize Deflate compression for '%1'", filename);
|
|
7010
|
-
error = true;
|
|
7011
|
-
return false;
|
|
7012
|
-
}
|
|
7013
|
-
|
|
7014
|
-
if (type == CompressionType::Gzip) {
|
|
7015
|
-
static uint8_t gzip_header[] = {
|
|
7016
|
-
0x1F, 0x8B, // Fixed bytes
|
|
7017
|
-
8, // Deflate
|
|
7018
|
-
0, // FLG
|
|
7019
|
-
0, 0, 0, 0, // MTIME
|
|
7020
|
-
0, // XFL
|
|
7021
|
-
0 // OS
|
|
7022
|
-
};
|
|
7023
|
-
|
|
7024
|
-
if (!WriteRaw(gzip_header))
|
|
7025
|
-
return false;
|
|
7026
|
-
}
|
|
7027
|
-
#else
|
|
7028
|
-
LogError("Deflate compression not available for '%1'", filename);
|
|
6581
|
+
if (!func) {
|
|
6582
|
+
LogError("%1 compression is not available for '%2'", CompressionTypeNames[(int)type], filename);
|
|
7029
6583
|
error = true;
|
|
7030
6584
|
return false;
|
|
7031
|
-
#endif
|
|
7032
|
-
} break;
|
|
7033
|
-
|
|
7034
|
-
case CompressionType::Brotli: {
|
|
7035
|
-
#ifdef BROTLI_DEFAULT_MODE
|
|
7036
|
-
BrotliEncoderState *state = BrotliEncoderCreateInstance(nullptr, nullptr, nullptr);
|
|
7037
|
-
compression.u.brotli = state;
|
|
7038
|
-
|
|
7039
|
-
RG_STATIC_ASSERT(BROTLI_MIN_QUALITY == 0 && BROTLI_MAX_QUALITY == 11);
|
|
7040
|
-
|
|
7041
|
-
switch (speed) {
|
|
7042
|
-
case CompressionSpeed::Default: { BrotliEncoderSetParameter(state, BROTLI_PARAM_QUALITY, 6); } break;
|
|
7043
|
-
case CompressionSpeed::Slow: { BrotliEncoderSetParameter(state, BROTLI_PARAM_QUALITY, 11); } break;
|
|
7044
|
-
case CompressionSpeed::Fast: { BrotliEncoderSetParameter(state, BROTLI_PARAM_QUALITY, 0); } break;
|
|
7045
|
-
}
|
|
7046
|
-
#else
|
|
7047
|
-
LogError("Brotli compression not available for '%1'", filename);
|
|
7048
|
-
error = true;
|
|
7049
|
-
return false;
|
|
7050
|
-
#endif
|
|
7051
|
-
} break;
|
|
7052
|
-
}
|
|
7053
|
-
|
|
7054
|
-
compression.type = type;
|
|
7055
|
-
compression.speed = speed;
|
|
7056
|
-
|
|
7057
|
-
return true;
|
|
7058
|
-
}
|
|
7059
|
-
|
|
7060
|
-
#ifdef MZ_VERSION
|
|
7061
|
-
bool StreamWriter::WriteDeflate(Span<const uint8_t> buf)
|
|
7062
|
-
{
|
|
7063
|
-
MinizDeflateContext *ctx = compression.u.miniz;
|
|
7064
|
-
|
|
7065
|
-
if (compression.type == CompressionType::Gzip) {
|
|
7066
|
-
ctx->crc32 = (uint32_t)mz_crc32(ctx->crc32, buf.ptr, (size_t)buf.len);
|
|
7067
|
-
ctx->uncompressed_size += buf.len;
|
|
7068
|
-
}
|
|
7069
|
-
|
|
7070
|
-
tdefl_status status = tdefl_compress_buffer(&ctx->deflator, buf.ptr, (size_t)buf.len, TDEFL_NO_FLUSH);
|
|
7071
|
-
if (status < TDEFL_STATUS_OKAY) {
|
|
7072
|
-
if (status != TDEFL_STATUS_PUT_BUF_FAILED) {
|
|
7073
|
-
LogError("Failed to deflate stream to '%1'", filename);
|
|
7074
6585
|
}
|
|
7075
6586
|
|
|
7076
|
-
|
|
7077
|
-
return false;
|
|
7078
|
-
}
|
|
7079
|
-
|
|
7080
|
-
return true;
|
|
7081
|
-
}
|
|
7082
|
-
#endif
|
|
7083
|
-
|
|
7084
|
-
#ifdef BROTLI_DEFAULT_MODE
|
|
7085
|
-
bool StreamWriter::WriteBrotli(Span<const uint8_t> buf)
|
|
7086
|
-
{
|
|
7087
|
-
BrotliEncoderState *state = compression.u.brotli;
|
|
7088
|
-
uint8_t output_buf[2048];
|
|
6587
|
+
compressor = func(this);
|
|
7089
6588
|
|
|
7090
|
-
|
|
7091
|
-
const uint8_t *next_in = buf.ptr;
|
|
7092
|
-
uint8_t *next_out = output_buf;
|
|
7093
|
-
size_t avail_in = (size_t)buf.len;
|
|
7094
|
-
size_t avail_out = RG_SIZE(output_buf);
|
|
7095
|
-
|
|
7096
|
-
if (!BrotliEncoderCompressStream(state, BROTLI_OPERATION_PROCESS,
|
|
7097
|
-
&avail_in, &next_in, &avail_out, &next_out, nullptr)) {
|
|
6589
|
+
if (!compressor) {
|
|
7098
6590
|
error = true;
|
|
7099
6591
|
return false;
|
|
7100
6592
|
}
|
|
7101
|
-
if (!
|
|
6593
|
+
if (!compressor->Init(type, speed)) {
|
|
7102
6594
|
error = true;
|
|
7103
6595
|
return false;
|
|
7104
6596
|
}
|
|
7105
|
-
|
|
7106
|
-
buf.len -= next_in - buf.ptr;
|
|
7107
|
-
buf.ptr = next_in;
|
|
7108
6597
|
}
|
|
7109
6598
|
|
|
6599
|
+
compression_type = type;
|
|
6600
|
+
compression_speed = speed;
|
|
6601
|
+
|
|
7110
6602
|
return true;
|
|
7111
6603
|
}
|
|
7112
|
-
#endif
|
|
7113
6604
|
|
|
7114
6605
|
bool StreamWriter::WriteRaw(Span<const uint8_t> buf)
|
|
7115
6606
|
{
|
|
@@ -7161,6 +6652,11 @@ bool StreamWriter::WriteRaw(Span<const uint8_t> buf)
|
|
|
7161
6652
|
return true;
|
|
7162
6653
|
}
|
|
7163
6654
|
|
|
6655
|
+
StreamCompressorHelper::StreamCompressorHelper(CompressionType compression_type, CreateCompressorFunc *func)
|
|
6656
|
+
{
|
|
6657
|
+
CompressorFunctions[(int)compression_type] = func;
|
|
6658
|
+
}
|
|
6659
|
+
|
|
7164
6660
|
bool SpliceStream(StreamReader *reader, int64_t max_len, StreamWriter *writer)
|
|
7165
6661
|
{
|
|
7166
6662
|
if (!reader->IsValid())
|