koffi 2.3.10-beta.3 → 2.3.11
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 +12 -0
- package/build/2.3.11/koffi_darwin_arm64/koffi.node +0 -0
- package/build/2.3.11/koffi_darwin_x64/koffi.node +0 -0
- package/build/2.3.11/koffi_freebsd_arm64/koffi.node +0 -0
- package/build/2.3.11/koffi_freebsd_ia32/koffi.node +0 -0
- package/build/2.3.11/koffi_freebsd_x64/koffi.node +0 -0
- package/build/2.3.11/koffi_linux_arm32hf/koffi.node +0 -0
- package/build/2.3.11/koffi_linux_arm64/koffi.node +0 -0
- package/build/2.3.11/koffi_linux_ia32/koffi.node +0 -0
- package/build/2.3.11/koffi_linux_riscv64hf64/koffi.node +0 -0
- package/build/2.3.11/koffi_linux_x64/koffi.node +0 -0
- package/build/2.3.11/koffi_openbsd_ia32/koffi.node +0 -0
- package/build/2.3.11/koffi_openbsd_x64/koffi.node +0 -0
- package/build/2.3.11/koffi_win32_arm64/koffi.node +0 -0
- package/build/2.3.11/koffi_win32_ia32/koffi.node +0 -0
- package/build/2.3.11/koffi_win32_x64/koffi.node +0 -0
- package/package.json +2 -2
- package/src/cnoke/package.json +2 -8
- 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.3/koffi_darwin_arm64/koffi.node +0 -0
- package/build/2.3.10-beta.3/koffi_darwin_x64/koffi.node +0 -0
- package/build/2.3.10-beta.3/koffi_freebsd_arm64/koffi.node +0 -0
- package/build/2.3.10-beta.3/koffi_freebsd_ia32/koffi.node +0 -0
- package/build/2.3.10-beta.3/koffi_freebsd_x64/koffi.node +0 -0
- package/build/2.3.10-beta.3/koffi_linux_arm32hf/koffi.node +0 -0
- package/build/2.3.10-beta.3/koffi_linux_arm64/koffi.node +0 -0
- package/build/2.3.10-beta.3/koffi_linux_ia32/koffi.node +0 -0
- package/build/2.3.10-beta.3/koffi_linux_riscv64hf64/koffi.node +0 -0
- package/build/2.3.10-beta.3/koffi_linux_x64/koffi.node +0 -0
- package/build/2.3.10-beta.3/koffi_openbsd_ia32/koffi.node +0 -0
- package/build/2.3.10-beta.3/koffi_openbsd_x64/koffi.node +0 -0
- package/build/2.3.10-beta.3/koffi_win32_arm64/koffi.node +0 -0
- package/build/2.3.10-beta.3/koffi_win32_ia32/koffi.node +0 -0
- package/build/2.3.10-beta.3/koffi_win32_x64/koffi.node +0 -0
- /package/build/{2.3.10-beta.3 → 2.3.11}/koffi_win32_arm64/koffi.exp +0 -0
- /package/build/{2.3.10-beta.3 → 2.3.11}/koffi_win32_arm64/koffi.lib +0 -0
- /package/build/{2.3.10-beta.3 → 2.3.11}/koffi_win32_ia32/koffi.exp +0 -0
- /package/build/{2.3.10-beta.3 → 2.3.11}/koffi_win32_ia32/koffi.lib +0 -0
- /package/build/{2.3.10-beta.3 → 2.3.11}/koffi_win32_x64/koffi.exp +0 -0
- /package/build/{2.3.10-beta.3 → 2.3.11}/koffi_win32_x64/koffi.lib +0 -0
package/src/core/libcc/libcc.hh
CHANGED
|
@@ -136,7 +136,7 @@ static_assert(sizeof(double) == 8, "This code base is not designed to support si
|
|
|
136
136
|
#define RG_STRINGIFY(a) RG_STRINGIFY_(a)
|
|
137
137
|
#define RG_CONCAT_(a, b) a ## b
|
|
138
138
|
#define RG_CONCAT(a, b) RG_CONCAT_(a, b)
|
|
139
|
-
#define RG_UNIQUE_NAME(prefix) RG_CONCAT(prefix,
|
|
139
|
+
#define RG_UNIQUE_NAME(prefix) RG_CONCAT(prefix, __LINE__)
|
|
140
140
|
#define RG_FORCE_EXPAND(x) x
|
|
141
141
|
#define RG_IGNORE (void)!
|
|
142
142
|
|
|
@@ -597,7 +597,7 @@ public:
|
|
|
597
597
|
}; \
|
|
598
598
|
static ClassName RG_UNIQUE_NAME(init); \
|
|
599
599
|
ClassName::ClassName()
|
|
600
|
-
#define RG_INIT(Name) RG_INIT_(RG_UNIQUE_NAME(InitHelper))
|
|
600
|
+
#define RG_INIT(Name) RG_INIT_(RG_CONCAT(RG_UNIQUE_NAME(InitHelper), Name))
|
|
601
601
|
|
|
602
602
|
#define RG_EXIT_(ClassName) \
|
|
603
603
|
class ClassName { \
|
|
@@ -606,7 +606,7 @@ public:
|
|
|
606
606
|
}; \
|
|
607
607
|
static ClassName RG_UNIQUE_NAME(exit); \
|
|
608
608
|
ClassName::~ClassName()
|
|
609
|
-
#define RG_EXIT(Name) RG_EXIT_(RG_UNIQUE_NAME(ExitHelper))
|
|
609
|
+
#define RG_EXIT(Name) RG_EXIT_(RG_CONCAT(RG_UNIQUE_NAME(ExitHelper), Name))
|
|
610
610
|
|
|
611
611
|
template <typename T>
|
|
612
612
|
T MultiCmp()
|
|
@@ -3791,13 +3791,22 @@ enum class CompressionType {
|
|
|
3791
3791
|
None,
|
|
3792
3792
|
Zlib,
|
|
3793
3793
|
Gzip,
|
|
3794
|
-
Brotli
|
|
3794
|
+
Brotli,
|
|
3795
|
+
LZ4
|
|
3795
3796
|
};
|
|
3796
3797
|
static const char *const CompressionTypeNames[] = {
|
|
3797
3798
|
"None",
|
|
3798
3799
|
"Zlib",
|
|
3799
3800
|
"Gzip",
|
|
3800
|
-
"Brotli"
|
|
3801
|
+
"Brotli",
|
|
3802
|
+
"LZ4"
|
|
3803
|
+
};
|
|
3804
|
+
static const char *const CompressionTypeExtensions[] = {
|
|
3805
|
+
nullptr,
|
|
3806
|
+
nullptr,
|
|
3807
|
+
".gz",
|
|
3808
|
+
".br",
|
|
3809
|
+
".lz4"
|
|
3801
3810
|
};
|
|
3802
3811
|
|
|
3803
3812
|
Span<const char> GetPathDirectory(Span<const char> filename);
|
|
@@ -3842,6 +3851,9 @@ struct FileInfo {
|
|
|
3842
3851
|
int64_t mtime;
|
|
3843
3852
|
int64_t btime;
|
|
3844
3853
|
unsigned int mode;
|
|
3854
|
+
|
|
3855
|
+
uint32_t uid;
|
|
3856
|
+
uint32_t gid;
|
|
3845
3857
|
};
|
|
3846
3858
|
|
|
3847
3859
|
enum class StatResult {
|
|
@@ -4202,6 +4214,9 @@ enum class CompressionSpeed {
|
|
|
4202
4214
|
Fast
|
|
4203
4215
|
};
|
|
4204
4216
|
|
|
4217
|
+
class StreamDecompressor;
|
|
4218
|
+
class StreamCompressor;
|
|
4219
|
+
|
|
4205
4220
|
class StreamReader {
|
|
4206
4221
|
RG_DELETE_COPY(StreamReader)
|
|
4207
4222
|
|
|
@@ -4235,13 +4250,8 @@ class StreamReader {
|
|
|
4235
4250
|
bool eof = false;
|
|
4236
4251
|
} source;
|
|
4237
4252
|
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
union {
|
|
4241
|
-
struct MinizInflateContext *miniz;
|
|
4242
|
-
struct BrotliDecompressContext *brotli;
|
|
4243
|
-
} u;
|
|
4244
|
-
} compression;
|
|
4253
|
+
CompressionType compression_type = CompressionType::None;
|
|
4254
|
+
StreamDecompressor *decompressor = nullptr;
|
|
4245
4255
|
|
|
4246
4256
|
int64_t raw_len = -1;
|
|
4247
4257
|
Size raw_read = 0;
|
|
@@ -4278,7 +4288,7 @@ public:
|
|
|
4278
4288
|
bool Rewind();
|
|
4279
4289
|
|
|
4280
4290
|
const char *GetFileName() const { return filename; }
|
|
4281
|
-
CompressionType GetCompressionType() const { return
|
|
4291
|
+
CompressionType GetCompressionType() const { return compression_type; }
|
|
4282
4292
|
bool IsValid() const { return filename && !error; }
|
|
4283
4293
|
bool IsEOF() const { return eof; }
|
|
4284
4294
|
|
|
@@ -4301,10 +4311,9 @@ private:
|
|
|
4301
4311
|
|
|
4302
4312
|
bool InitDecompressor(CompressionType type);
|
|
4303
4313
|
|
|
4304
|
-
Size ReadInflate(Size max_len, void *out_buf);
|
|
4305
|
-
Size ReadBrotli(Size max_len, void *out_buf);
|
|
4306
|
-
|
|
4307
4314
|
Size ReadRaw(Size max_len, void *out_buf);
|
|
4315
|
+
|
|
4316
|
+
friend class StreamDecompressor;
|
|
4308
4317
|
};
|
|
4309
4318
|
|
|
4310
4319
|
static inline Size ReadFile(const char *filename, CompressionType compression_type, Span<uint8_t> out_buf)
|
|
@@ -4351,6 +4360,42 @@ static inline Size ReadFile(const char *filename, Size max_len, HeapArray<char>
|
|
|
4351
4360
|
return st.ReadAll(max_len, out_buf);
|
|
4352
4361
|
}
|
|
4353
4362
|
|
|
4363
|
+
class StreamDecompressor {
|
|
4364
|
+
protected:
|
|
4365
|
+
StreamReader *reader;
|
|
4366
|
+
|
|
4367
|
+
public:
|
|
4368
|
+
StreamDecompressor(StreamReader *reader) : reader(reader) {}
|
|
4369
|
+
virtual ~StreamDecompressor() {}
|
|
4370
|
+
|
|
4371
|
+
virtual bool Init(CompressionType type) = 0;
|
|
4372
|
+
virtual Size Read(Size max_len, void *out_buf) = 0;
|
|
4373
|
+
|
|
4374
|
+
protected:
|
|
4375
|
+
const char *GetFileName() const { return reader->filename; }
|
|
4376
|
+
bool IsValid() const { return reader->IsValid(); }
|
|
4377
|
+
bool IsSourceEOF() const { return reader->source.eof; }
|
|
4378
|
+
|
|
4379
|
+
Size ReadRaw(Size max_len, void *out_buf) { return reader->ReadRaw(max_len, out_buf); }
|
|
4380
|
+
|
|
4381
|
+
void SetEOF(bool eof) { reader->eof = eof; }
|
|
4382
|
+
};
|
|
4383
|
+
|
|
4384
|
+
typedef StreamDecompressor *CreateDecompressorFunc(StreamReader *reader);
|
|
4385
|
+
|
|
4386
|
+
class StreamDecompressorHelper {
|
|
4387
|
+
public:
|
|
4388
|
+
StreamDecompressorHelper(CompressionType type, CreateDecompressorFunc *func);
|
|
4389
|
+
};
|
|
4390
|
+
|
|
4391
|
+
#define RG_REGISTER_DECOMPRESSOR(Type, Cls) \
|
|
4392
|
+
static StreamDecompressor *RG_UNIQUE_NAME(CreateDecompressor)(StreamReader *reader) \
|
|
4393
|
+
{ \
|
|
4394
|
+
StreamDecompressor *decompressor = new Cls(reader); \
|
|
4395
|
+
return decompressor; \
|
|
4396
|
+
} \
|
|
4397
|
+
static StreamDecompressorHelper RG_UNIQUE_NAME(CreateDecompressorHelper)((Type), RG_UNIQUE_NAME(CreateDecompressor))
|
|
4398
|
+
|
|
4354
4399
|
class LineReader {
|
|
4355
4400
|
RG_DELETE_COPY(LineReader)
|
|
4356
4401
|
|
|
@@ -4420,14 +4465,9 @@ class StreamWriter {
|
|
|
4420
4465
|
bool vt100;
|
|
4421
4466
|
} dest;
|
|
4422
4467
|
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
union {
|
|
4427
|
-
struct MinizDeflateContext *miniz;
|
|
4428
|
-
struct BrotliEncoderStateStruct *brotli;
|
|
4429
|
-
} u;
|
|
4430
|
-
} compression;
|
|
4468
|
+
CompressionType compression_type = CompressionType::None;
|
|
4469
|
+
CompressionSpeed compression_speed = CompressionSpeed::Default;
|
|
4470
|
+
StreamCompressor *compressor = nullptr;
|
|
4431
4471
|
|
|
4432
4472
|
int64_t raw_written = 0;
|
|
4433
4473
|
|
|
@@ -4471,7 +4511,8 @@ public:
|
|
|
4471
4511
|
bool Flush();
|
|
4472
4512
|
|
|
4473
4513
|
const char *GetFileName() const { return filename; }
|
|
4474
|
-
CompressionType GetCompressionType() const { return
|
|
4514
|
+
CompressionType GetCompressionType() const { return compression_type; }
|
|
4515
|
+
CompressionSpeed GetCompressionSpeed() const { return compression_speed; }
|
|
4475
4516
|
bool IsVt100() const { return dest.vt100; }
|
|
4476
4517
|
bool IsValid() const { return filename && !error; }
|
|
4477
4518
|
|
|
@@ -4490,10 +4531,9 @@ private:
|
|
|
4490
4531
|
|
|
4491
4532
|
bool InitCompressor(CompressionType type, CompressionSpeed speed);
|
|
4492
4533
|
|
|
4493
|
-
bool WriteDeflate(Span<const uint8_t> buf);
|
|
4494
|
-
bool WriteBrotli(Span<const uint8_t> buf);
|
|
4495
|
-
|
|
4496
4534
|
bool WriteRaw(Span<const uint8_t> buf);
|
|
4535
|
+
|
|
4536
|
+
friend class StreamCompressor;
|
|
4497
4537
|
};
|
|
4498
4538
|
|
|
4499
4539
|
static inline bool WriteFile(Span<const uint8_t> buf, const char *filename, unsigned int flags = 0,
|
|
@@ -4511,6 +4551,40 @@ static inline bool WriteFile(Span<const char> buf, const char *filename, unsigne
|
|
|
4511
4551
|
return st.Close();
|
|
4512
4552
|
}
|
|
4513
4553
|
|
|
4554
|
+
class StreamCompressor {
|
|
4555
|
+
protected:
|
|
4556
|
+
StreamWriter *writer;
|
|
4557
|
+
|
|
4558
|
+
public:
|
|
4559
|
+
StreamCompressor(StreamWriter *writer) : writer(writer) {}
|
|
4560
|
+
virtual ~StreamCompressor() {}
|
|
4561
|
+
|
|
4562
|
+
virtual bool Init(CompressionType type, CompressionSpeed speed) = 0;
|
|
4563
|
+
virtual bool Write(Span<const uint8_t> buf) = 0;
|
|
4564
|
+
virtual bool Finalize() = 0;
|
|
4565
|
+
|
|
4566
|
+
protected:
|
|
4567
|
+
const char *GetFileName() const { return writer->filename; }
|
|
4568
|
+
bool IsValid() const { return writer->IsValid(); }
|
|
4569
|
+
|
|
4570
|
+
bool WriteRaw(Span<const uint8_t> buf) { return writer->WriteRaw(buf); }
|
|
4571
|
+
};
|
|
4572
|
+
|
|
4573
|
+
typedef StreamCompressor *CreateCompressorFunc(StreamWriter *writer);
|
|
4574
|
+
|
|
4575
|
+
class StreamCompressorHelper {
|
|
4576
|
+
public:
|
|
4577
|
+
StreamCompressorHelper(CompressionType type, CreateCompressorFunc *func);
|
|
4578
|
+
};
|
|
4579
|
+
|
|
4580
|
+
#define RG_REGISTER_COMPRESSOR(Type, Cls) \
|
|
4581
|
+
static StreamCompressor *RG_UNIQUE_NAME(CreateCompressor)(StreamWriter *writer) \
|
|
4582
|
+
{ \
|
|
4583
|
+
StreamCompressor *compressor = new Cls(writer); \
|
|
4584
|
+
return compressor; \
|
|
4585
|
+
} \
|
|
4586
|
+
static StreamCompressorHelper RG_UNIQUE_NAME(CreateCompressorHelper)((Type), RG_UNIQUE_NAME(CreateCompressor))
|
|
4587
|
+
|
|
4514
4588
|
bool SpliceStream(StreamReader *reader, int64_t max_len, StreamWriter *writer);
|
|
4515
4589
|
|
|
4516
4590
|
// For convenience, don't close them
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// Copyright 2023 Niels Martignène <niels.martignene@protonmail.com>
|
|
2
|
+
|
|
3
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
4
|
+
// this software and associated documentation files (the “Software”), to deal in
|
|
5
|
+
// the Software without restriction, including without limitation the rights to use,
|
|
6
|
+
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
|
7
|
+
// Software, and to permit persons to whom the Software is furnished to do so,
|
|
8
|
+
// subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
// The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
// copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
|
|
14
|
+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
15
|
+
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
16
|
+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
17
|
+
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
18
|
+
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
19
|
+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
20
|
+
// OTHER DEALINGS IN THE SOFTWARE.
|
|
21
|
+
|
|
22
|
+
#include "libcc.hh"
|
|
23
|
+
|
|
24
|
+
#include "vendor/lz4/lib/lz4.h"
|
|
25
|
+
#include "vendor/lz4/lib/lz4hc.h"
|
|
26
|
+
#include "vendor/lz4/lib/lz4frame.h"
|
|
27
|
+
|
|
28
|
+
namespace RG {
|
|
29
|
+
|
|
30
|
+
class LZ4Decompressor: public StreamDecompressor {
|
|
31
|
+
LZ4F_dctx *decoder = nullptr;
|
|
32
|
+
bool done = false;
|
|
33
|
+
|
|
34
|
+
uint8_t in_buf[256 * 1024];
|
|
35
|
+
Size in_len = 0;
|
|
36
|
+
Size in_hint = RG_SIZE(in_buf);
|
|
37
|
+
|
|
38
|
+
uint8_t out_buf[256 * 1024];
|
|
39
|
+
Size out_len = 0;
|
|
40
|
+
|
|
41
|
+
public:
|
|
42
|
+
LZ4Decompressor(StreamReader *reader) : StreamDecompressor(reader) {}
|
|
43
|
+
~LZ4Decompressor();
|
|
44
|
+
|
|
45
|
+
bool Init(CompressionType type) override;
|
|
46
|
+
Size Read(Size max_len, void *out_buf) override;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
LZ4Decompressor::~LZ4Decompressor()
|
|
50
|
+
{
|
|
51
|
+
LZ4F_freeDecompressionContext(decoder);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
bool LZ4Decompressor::Init(CompressionType)
|
|
55
|
+
{
|
|
56
|
+
LZ4F_errorCode_t err = LZ4F_createDecompressionContext(&decoder, LZ4F_VERSION);
|
|
57
|
+
if (LZ4F_isError(err))
|
|
58
|
+
throw std::bad_alloc();
|
|
59
|
+
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
Size LZ4Decompressor::Read(Size max_len, void *user_buf)
|
|
64
|
+
{
|
|
65
|
+
for (;;) {
|
|
66
|
+
if (out_len || done) {
|
|
67
|
+
Size copy_len = std::min(max_len, out_len);
|
|
68
|
+
|
|
69
|
+
out_len -= copy_len;
|
|
70
|
+
memcpy(user_buf, out_buf, copy_len);
|
|
71
|
+
memmove(out_buf, out_buf + copy_len, out_len);
|
|
72
|
+
|
|
73
|
+
SetEOF(!out_len && done);
|
|
74
|
+
return copy_len;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (in_len < in_hint) {
|
|
78
|
+
Size raw_len = ReadRaw(in_hint - in_len, in_buf + in_len);
|
|
79
|
+
if (raw_len < 0)
|
|
80
|
+
return -1;
|
|
81
|
+
in_len += raw_len;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const uint8_t *next_in = in_buf;
|
|
85
|
+
uint8_t *next_out = out_buf + out_len;
|
|
86
|
+
size_t avail_in = (size_t)in_len;
|
|
87
|
+
size_t avail_out = (size_t)(RG_SIZE(out_buf) - out_len);
|
|
88
|
+
|
|
89
|
+
LZ4F_decompressOptions_t opt = {};
|
|
90
|
+
size_t ret = LZ4F_decompress(decoder, next_out, &avail_out, next_in, &avail_in, &opt);
|
|
91
|
+
|
|
92
|
+
if (!ret) {
|
|
93
|
+
done = true;
|
|
94
|
+
} else if (LZ4F_isError(ret)) {
|
|
95
|
+
LogError("Malformed LZ4 stream in '%1': %2", GetFileName(), LZ4F_getErrorName(ret));
|
|
96
|
+
return -1;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
memmove_safe(in_buf, in_buf + avail_in, (size_t)in_len - avail_in);
|
|
100
|
+
in_len -= avail_in;
|
|
101
|
+
in_hint = std::min(RG_SIZE(in_buf), (Size)ret);
|
|
102
|
+
|
|
103
|
+
out_len += (Size)avail_out;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
RG_UNREACHABLE();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
class LZ4Compressor: public StreamCompressor {
|
|
110
|
+
LZ4F_cctx *encoder = nullptr;
|
|
111
|
+
LZ4F_preferences_t prefs = {};
|
|
112
|
+
|
|
113
|
+
HeapArray<uint8_t> dynamic_buf;
|
|
114
|
+
|
|
115
|
+
public:
|
|
116
|
+
LZ4Compressor(StreamWriter *writer) : StreamCompressor(writer) {}
|
|
117
|
+
~LZ4Compressor();
|
|
118
|
+
|
|
119
|
+
bool Init(CompressionType type, CompressionSpeed speed) override;
|
|
120
|
+
bool Write(Span<const uint8_t> buf) override;
|
|
121
|
+
bool Finalize() override;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
LZ4Compressor::~LZ4Compressor()
|
|
125
|
+
{
|
|
126
|
+
LZ4F_freeCompressionContext(encoder);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
bool LZ4Compressor::Init(CompressionType, CompressionSpeed speed)
|
|
130
|
+
{
|
|
131
|
+
LZ4F_errorCode_t err = LZ4F_createCompressionContext(&encoder, LZ4F_VERSION);
|
|
132
|
+
if (LZ4F_isError(err))
|
|
133
|
+
throw std::bad_alloc();
|
|
134
|
+
|
|
135
|
+
switch (speed) {
|
|
136
|
+
case CompressionSpeed::Default: { prefs.compressionLevel = LZ4HC_CLEVEL_MIN; } break;
|
|
137
|
+
case CompressionSpeed::Slow: { prefs.compressionLevel = LZ4HC_CLEVEL_MAX; } break;
|
|
138
|
+
case CompressionSpeed::Fast: { prefs.compressionLevel = 0; } break;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
dynamic_buf.Grow(LZ4F_HEADER_SIZE_MAX);
|
|
142
|
+
|
|
143
|
+
size_t ret = LZ4F_compressBegin(encoder, dynamic_buf.end(), dynamic_buf.capacity - dynamic_buf.len, &prefs);
|
|
144
|
+
|
|
145
|
+
if (LZ4F_isError(ret)) {
|
|
146
|
+
LogError("Failed to start LZ4 stream for '%1': %2", GetFileName(), LZ4F_getErrorName(ret));
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
dynamic_buf.len += ret;
|
|
151
|
+
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
bool LZ4Compressor::Write(Span<const uint8_t> buf)
|
|
156
|
+
{
|
|
157
|
+
size_t needed = LZ4F_compressBound((size_t)buf.len, &prefs);
|
|
158
|
+
dynamic_buf.Grow((Size)needed);
|
|
159
|
+
|
|
160
|
+
size_t ret = LZ4F_compressUpdate(encoder, dynamic_buf.end(), (size_t)(dynamic_buf.capacity - dynamic_buf.len),
|
|
161
|
+
buf.ptr, (size_t)buf.len, nullptr);
|
|
162
|
+
|
|
163
|
+
if (LZ4F_isError(ret)) {
|
|
164
|
+
LogError("Failed to write LZ4 stream for '%1': %2", GetFileName(), LZ4F_getErrorName(ret));
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
dynamic_buf.len += (Size)ret;
|
|
169
|
+
|
|
170
|
+
if (dynamic_buf.len >= 512) {
|
|
171
|
+
if (!WriteRaw(dynamic_buf))
|
|
172
|
+
return false;
|
|
173
|
+
dynamic_buf.len = 0;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
bool LZ4Compressor::Finalize()
|
|
180
|
+
{
|
|
181
|
+
size_t needed = LZ4F_compressBound(0, &prefs);
|
|
182
|
+
dynamic_buf.Grow((Size)needed);
|
|
183
|
+
|
|
184
|
+
size_t ret = LZ4F_compressEnd(encoder, dynamic_buf.end(),
|
|
185
|
+
(size_t)(dynamic_buf.capacity - dynamic_buf.len), nullptr);
|
|
186
|
+
|
|
187
|
+
if (LZ4F_isError(ret)) {
|
|
188
|
+
LogError("Failed to finalize LZ4 stream for '%1': %2", GetFileName(), LZ4F_getErrorName(ret));
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
dynamic_buf.len += (Size)ret;
|
|
193
|
+
|
|
194
|
+
if (!WriteRaw(dynamic_buf))
|
|
195
|
+
return false;
|
|
196
|
+
dynamic_buf.len = 0;
|
|
197
|
+
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
RG_REGISTER_DECOMPRESSOR(CompressionType::LZ4, LZ4Decompressor);
|
|
202
|
+
RG_REGISTER_COMPRESSOR(CompressionType::LZ4, LZ4Compressor);
|
|
203
|
+
|
|
204
|
+
}
|