deflate-ruby 1.0.1 → 1.0.3
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.
- checksums.yaml +4 -4
- data/CLAUDE.md +95 -92
- data/GEM_VERIFICATION_REPORT.md +140 -0
- data/LICENSE.txt +6 -6
- data/README.md +87 -65
- data/Rakefile +23 -0
- data/ext/deflate_ruby/{libdeflate/lib/x86/adler32_impl.h → adler32_impl.h} +8 -7
- data/ext/deflate_ruby/common_defs.h +748 -0
- data/ext/deflate_ruby/{libdeflate/lib/x86/cpu_features.c → cpu_features.c} +46 -16
- data/ext/deflate_ruby/{libdeflate/lib/x86/cpu_features.h → cpu_features.h} +2 -1
- data/ext/deflate_ruby/{libdeflate/lib/x86/crc32_impl.h → crc32_impl.h} +22 -23
- data/ext/deflate_ruby/{libdeflate/lib/crc32_multipliers.h → crc32_multipliers.h} +2 -4
- data/ext/deflate_ruby/{libdeflate/lib/x86/crc32_pclmul_template.h → crc32_pclmul_template.h} +23 -94
- data/ext/deflate_ruby/{libdeflate/lib/crc32_tables.h → crc32_tables.h} +1 -1
- data/ext/deflate_ruby/{libdeflate/lib/deflate_compress.c → deflate_compress.c} +59 -60
- data/ext/deflate_ruby/deflate_ruby.c +392 -218
- data/ext/deflate_ruby/deflate_ruby.h +6 -0
- data/ext/deflate_ruby/extconf.rb +35 -25
- data/ext/deflate_ruby/libdeflate/adler32.c +162 -0
- data/ext/deflate_ruby/libdeflate/{lib/arm → arm}/adler32_impl.h +14 -7
- data/ext/deflate_ruby/libdeflate/{lib/arm → arm}/crc32_impl.h +25 -31
- data/ext/deflate_ruby/libdeflate/arm/crc32_pmull_helpers.h +156 -0
- data/ext/deflate_ruby/libdeflate/arm/crc32_pmull_wide.h +226 -0
- data/ext/deflate_ruby/libdeflate/bt_matchfinder.h +342 -0
- data/ext/deflate_ruby/libdeflate/common_defs.h +2 -1
- data/ext/deflate_ruby/libdeflate/cpu_features_common.h +93 -0
- data/ext/deflate_ruby/libdeflate/crc32.c +262 -0
- data/ext/deflate_ruby/libdeflate/crc32_multipliers.h +375 -0
- data/ext/deflate_ruby/libdeflate/crc32_tables.h +587 -0
- data/ext/deflate_ruby/libdeflate/decompress_template.h +777 -0
- data/ext/deflate_ruby/libdeflate/deflate_compress.c +4128 -0
- data/ext/deflate_ruby/libdeflate/deflate_compress.h +15 -0
- data/ext/deflate_ruby/libdeflate/deflate_constants.h +56 -0
- data/ext/deflate_ruby/libdeflate/deflate_decompress.c +1208 -0
- data/ext/deflate_ruby/libdeflate/gzip_compress.c +90 -0
- data/ext/deflate_ruby/libdeflate/gzip_constants.h +45 -0
- data/ext/deflate_ruby/libdeflate/gzip_decompress.c +144 -0
- data/ext/deflate_ruby/libdeflate/hc_matchfinder.h +401 -0
- data/ext/deflate_ruby/libdeflate/ht_matchfinder.h +234 -0
- data/ext/deflate_ruby/libdeflate/lib_common.h +106 -0
- data/ext/deflate_ruby/libdeflate/libdeflate.h +2 -2
- data/ext/deflate_ruby/libdeflate/{lib/matchfinder_common.h → matchfinder_common.h} +3 -3
- data/ext/deflate_ruby/libdeflate/x86/adler32_impl.h +135 -0
- data/ext/deflate_ruby/libdeflate/x86/adler32_template.h +518 -0
- data/ext/deflate_ruby/libdeflate/x86/cpu_features.c +213 -0
- data/ext/deflate_ruby/libdeflate/x86/cpu_features.h +170 -0
- data/ext/deflate_ruby/libdeflate/x86/crc32_impl.h +159 -0
- data/ext/deflate_ruby/libdeflate/x86/crc32_pclmul_template.h +424 -0
- data/ext/deflate_ruby/libdeflate/x86/decompress_impl.h +57 -0
- data/ext/deflate_ruby/libdeflate.h +411 -0
- data/ext/deflate_ruby/matchfinder_common.h +224 -0
- data/ext/deflate_ruby/matchfinder_impl.h +122 -0
- data/ext/deflate_ruby/utils.c +141 -0
- data/ext/deflate_ruby/zlib_compress.c +82 -0
- data/ext/deflate_ruby/zlib_constants.h +21 -0
- data/ext/deflate_ruby/zlib_decompress.c +104 -0
- data/lib/deflate_ruby/version.rb +1 -1
- data/lib/deflate_ruby.rb +1 -63
- data/sig/deflate_ruby.rbs +4 -0
- data/test/test_deflate_ruby.rb +220 -0
- data/test/test_helper.rb +6 -0
- metadata +90 -144
- data/ext/deflate_ruby/libdeflate/CMakeLists.txt +0 -270
- data/ext/deflate_ruby/libdeflate/NEWS.md +0 -494
- data/ext/deflate_ruby/libdeflate/README.md +0 -228
- data/ext/deflate_ruby/libdeflate/libdeflate-config.cmake.in +0 -3
- data/ext/deflate_ruby/libdeflate/libdeflate.pc.in +0 -18
- data/ext/deflate_ruby/libdeflate/programs/CMakeLists.txt +0 -105
- data/ext/deflate_ruby/libdeflate/programs/benchmark.c +0 -696
- data/ext/deflate_ruby/libdeflate/programs/checksum.c +0 -218
- data/ext/deflate_ruby/libdeflate/programs/config.h.in +0 -19
- data/ext/deflate_ruby/libdeflate/programs/gzip.c +0 -688
- data/ext/deflate_ruby/libdeflate/programs/prog_util.c +0 -521
- data/ext/deflate_ruby/libdeflate/programs/prog_util.h +0 -225
- data/ext/deflate_ruby/libdeflate/programs/test_checksums.c +0 -200
- data/ext/deflate_ruby/libdeflate/programs/test_custom_malloc.c +0 -155
- data/ext/deflate_ruby/libdeflate/programs/test_incomplete_codes.c +0 -385
- data/ext/deflate_ruby/libdeflate/programs/test_invalid_streams.c +0 -130
- data/ext/deflate_ruby/libdeflate/programs/test_litrunlen_overflow.c +0 -72
- data/ext/deflate_ruby/libdeflate/programs/test_overread.c +0 -95
- data/ext/deflate_ruby/libdeflate/programs/test_slow_decompression.c +0 -472
- data/ext/deflate_ruby/libdeflate/programs/test_trailing_bytes.c +0 -151
- data/ext/deflate_ruby/libdeflate/programs/test_util.c +0 -237
- data/ext/deflate_ruby/libdeflate/programs/test_util.h +0 -61
- data/ext/deflate_ruby/libdeflate/programs/tgetopt.c +0 -118
- data/ext/deflate_ruby/libdeflate/scripts/android_build.sh +0 -118
- data/ext/deflate_ruby/libdeflate/scripts/android_tests.sh +0 -69
- data/ext/deflate_ruby/libdeflate/scripts/benchmark.sh +0 -10
- data/ext/deflate_ruby/libdeflate/scripts/checksum.sh +0 -10
- data/ext/deflate_ruby/libdeflate/scripts/checksum_benchmarks.sh +0 -253
- data/ext/deflate_ruby/libdeflate/scripts/cmake-helper.sh +0 -17
- data/ext/deflate_ruby/libdeflate/scripts/deflate_benchmarks.sh +0 -119
- data/ext/deflate_ruby/libdeflate/scripts/exec_tests.sh +0 -38
- data/ext/deflate_ruby/libdeflate/scripts/gen-release-archives.sh +0 -37
- data/ext/deflate_ruby/libdeflate/scripts/gen_bitreverse_tab.py +0 -19
- data/ext/deflate_ruby/libdeflate/scripts/gen_crc32_multipliers.c +0 -199
- data/ext/deflate_ruby/libdeflate/scripts/gen_crc32_tables.c +0 -105
- data/ext/deflate_ruby/libdeflate/scripts/gen_default_litlen_costs.py +0 -44
- data/ext/deflate_ruby/libdeflate/scripts/gen_offset_slot_map.py +0 -29
- data/ext/deflate_ruby/libdeflate/scripts/gzip_tests.sh +0 -523
- data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/deflate_compress/corpus/0 +0 -0
- data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/deflate_compress/fuzz.c +0 -95
- data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/deflate_decompress/corpus/0 +0 -3
- data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/deflate_decompress/fuzz.c +0 -62
- data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/fuzz.sh +0 -108
- data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/gzip_decompress/corpus/0 +0 -0
- data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/gzip_decompress/fuzz.c +0 -19
- data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/zlib_decompress/corpus/0 +0 -3
- data/ext/deflate_ruby/libdeflate/scripts/libFuzzer/zlib_decompress/fuzz.c +0 -19
- data/ext/deflate_ruby/libdeflate/scripts/run_tests.sh +0 -416
- data/ext/deflate_ruby/libdeflate/scripts/toolchain-i686-w64-mingw32.cmake +0 -8
- data/ext/deflate_ruby/libdeflate/scripts/toolchain-x86_64-w64-mingw32.cmake +0 -8
- /data/ext/deflate_ruby/{libdeflate/lib/adler32.c → adler32.c} +0 -0
- /data/ext/deflate_ruby/{libdeflate/lib/x86/adler32_template.h → adler32_template.h} +0 -0
- /data/ext/deflate_ruby/{libdeflate/lib/bt_matchfinder.h → bt_matchfinder.h} +0 -0
- /data/ext/deflate_ruby/{libdeflate/lib/cpu_features_common.h → cpu_features_common.h} +0 -0
- /data/ext/deflate_ruby/{libdeflate/lib/crc32.c → crc32.c} +0 -0
- /data/ext/deflate_ruby/{libdeflate/lib/arm/crc32_pmull_helpers.h → crc32_pmull_helpers.h} +0 -0
- /data/ext/deflate_ruby/{libdeflate/lib/arm/crc32_pmull_wide.h → crc32_pmull_wide.h} +0 -0
- /data/ext/deflate_ruby/{libdeflate/lib/x86/decompress_impl.h → decompress_impl.h} +0 -0
- /data/ext/deflate_ruby/{libdeflate/lib/decompress_template.h → decompress_template.h} +0 -0
- /data/ext/deflate_ruby/{libdeflate/lib/deflate_compress.h → deflate_compress.h} +0 -0
- /data/ext/deflate_ruby/{libdeflate/lib/deflate_constants.h → deflate_constants.h} +0 -0
- /data/ext/deflate_ruby/{libdeflate/lib/deflate_decompress.c → deflate_decompress.c} +0 -0
- /data/ext/deflate_ruby/{libdeflate/lib/gzip_compress.c → gzip_compress.c} +0 -0
- /data/ext/deflate_ruby/{libdeflate/lib/gzip_constants.h → gzip_constants.h} +0 -0
- /data/ext/deflate_ruby/{libdeflate/lib/gzip_decompress.c → gzip_decompress.c} +0 -0
- /data/ext/deflate_ruby/{libdeflate/lib/hc_matchfinder.h → hc_matchfinder.h} +0 -0
- /data/ext/deflate_ruby/{libdeflate/lib/ht_matchfinder.h → ht_matchfinder.h} +0 -0
- /data/ext/deflate_ruby/{libdeflate/lib/lib_common.h → lib_common.h} +0 -0
- /data/ext/deflate_ruby/libdeflate/{lib/arm → arm}/cpu_features.c +0 -0
- /data/ext/deflate_ruby/libdeflate/{lib/arm → arm}/cpu_features.h +0 -0
- /data/ext/deflate_ruby/libdeflate/{lib/arm → arm}/matchfinder_impl.h +0 -0
- /data/ext/deflate_ruby/libdeflate/{lib/riscv → riscv}/matchfinder_impl.h +0 -0
- /data/ext/deflate_ruby/libdeflate/{lib/utils.c → utils.c} +0 -0
- /data/ext/deflate_ruby/libdeflate/{lib/x86 → x86}/matchfinder_impl.h +0 -0
- /data/ext/deflate_ruby/libdeflate/{lib/zlib_compress.c → zlib_compress.c} +0 -0
- /data/ext/deflate_ruby/libdeflate/{lib/zlib_constants.h → zlib_constants.h} +0 -0
- /data/ext/deflate_ruby/libdeflate/{lib/zlib_decompress.c → zlib_decompress.c} +0 -0
|
@@ -1,301 +1,475 @@
|
|
|
1
|
-
#include
|
|
2
|
-
#include "libdeflate.h"
|
|
1
|
+
#include "deflate_ruby.h"
|
|
2
|
+
#include "libdeflate/libdeflate.h"
|
|
3
3
|
#include <string.h>
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
VALUE rb_mDeflateRuby;
|
|
6
|
+
VALUE rb_cCompressor;
|
|
7
|
+
VALUE rb_cDecompressor;
|
|
8
|
+
VALUE rb_eDeflateError;
|
|
9
|
+
VALUE rb_eCompressionError;
|
|
10
|
+
VALUE rb_eDecompressionError;
|
|
11
|
+
|
|
12
|
+
// Compressor wrapper structure
|
|
13
|
+
typedef struct {
|
|
14
|
+
struct libdeflate_compressor *compressor;
|
|
15
|
+
} CompressorData;
|
|
16
|
+
|
|
17
|
+
// Decompressor wrapper structure
|
|
18
|
+
typedef struct {
|
|
19
|
+
struct libdeflate_decompressor *decompressor;
|
|
20
|
+
} DecompressorData;
|
|
21
|
+
|
|
22
|
+
// Free compressor
|
|
23
|
+
static void compressor_free(void *ptr) {
|
|
24
|
+
CompressorData *data = (CompressorData *)ptr;
|
|
25
|
+
if (data->compressor) {
|
|
26
|
+
libdeflate_free_compressor(data->compressor);
|
|
27
|
+
data->compressor = NULL;
|
|
28
|
+
}
|
|
29
|
+
xfree(data);
|
|
30
|
+
}
|
|
7
31
|
|
|
8
|
-
//
|
|
9
|
-
static
|
|
10
|
-
|
|
32
|
+
// Compressor allocation
|
|
33
|
+
static const rb_data_type_t compressor_type = {
|
|
34
|
+
"DeflateRuby::Compressor",
|
|
35
|
+
{NULL, compressor_free, NULL},
|
|
36
|
+
0, 0,
|
|
37
|
+
RUBY_TYPED_FREE_IMMEDIATELY
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Free decompressor
|
|
41
|
+
static void decompressor_free(void *ptr) {
|
|
42
|
+
DecompressorData *data = (DecompressorData *)ptr;
|
|
43
|
+
if (data->decompressor) {
|
|
44
|
+
libdeflate_free_decompressor(data->decompressor);
|
|
45
|
+
data->decompressor = NULL;
|
|
46
|
+
}
|
|
47
|
+
xfree(data);
|
|
11
48
|
}
|
|
12
49
|
|
|
13
|
-
//
|
|
14
|
-
static
|
|
15
|
-
|
|
16
|
-
|
|
50
|
+
// Decompressor allocation
|
|
51
|
+
static const rb_data_type_t decompressor_type = {
|
|
52
|
+
"DeflateRuby::Decompressor",
|
|
53
|
+
{NULL, decompressor_free, NULL},
|
|
54
|
+
0, 0,
|
|
55
|
+
RUBY_TYPED_FREE_IMMEDIATELY
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Compressor.new(level: 6)
|
|
59
|
+
static VALUE compressor_initialize(int argc, VALUE *argv, VALUE self) {
|
|
60
|
+
VALUE opts;
|
|
61
|
+
rb_scan_args(argc, argv, "0:", &opts);
|
|
62
|
+
|
|
63
|
+
int level = 6; // default compression level
|
|
64
|
+
|
|
65
|
+
if (!NIL_P(opts)) {
|
|
66
|
+
VALUE level_val = rb_hash_aref(opts, ID2SYM(rb_intern("level")));
|
|
67
|
+
if (!NIL_P(level_val)) {
|
|
68
|
+
level = NUM2INT(level_val);
|
|
69
|
+
if (level < 0 || level > 12) {
|
|
70
|
+
rb_raise(rb_eArgError, "compression level must be between 0 and 12");
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
17
74
|
|
|
18
|
-
|
|
75
|
+
CompressorData *data;
|
|
76
|
+
TypedData_Get_Struct(self, CompressorData, &compressor_type, data);
|
|
19
77
|
|
|
20
|
-
|
|
21
|
-
if (
|
|
22
|
-
rb_raise(
|
|
78
|
+
data->compressor = libdeflate_alloc_compressor(level);
|
|
79
|
+
if (!data->compressor) {
|
|
80
|
+
rb_raise(rb_eCompressionError, "failed to allocate compressor");
|
|
23
81
|
}
|
|
24
82
|
|
|
25
|
-
|
|
26
|
-
|
|
83
|
+
return self;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Allocate compressor
|
|
87
|
+
static VALUE compressor_alloc(VALUE klass) {
|
|
88
|
+
CompressorData *data = ALLOC(CompressorData);
|
|
89
|
+
data->compressor = NULL;
|
|
90
|
+
return TypedData_Wrap_Struct(klass, &compressor_type, data);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// compressor.deflate_compress(data) -> String
|
|
94
|
+
static VALUE compressor_deflate_compress(VALUE self, VALUE input) {
|
|
95
|
+
StringValue(input);
|
|
27
96
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
97
|
+
CompressorData *data;
|
|
98
|
+
TypedData_Get_Struct(self, CompressorData, &compressor_type, data);
|
|
99
|
+
|
|
100
|
+
if (!data->compressor) {
|
|
101
|
+
rb_raise(rb_eCompressionError, "compressor is closed");
|
|
31
102
|
}
|
|
32
103
|
|
|
33
|
-
|
|
34
|
-
|
|
104
|
+
const char *in_data = RSTRING_PTR(input);
|
|
105
|
+
size_t in_size = RSTRING_LEN(input);
|
|
35
106
|
|
|
36
|
-
size_t
|
|
37
|
-
|
|
38
|
-
in_data,
|
|
39
|
-
in_size,
|
|
40
|
-
RSTRING_PTR(out_str),
|
|
41
|
-
max_out_size
|
|
42
|
-
);
|
|
107
|
+
size_t out_bound = libdeflate_deflate_compress_bound(data->compressor, in_size);
|
|
108
|
+
VALUE output = rb_str_buf_new(out_bound);
|
|
43
109
|
|
|
44
|
-
|
|
110
|
+
size_t out_size = libdeflate_deflate_compress(
|
|
111
|
+
data->compressor,
|
|
112
|
+
in_data, in_size,
|
|
113
|
+
RSTRING_PTR(output), out_bound
|
|
114
|
+
);
|
|
45
115
|
|
|
46
|
-
if (
|
|
47
|
-
|
|
116
|
+
if (out_size == 0) {
|
|
117
|
+
rb_raise(rb_eCompressionError, "compression failed");
|
|
48
118
|
}
|
|
49
119
|
|
|
50
|
-
rb_str_set_len(
|
|
51
|
-
return
|
|
120
|
+
rb_str_set_len(output, out_size);
|
|
121
|
+
return output;
|
|
52
122
|
}
|
|
53
123
|
|
|
54
|
-
//
|
|
55
|
-
static VALUE
|
|
56
|
-
|
|
124
|
+
// compressor.zlib_compress(data) -> String
|
|
125
|
+
static VALUE compressor_zlib_compress(VALUE self, VALUE input) {
|
|
126
|
+
StringValue(input);
|
|
57
127
|
|
|
58
|
-
|
|
59
|
-
|
|
128
|
+
CompressorData *data;
|
|
129
|
+
TypedData_Get_Struct(self, CompressorData, &compressor_type, data);
|
|
60
130
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
raise_deflate_error("Failed to allocate decompressor");
|
|
131
|
+
if (!data->compressor) {
|
|
132
|
+
rb_raise(rb_eCompressionError, "compressor is closed");
|
|
64
133
|
}
|
|
65
134
|
|
|
66
|
-
|
|
67
|
-
size_t
|
|
68
|
-
VALUE out_str = rb_str_buf_new(out_size);
|
|
69
|
-
size_t actual_size;
|
|
70
|
-
|
|
71
|
-
enum libdeflate_result result;
|
|
72
|
-
|
|
73
|
-
// Try decompression, increase buffer if needed
|
|
74
|
-
for (int attempts = 0; attempts < 10; attempts++) {
|
|
75
|
-
result = libdeflate_deflate_decompress(
|
|
76
|
-
decompressor,
|
|
77
|
-
in_data,
|
|
78
|
-
in_size,
|
|
79
|
-
RSTRING_PTR(out_str),
|
|
80
|
-
out_size,
|
|
81
|
-
&actual_size
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
if (result == LIBDEFLATE_SUCCESS) {
|
|
85
|
-
break;
|
|
86
|
-
} else if (result == LIBDEFLATE_INSUFFICIENT_SPACE) {
|
|
87
|
-
out_size *= 2;
|
|
88
|
-
rb_str_resize(out_str, out_size);
|
|
89
|
-
} else {
|
|
90
|
-
libdeflate_free_decompressor(decompressor);
|
|
91
|
-
raise_deflate_error("Decompression failed: invalid or corrupted data");
|
|
92
|
-
}
|
|
93
|
-
}
|
|
135
|
+
const char *in_data = RSTRING_PTR(input);
|
|
136
|
+
size_t in_size = RSTRING_LEN(input);
|
|
94
137
|
|
|
95
|
-
|
|
138
|
+
size_t out_bound = libdeflate_zlib_compress_bound(data->compressor, in_size);
|
|
139
|
+
VALUE output = rb_str_buf_new(out_bound);
|
|
96
140
|
|
|
97
|
-
|
|
98
|
-
|
|
141
|
+
size_t out_size = libdeflate_zlib_compress(
|
|
142
|
+
data->compressor,
|
|
143
|
+
in_data, in_size,
|
|
144
|
+
RSTRING_PTR(output), out_bound
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
if (out_size == 0) {
|
|
148
|
+
rb_raise(rb_eCompressionError, "compression failed");
|
|
99
149
|
}
|
|
100
150
|
|
|
101
|
-
rb_str_set_len(
|
|
102
|
-
return
|
|
151
|
+
rb_str_set_len(output, out_size);
|
|
152
|
+
return output;
|
|
103
153
|
}
|
|
104
154
|
|
|
105
|
-
//
|
|
106
|
-
static VALUE
|
|
107
|
-
|
|
108
|
-
rb_scan_args(argc, argv, "11", &data, &level_val);
|
|
155
|
+
// compressor.gzip_compress(data) -> String
|
|
156
|
+
static VALUE compressor_gzip_compress(VALUE self, VALUE input) {
|
|
157
|
+
StringValue(input);
|
|
109
158
|
|
|
110
|
-
|
|
159
|
+
CompressorData *data;
|
|
160
|
+
TypedData_Get_Struct(self, CompressorData, &compressor_type, data);
|
|
111
161
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
rb_raise(rb_eArgError, "compression level must be between 1 and 12");
|
|
162
|
+
if (!data->compressor) {
|
|
163
|
+
rb_raise(rb_eCompressionError, "compressor is closed");
|
|
115
164
|
}
|
|
116
165
|
|
|
117
|
-
const char *in_data = RSTRING_PTR(
|
|
118
|
-
size_t in_size = RSTRING_LEN(
|
|
119
|
-
|
|
120
|
-
struct libdeflate_compressor *compressor = libdeflate_alloc_compressor(level);
|
|
121
|
-
if (!compressor) {
|
|
122
|
-
raise_deflate_error("Failed to allocate compressor");
|
|
123
|
-
}
|
|
166
|
+
const char *in_data = RSTRING_PTR(input);
|
|
167
|
+
size_t in_size = RSTRING_LEN(input);
|
|
124
168
|
|
|
125
|
-
size_t
|
|
126
|
-
VALUE
|
|
169
|
+
size_t out_bound = libdeflate_gzip_compress_bound(data->compressor, in_size);
|
|
170
|
+
VALUE output = rb_str_buf_new(out_bound);
|
|
127
171
|
|
|
128
|
-
size_t
|
|
129
|
-
compressor,
|
|
130
|
-
in_data,
|
|
131
|
-
|
|
132
|
-
RSTRING_PTR(out_str),
|
|
133
|
-
max_out_size
|
|
172
|
+
size_t out_size = libdeflate_gzip_compress(
|
|
173
|
+
data->compressor,
|
|
174
|
+
in_data, in_size,
|
|
175
|
+
RSTRING_PTR(output), out_bound
|
|
134
176
|
);
|
|
135
177
|
|
|
136
|
-
|
|
178
|
+
if (out_size == 0) {
|
|
179
|
+
rb_raise(rb_eCompressionError, "compression failed");
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
rb_str_set_len(output, out_size);
|
|
183
|
+
return output;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// compressor.deflate_compress_bound(size) -> Integer
|
|
187
|
+
static VALUE compressor_deflate_compress_bound(VALUE self, VALUE size) {
|
|
188
|
+
CompressorData *data;
|
|
189
|
+
TypedData_Get_Struct(self, CompressorData, &compressor_type, data);
|
|
137
190
|
|
|
138
|
-
if (
|
|
139
|
-
|
|
191
|
+
if (!data->compressor) {
|
|
192
|
+
rb_raise(rb_eCompressionError, "compressor is closed");
|
|
140
193
|
}
|
|
141
194
|
|
|
142
|
-
|
|
143
|
-
return
|
|
195
|
+
size_t bound = libdeflate_deflate_compress_bound(data->compressor, NUM2SIZET(size));
|
|
196
|
+
return SIZET2NUM(bound);
|
|
144
197
|
}
|
|
145
198
|
|
|
146
|
-
//
|
|
147
|
-
static VALUE
|
|
148
|
-
|
|
199
|
+
// compressor.zlib_compress_bound(size) -> Integer
|
|
200
|
+
static VALUE compressor_zlib_compress_bound(VALUE self, VALUE size) {
|
|
201
|
+
CompressorData *data;
|
|
202
|
+
TypedData_Get_Struct(self, CompressorData, &compressor_type, data);
|
|
203
|
+
|
|
204
|
+
if (!data->compressor) {
|
|
205
|
+
rb_raise(rb_eCompressionError, "compressor is closed");
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
size_t bound = libdeflate_zlib_compress_bound(data->compressor, NUM2SIZET(size));
|
|
209
|
+
return SIZET2NUM(bound);
|
|
210
|
+
}
|
|
149
211
|
|
|
150
|
-
|
|
151
|
-
|
|
212
|
+
// compressor.gzip_compress_bound(size) -> Integer
|
|
213
|
+
static VALUE compressor_gzip_compress_bound(VALUE self, VALUE size) {
|
|
214
|
+
CompressorData *data;
|
|
215
|
+
TypedData_Get_Struct(self, CompressorData, &compressor_type, data);
|
|
152
216
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
raise_deflate_error("Failed to allocate decompressor");
|
|
217
|
+
if (!data->compressor) {
|
|
218
|
+
rb_raise(rb_eCompressionError, "compressor is closed");
|
|
156
219
|
}
|
|
157
220
|
|
|
158
|
-
size_t
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
out_size,
|
|
171
|
-
&actual_size
|
|
172
|
-
);
|
|
173
|
-
|
|
174
|
-
if (result == LIBDEFLATE_SUCCESS) {
|
|
175
|
-
break;
|
|
176
|
-
} else if (result == LIBDEFLATE_INSUFFICIENT_SPACE) {
|
|
177
|
-
out_size *= 2;
|
|
178
|
-
rb_str_resize(out_str, out_size);
|
|
179
|
-
} else {
|
|
180
|
-
libdeflate_free_decompressor(decompressor);
|
|
181
|
-
raise_deflate_error("Decompression failed: invalid or corrupted zlib data");
|
|
182
|
-
}
|
|
221
|
+
size_t bound = libdeflate_gzip_compress_bound(data->compressor, NUM2SIZET(size));
|
|
222
|
+
return SIZET2NUM(bound);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// compressor.close
|
|
226
|
+
static VALUE compressor_close(VALUE self) {
|
|
227
|
+
CompressorData *data;
|
|
228
|
+
TypedData_Get_Struct(self, CompressorData, &compressor_type, data);
|
|
229
|
+
|
|
230
|
+
if (data->compressor) {
|
|
231
|
+
libdeflate_free_compressor(data->compressor);
|
|
232
|
+
data->compressor = NULL;
|
|
183
233
|
}
|
|
184
234
|
|
|
185
|
-
|
|
235
|
+
return Qnil;
|
|
236
|
+
}
|
|
186
237
|
|
|
187
|
-
|
|
188
|
-
|
|
238
|
+
// Decompressor.new
|
|
239
|
+
static VALUE decompressor_initialize(VALUE self) {
|
|
240
|
+
DecompressorData *data;
|
|
241
|
+
TypedData_Get_Struct(self, DecompressorData, &decompressor_type, data);
|
|
242
|
+
|
|
243
|
+
data->decompressor = libdeflate_alloc_decompressor();
|
|
244
|
+
if (!data->decompressor) {
|
|
245
|
+
rb_raise(rb_eDecompressionError, "failed to allocate decompressor");
|
|
189
246
|
}
|
|
190
247
|
|
|
191
|
-
|
|
192
|
-
|
|
248
|
+
return self;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Allocate decompressor
|
|
252
|
+
static VALUE decompressor_alloc(VALUE klass) {
|
|
253
|
+
DecompressorData *data = ALLOC(DecompressorData);
|
|
254
|
+
data->decompressor = NULL;
|
|
255
|
+
return TypedData_Wrap_Struct(klass, &decompressor_type, data);
|
|
193
256
|
}
|
|
194
257
|
|
|
195
|
-
//
|
|
196
|
-
static VALUE
|
|
197
|
-
|
|
198
|
-
rb_scan_args(argc, argv, "11", &data, &level_val);
|
|
258
|
+
// decompressor.deflate_decompress(data, output_size) -> String
|
|
259
|
+
static VALUE decompressor_deflate_decompress(VALUE self, VALUE input, VALUE out_size_val) {
|
|
260
|
+
StringValue(input);
|
|
199
261
|
|
|
200
|
-
|
|
262
|
+
DecompressorData *data;
|
|
263
|
+
TypedData_Get_Struct(self, DecompressorData, &decompressor_type, data);
|
|
201
264
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
rb_raise(rb_eArgError, "compression level must be between 1 and 12");
|
|
265
|
+
if (!data->decompressor) {
|
|
266
|
+
rb_raise(rb_eDecompressionError, "decompressor is closed");
|
|
205
267
|
}
|
|
206
268
|
|
|
207
|
-
const char *in_data = RSTRING_PTR(
|
|
208
|
-
size_t in_size = RSTRING_LEN(
|
|
269
|
+
const char *in_data = RSTRING_PTR(input);
|
|
270
|
+
size_t in_size = RSTRING_LEN(input);
|
|
271
|
+
size_t out_size = NUM2SIZET(out_size_val);
|
|
209
272
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
273
|
+
VALUE output = rb_str_buf_new(out_size);
|
|
274
|
+
size_t actual_out_size;
|
|
275
|
+
|
|
276
|
+
enum libdeflate_result result = libdeflate_deflate_decompress(
|
|
277
|
+
data->decompressor,
|
|
278
|
+
in_data, in_size,
|
|
279
|
+
RSTRING_PTR(output), out_size,
|
|
280
|
+
&actual_out_size
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
if (result != LIBDEFLATE_SUCCESS) {
|
|
284
|
+
const char *msg;
|
|
285
|
+
switch (result) {
|
|
286
|
+
case LIBDEFLATE_BAD_DATA:
|
|
287
|
+
msg = "bad compressed data";
|
|
288
|
+
break;
|
|
289
|
+
case LIBDEFLATE_SHORT_OUTPUT:
|
|
290
|
+
msg = "output buffer too small";
|
|
291
|
+
break;
|
|
292
|
+
case LIBDEFLATE_INSUFFICIENT_SPACE:
|
|
293
|
+
msg = "insufficient space";
|
|
294
|
+
break;
|
|
295
|
+
default:
|
|
296
|
+
msg = "decompression failed";
|
|
297
|
+
}
|
|
298
|
+
rb_raise(rb_eDecompressionError, "%s", msg);
|
|
213
299
|
}
|
|
214
300
|
|
|
215
|
-
|
|
216
|
-
|
|
301
|
+
rb_str_set_len(output, actual_out_size);
|
|
302
|
+
return output;
|
|
303
|
+
}
|
|
217
304
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
305
|
+
// decompressor.zlib_decompress(data, output_size) -> String
|
|
306
|
+
static VALUE decompressor_zlib_decompress(VALUE self, VALUE input, VALUE out_size_val) {
|
|
307
|
+
StringValue(input);
|
|
308
|
+
|
|
309
|
+
DecompressorData *data;
|
|
310
|
+
TypedData_Get_Struct(self, DecompressorData, &decompressor_type, data);
|
|
311
|
+
|
|
312
|
+
if (!data->decompressor) {
|
|
313
|
+
rb_raise(rb_eDecompressionError, "decompressor is closed");
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const char *in_data = RSTRING_PTR(input);
|
|
317
|
+
size_t in_size = RSTRING_LEN(input);
|
|
318
|
+
size_t out_size = NUM2SIZET(out_size_val);
|
|
225
319
|
|
|
226
|
-
|
|
320
|
+
VALUE output = rb_str_buf_new(out_size);
|
|
321
|
+
size_t actual_out_size;
|
|
227
322
|
|
|
228
|
-
|
|
229
|
-
|
|
323
|
+
enum libdeflate_result result = libdeflate_zlib_decompress(
|
|
324
|
+
data->decompressor,
|
|
325
|
+
in_data, in_size,
|
|
326
|
+
RSTRING_PTR(output), out_size,
|
|
327
|
+
&actual_out_size
|
|
328
|
+
);
|
|
329
|
+
|
|
330
|
+
if (result != LIBDEFLATE_SUCCESS) {
|
|
331
|
+
const char *msg;
|
|
332
|
+
switch (result) {
|
|
333
|
+
case LIBDEFLATE_BAD_DATA:
|
|
334
|
+
msg = "bad compressed data";
|
|
335
|
+
break;
|
|
336
|
+
case LIBDEFLATE_SHORT_OUTPUT:
|
|
337
|
+
msg = "output buffer too small";
|
|
338
|
+
break;
|
|
339
|
+
case LIBDEFLATE_INSUFFICIENT_SPACE:
|
|
340
|
+
msg = "insufficient space";
|
|
341
|
+
break;
|
|
342
|
+
default:
|
|
343
|
+
msg = "decompression failed";
|
|
344
|
+
}
|
|
345
|
+
rb_raise(rb_eDecompressionError, "%s", msg);
|
|
230
346
|
}
|
|
231
347
|
|
|
232
|
-
rb_str_set_len(
|
|
233
|
-
return
|
|
348
|
+
rb_str_set_len(output, actual_out_size);
|
|
349
|
+
return output;
|
|
234
350
|
}
|
|
235
351
|
|
|
236
|
-
//
|
|
237
|
-
static VALUE
|
|
238
|
-
|
|
352
|
+
// decompressor.gzip_decompress(data, output_size) -> String
|
|
353
|
+
static VALUE decompressor_gzip_decompress(VALUE self, VALUE input, VALUE out_size_val) {
|
|
354
|
+
StringValue(input);
|
|
239
355
|
|
|
240
|
-
|
|
241
|
-
|
|
356
|
+
DecompressorData *data;
|
|
357
|
+
TypedData_Get_Struct(self, DecompressorData, &decompressor_type, data);
|
|
242
358
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
raise_deflate_error("Failed to allocate decompressor");
|
|
359
|
+
if (!data->decompressor) {
|
|
360
|
+
rb_raise(rb_eDecompressionError, "decompressor is closed");
|
|
246
361
|
}
|
|
247
362
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
size_t
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
363
|
+
const char *in_data = RSTRING_PTR(input);
|
|
364
|
+
size_t in_size = RSTRING_LEN(input);
|
|
365
|
+
size_t out_size = NUM2SIZET(out_size_val);
|
|
366
|
+
|
|
367
|
+
VALUE output = rb_str_buf_new(out_size);
|
|
368
|
+
size_t actual_out_size;
|
|
369
|
+
|
|
370
|
+
enum libdeflate_result result = libdeflate_gzip_decompress(
|
|
371
|
+
data->decompressor,
|
|
372
|
+
in_data, in_size,
|
|
373
|
+
RSTRING_PTR(output), out_size,
|
|
374
|
+
&actual_out_size
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
if (result != LIBDEFLATE_SUCCESS) {
|
|
378
|
+
const char *msg;
|
|
379
|
+
switch (result) {
|
|
380
|
+
case LIBDEFLATE_BAD_DATA:
|
|
381
|
+
msg = "bad compressed data";
|
|
382
|
+
break;
|
|
383
|
+
case LIBDEFLATE_SHORT_OUTPUT:
|
|
384
|
+
msg = "output buffer too small";
|
|
385
|
+
break;
|
|
386
|
+
case LIBDEFLATE_INSUFFICIENT_SPACE:
|
|
387
|
+
msg = "insufficient space";
|
|
388
|
+
break;
|
|
389
|
+
default:
|
|
390
|
+
msg = "decompression failed";
|
|
272
391
|
}
|
|
392
|
+
rb_raise(rb_eDecompressionError, "%s", msg);
|
|
273
393
|
}
|
|
274
394
|
|
|
275
|
-
|
|
395
|
+
rb_str_set_len(output, actual_out_size);
|
|
396
|
+
return output;
|
|
397
|
+
}
|
|
276
398
|
|
|
277
|
-
|
|
278
|
-
|
|
399
|
+
// decompressor.close
|
|
400
|
+
static VALUE decompressor_close(VALUE self) {
|
|
401
|
+
DecompressorData *data;
|
|
402
|
+
TypedData_Get_Struct(self, DecompressorData, &decompressor_type, data);
|
|
403
|
+
|
|
404
|
+
if (data->decompressor) {
|
|
405
|
+
libdeflate_free_decompressor(data->decompressor);
|
|
406
|
+
data->decompressor = NULL;
|
|
279
407
|
}
|
|
280
408
|
|
|
281
|
-
|
|
282
|
-
return out_str;
|
|
409
|
+
return Qnil;
|
|
283
410
|
}
|
|
284
411
|
|
|
285
|
-
//
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
412
|
+
// DeflateRuby.crc32(data, initial = 0) -> Integer
|
|
413
|
+
static VALUE module_crc32(int argc, VALUE *argv, VALUE self) {
|
|
414
|
+
VALUE input, initial;
|
|
415
|
+
rb_scan_args(argc, argv, "11", &input, &initial);
|
|
416
|
+
|
|
417
|
+
StringValue(input);
|
|
289
418
|
|
|
290
|
-
|
|
291
|
-
rb_define_module_function(rb_mDeflateRuby, "deflate_compress", rb_deflate_compress, -1);
|
|
292
|
-
rb_define_module_function(rb_mDeflateRuby, "deflate_decompress", rb_deflate_decompress, 1);
|
|
419
|
+
uint32_t crc = NIL_P(initial) ? 0 : NUM2UINT(initial);
|
|
293
420
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
421
|
+
crc = libdeflate_crc32(crc, RSTRING_PTR(input), RSTRING_LEN(input));
|
|
422
|
+
|
|
423
|
+
return UINT2NUM(crc);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// DeflateRuby.adler32(data, initial = 1) -> Integer
|
|
427
|
+
static VALUE module_adler32(int argc, VALUE *argv, VALUE self) {
|
|
428
|
+
VALUE input, initial;
|
|
429
|
+
rb_scan_args(argc, argv, "11", &input, &initial);
|
|
430
|
+
|
|
431
|
+
StringValue(input);
|
|
432
|
+
|
|
433
|
+
uint32_t adler = NIL_P(initial) ? 1 : NUM2UINT(initial);
|
|
434
|
+
|
|
435
|
+
adler = libdeflate_adler32(adler, RSTRING_PTR(input), RSTRING_LEN(input));
|
|
436
|
+
|
|
437
|
+
return UINT2NUM(adler);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
RUBY_FUNC_EXPORTED void
|
|
441
|
+
Init_deflate_ruby(void)
|
|
442
|
+
{
|
|
443
|
+
// Define module
|
|
444
|
+
rb_mDeflateRuby = rb_define_module("DeflateRuby");
|
|
297
445
|
|
|
298
|
-
//
|
|
299
|
-
|
|
300
|
-
|
|
446
|
+
// Define exception classes
|
|
447
|
+
rb_eDeflateError = rb_define_class_under(rb_mDeflateRuby, "DeflateError", rb_eStandardError);
|
|
448
|
+
rb_eCompressionError = rb_define_class_under(rb_mDeflateRuby, "CompressionError", rb_eDeflateError);
|
|
449
|
+
rb_eDecompressionError = rb_define_class_under(rb_mDeflateRuby, "DecompressionError", rb_eDeflateError);
|
|
450
|
+
|
|
451
|
+
// Define Compressor class
|
|
452
|
+
rb_cCompressor = rb_define_class_under(rb_mDeflateRuby, "Compressor", rb_cObject);
|
|
453
|
+
rb_define_alloc_func(rb_cCompressor, compressor_alloc);
|
|
454
|
+
rb_define_method(rb_cCompressor, "initialize", compressor_initialize, -1);
|
|
455
|
+
rb_define_method(rb_cCompressor, "deflate_compress", compressor_deflate_compress, 1);
|
|
456
|
+
rb_define_method(rb_cCompressor, "zlib_compress", compressor_zlib_compress, 1);
|
|
457
|
+
rb_define_method(rb_cCompressor, "gzip_compress", compressor_gzip_compress, 1);
|
|
458
|
+
rb_define_method(rb_cCompressor, "deflate_compress_bound", compressor_deflate_compress_bound, 1);
|
|
459
|
+
rb_define_method(rb_cCompressor, "zlib_compress_bound", compressor_zlib_compress_bound, 1);
|
|
460
|
+
rb_define_method(rb_cCompressor, "gzip_compress_bound", compressor_gzip_compress_bound, 1);
|
|
461
|
+
rb_define_method(rb_cCompressor, "close", compressor_close, 0);
|
|
462
|
+
|
|
463
|
+
// Define Decompressor class
|
|
464
|
+
rb_cDecompressor = rb_define_class_under(rb_mDeflateRuby, "Decompressor", rb_cObject);
|
|
465
|
+
rb_define_alloc_func(rb_cDecompressor, decompressor_alloc);
|
|
466
|
+
rb_define_method(rb_cDecompressor, "initialize", decompressor_initialize, 0);
|
|
467
|
+
rb_define_method(rb_cDecompressor, "deflate_decompress", decompressor_deflate_decompress, 2);
|
|
468
|
+
rb_define_method(rb_cDecompressor, "zlib_decompress", decompressor_zlib_decompress, 2);
|
|
469
|
+
rb_define_method(rb_cDecompressor, "gzip_decompress", decompressor_gzip_decompress, 2);
|
|
470
|
+
rb_define_method(rb_cDecompressor, "close", decompressor_close, 0);
|
|
471
|
+
|
|
472
|
+
// Define module methods
|
|
473
|
+
rb_define_module_function(rb_mDeflateRuby, "crc32", module_crc32, -1);
|
|
474
|
+
rb_define_module_function(rb_mDeflateRuby, "adler32", module_adler32, -1);
|
|
301
475
|
}
|