multi_compress 0.5.0 → 0.6.1
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/CHANGELOG.md +45 -0
- data/GET_STARTED.md +20 -1
- data/README.md +15 -2
- data/THIRD_PARTY_NOTICES.md +1 -1
- data/db_core/include/mcdb_format.h +67 -9
- data/db_core/src/mcdb_format.c +392 -139
- data/db_deployment/mysql/README.md +19 -0
- data/db_deployment/mysql/bin/common +70 -18
- data/db_deployment/mysql/bin/enable +5 -1
- data/db_deployment/mysql/bin/status +2 -0
- data/db_deployment/mysql/bin/upgrade +17 -5
- data/db_deployment/postgres/README.md +24 -0
- data/db_deployment/postgres/bin/enable +2 -0
- data/db_deployment/postgres/bin/install +4 -2
- data/docs/database-envelope-v2.md +147 -0
- data/docs/rfcs/0002-mcdb2-dictionaries.md +75 -0
- data/ext/multi_compress/multi_compress.c +261 -76
- data/ext/multi_compress/vendor/.vendored +1 -1
- data/ext/multi_compress/vendor/brotli/c/common/version.h +2 -2
- data/ext/multi_compress/vendor/brotli/c/dec/decode.c +59 -30
- data/ext/multi_compress/vendor/brotli/c/include/brotli/decode.h +1 -3
- data/lib/multi_compress/active_record.rb +11 -5
- data/lib/multi_compress/codec.rb +164 -94
- data/lib/multi_compress/database/api.rb +42 -0
- data/lib/multi_compress/database/decoding.rb +42 -0
- data/lib/multi_compress/database/dictionary.rb +72 -0
- data/lib/multi_compress/database/encoding.rb +31 -0
- data/lib/multi_compress/database/header.rb +71 -0
- data/lib/multi_compress/database/operations.rb +73 -0
- data/lib/multi_compress/database/validation.rb +95 -0
- data/lib/multi_compress/database.rb +29 -95
- data/lib/multi_compress/db_deployment/bundle_archiver.rb +70 -0
- data/lib/multi_compress/db_deployment/bundle_metadata.rb +56 -0
- data/lib/multi_compress/db_deployment/bundle_stager.rb +62 -0
- data/lib/multi_compress/db_deployment/commands.rb +309 -0
- data/lib/multi_compress/db_deployment/deployment_bundle.rb +80 -0
- data/lib/multi_compress/db_deployment/deterministic_tar_writer.rb +76 -0
- data/lib/multi_compress/db_deployment/dictionary_registry.rb +244 -0
- data/lib/multi_compress/db_deployment/readable_view.rb +112 -0
- data/lib/multi_compress/db_deployment/readable_view_options.rb +51 -0
- data/lib/multi_compress/db_deployment/sql_identifiers.rb +45 -0
- data/lib/multi_compress/db_deployment.rb +13 -435
- data/lib/multi_compress/reader/buffer_operations.rb +57 -0
- data/lib/multi_compress/reader/read_operations.rb +67 -0
- data/lib/multi_compress/reader.rb +97 -0
- data/lib/multi_compress/stream_io.rb +13 -0
- data/lib/multi_compress/version.rb +1 -1
- data/lib/multi_compress/writer.rb +85 -0
- data/lib/multi_compress.rb +42 -333
- data/mysql_udf/README.md +45 -0
- data/mysql_udf/sql/examples.sql +5 -0
- data/mysql_udf/sql/install.sql +25 -1
- data/mysql_udf/sql/uninstall.sql +7 -1
- data/mysql_udf/sql/views.sql +16 -4
- data/mysql_udf/src/multi_compress_mysql.c +383 -44
- data/mysql_udf/test/run_e2e.sh +119 -1
- data/postgres_extension/Makefile +2 -2
- data/postgres_extension/README.md +48 -0
- data/postgres_extension/multi_compress.control +2 -2
- data/postgres_extension/multi_compress_pg.exports +12 -0
- data/postgres_extension/sql/examples.sql +11 -0
- data/postgres_extension/sql/multi_compress--0.5.0--0.6.0.sql +59 -0
- data/postgres_extension/sql/multi_compress--0.6.0.sql +85 -0
- data/postgres_extension/src/multi_compress_pg.c +301 -16
- data/postgres_extension/test/run_e2e.sh +90 -2
- metadata +29 -6
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
#include <brotli/decode.h>
|
|
9
9
|
#include <brotli/encode.h>
|
|
10
10
|
#include <lz4.h>
|
|
11
|
-
#include <
|
|
11
|
+
#include <limits.h>
|
|
12
12
|
#include <lz4frame.h>
|
|
13
|
+
#include <lz4hc.h>
|
|
13
14
|
#include <pthread.h>
|
|
14
15
|
#include <stdio.h>
|
|
15
16
|
#include <stdint.h>
|
|
@@ -518,30 +519,42 @@ static compress_algo_t detect_algo(const uint8_t *data, size_t len) {
|
|
|
518
519
|
return ALGO_ZSTD;
|
|
519
520
|
}
|
|
520
521
|
|
|
521
|
-
static inline
|
|
522
|
-
|
|
522
|
+
static inline long rb_checked_string_length(size_t len) {
|
|
523
|
+
if ((uintmax_t)len > (uintmax_t)LONG_MAX)
|
|
524
|
+
rb_raise(eDataError, "string size exceeds Ruby's maximum length");
|
|
525
|
+
|
|
526
|
+
return (long)len;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
static inline VALUE rb_binary_str_new(const char *ptr, size_t len) {
|
|
530
|
+
VALUE str = rb_str_new(ptr, rb_checked_string_length(len));
|
|
523
531
|
rb_enc_associate(str, binary_encoding);
|
|
524
532
|
return str;
|
|
525
533
|
}
|
|
526
534
|
|
|
527
|
-
static inline VALUE rb_binary_str_buf_new(
|
|
528
|
-
VALUE str = rb_str_buf_new(capa);
|
|
535
|
+
static inline VALUE rb_binary_str_buf_new(size_t capa) {
|
|
536
|
+
VALUE str = rb_str_buf_new(rb_checked_string_length(capa));
|
|
529
537
|
rb_enc_associate(str, binary_encoding);
|
|
530
538
|
return str;
|
|
531
539
|
}
|
|
532
540
|
|
|
533
|
-
static inline VALUE rb_binary_str_buf_reserve(
|
|
534
|
-
VALUE str = rb_str_buf_new(capa);
|
|
541
|
+
static inline VALUE rb_binary_str_buf_reserve(size_t capa) {
|
|
542
|
+
VALUE str = rb_str_buf_new(rb_checked_string_length(capa));
|
|
535
543
|
rb_enc_associate(str, binary_encoding);
|
|
536
544
|
return str;
|
|
537
545
|
}
|
|
538
546
|
|
|
547
|
+
static inline void rb_binary_str_set_len(VALUE str, size_t len) {
|
|
548
|
+
rb_str_set_len(str, rb_checked_string_length(len));
|
|
549
|
+
}
|
|
550
|
+
|
|
539
551
|
static inline void grow_binary_str(VALUE str, size_t cur_len, size_t new_cap) {
|
|
540
552
|
size_t cur_cap = (size_t)rb_str_capacity(str);
|
|
541
553
|
if (new_cap <= cur_cap)
|
|
542
554
|
return;
|
|
543
|
-
|
|
544
|
-
|
|
555
|
+
(void)rb_checked_string_length(new_cap);
|
|
556
|
+
rb_binary_str_set_len(str, cur_len);
|
|
557
|
+
rb_str_modify_expand(str, rb_checked_string_length(new_cap - cur_len));
|
|
545
558
|
}
|
|
546
559
|
|
|
547
560
|
typedef struct {
|
|
@@ -562,6 +575,8 @@ static void limits_config_apply_parsed(const mc_opts_t *opts, limits_config_t *l
|
|
|
562
575
|
size_t max_output_size = NUM2SIZET(val);
|
|
563
576
|
if (max_output_size == 0)
|
|
564
577
|
rb_raise(rb_eArgError, "max_output_size must be greater than 0");
|
|
578
|
+
if ((uintmax_t)max_output_size > (uintmax_t)LONG_MAX)
|
|
579
|
+
rb_raise(rb_eArgError, "max_output_size exceeds Ruby's maximum string length");
|
|
565
580
|
limits->max_output_size = max_output_size;
|
|
566
581
|
}
|
|
567
582
|
|
|
@@ -1306,7 +1321,7 @@ static VALUE compress_compress(int argc, VALUE *argv, VALUE self) {
|
|
|
1306
1321
|
rb_raise(eMemError, "zstd: failed to create context");
|
|
1307
1322
|
if (ZSTD_isError(csize))
|
|
1308
1323
|
rb_raise(eError, "zstd compress: %s", ZSTD_getErrorName(csize));
|
|
1309
|
-
|
|
1324
|
+
rb_binary_str_set_len(dst, csize);
|
|
1310
1325
|
RB_GC_GUARD(data);
|
|
1311
1326
|
RB_GC_GUARD(dict_val);
|
|
1312
1327
|
return dst;
|
|
@@ -1343,7 +1358,7 @@ static VALUE compress_compress(int argc, VALUE *argv, VALUE self) {
|
|
|
1343
1358
|
rb_raise(eError, "zstd compress: %s", ZSTD_getErrorName(fargs.result));
|
|
1344
1359
|
}
|
|
1345
1360
|
|
|
1346
|
-
VALUE result = rb_binary_str_new(out_buf,
|
|
1361
|
+
VALUE result = rb_binary_str_new(out_buf, fargs.result);
|
|
1347
1362
|
free(out_buf);
|
|
1348
1363
|
RB_GC_GUARD(data);
|
|
1349
1364
|
RB_GC_GUARD(dict_val);
|
|
@@ -1370,7 +1385,7 @@ static VALUE compress_compress(int argc, VALUE *argv, VALUE self) {
|
|
|
1370
1385
|
if (ZSTD_isError(args.result))
|
|
1371
1386
|
rb_raise(eError, "zstd compress: %s", ZSTD_getErrorName(args.result));
|
|
1372
1387
|
|
|
1373
|
-
|
|
1388
|
+
rb_binary_str_set_len(dst, args.result);
|
|
1374
1389
|
RB_GC_GUARD(data);
|
|
1375
1390
|
RB_GC_GUARD(dict_val);
|
|
1376
1391
|
return dst;
|
|
@@ -1383,7 +1398,7 @@ static VALUE compress_compress(int argc, VALUE *argv, VALUE self) {
|
|
|
1383
1398
|
prefs.frameInfo.blockChecksumFlag = LZ4F_blockChecksumEnabled;
|
|
1384
1399
|
prefs.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled;
|
|
1385
1400
|
size_t bound = LZ4F_compressFrameBound(slen, &prefs);
|
|
1386
|
-
VALUE dst = rb_binary_str_buf_reserve(
|
|
1401
|
+
VALUE dst = rb_binary_str_buf_reserve(bound);
|
|
1387
1402
|
lz4frame_compress_args_t args = {
|
|
1388
1403
|
.src = src,
|
|
1389
1404
|
.src_len = slen,
|
|
@@ -1401,7 +1416,7 @@ static VALUE compress_compress(int argc, VALUE *argv, VALUE self) {
|
|
|
1401
1416
|
if (args.error_code)
|
|
1402
1417
|
rb_raise(eError, "lz4 frame compress failed: %s",
|
|
1403
1418
|
LZ4F_getErrorName(args.error_code));
|
|
1404
|
-
|
|
1419
|
+
rb_binary_str_set_len(dst, args.result);
|
|
1405
1420
|
RB_GC_GUARD(data);
|
|
1406
1421
|
return dst;
|
|
1407
1422
|
}
|
|
@@ -1438,7 +1453,7 @@ static VALUE compress_compress(int argc, VALUE *argv, VALUE self) {
|
|
|
1438
1453
|
size_t total = 8 + (size_t)csize;
|
|
1439
1454
|
write_le_u32((uint8_t *)out + total, 0);
|
|
1440
1455
|
|
|
1441
|
-
|
|
1456
|
+
rb_binary_str_set_len(dst, total + 4);
|
|
1442
1457
|
RB_GC_GUARD(data);
|
|
1443
1458
|
return dst;
|
|
1444
1459
|
} else {
|
|
@@ -1460,7 +1475,7 @@ static VALUE compress_compress(int argc, VALUE *argv, VALUE self) {
|
|
|
1460
1475
|
size_t total = 8 + csize;
|
|
1461
1476
|
write_le_u32((uint8_t *)out + total, 0);
|
|
1462
1477
|
|
|
1463
|
-
|
|
1478
|
+
rb_binary_str_set_len(dst, total + 4);
|
|
1464
1479
|
RB_GC_GUARD(data);
|
|
1465
1480
|
return dst;
|
|
1466
1481
|
}
|
|
@@ -1516,7 +1531,7 @@ static VALUE compress_compress(int argc, VALUE *argv, VALUE self) {
|
|
|
1516
1531
|
if (!ok)
|
|
1517
1532
|
rb_raise(eError, "brotli compress with dict failed");
|
|
1518
1533
|
|
|
1519
|
-
|
|
1534
|
+
rb_binary_str_set_len(dst, initial_out - available_out);
|
|
1520
1535
|
RB_GC_GUARD(data);
|
|
1521
1536
|
RB_GC_GUARD(dict_val);
|
|
1522
1537
|
return dst;
|
|
@@ -1540,7 +1555,7 @@ static VALUE compress_compress(int argc, VALUE *argv, VALUE self) {
|
|
|
1540
1555
|
if (!args.result)
|
|
1541
1556
|
rb_raise(eError, "brotli compress failed");
|
|
1542
1557
|
|
|
1543
|
-
|
|
1558
|
+
rb_binary_str_set_len(dst, actual_out_len);
|
|
1544
1559
|
RB_GC_GUARD(data);
|
|
1545
1560
|
return dst;
|
|
1546
1561
|
} else {
|
|
@@ -1550,7 +1565,7 @@ static VALUE compress_compress(int argc, VALUE *argv, VALUE self) {
|
|
|
1550
1565
|
(const uint8_t *)src, &out_len, (uint8_t *)RSTRING_PTR(dst));
|
|
1551
1566
|
if (!ok)
|
|
1552
1567
|
rb_raise(eError, "brotli compress failed");
|
|
1553
|
-
|
|
1568
|
+
rb_binary_str_set_len(dst, out_len);
|
|
1554
1569
|
RB_GC_GUARD(data);
|
|
1555
1570
|
return dst;
|
|
1556
1571
|
}
|
|
@@ -1560,6 +1575,20 @@ static VALUE compress_compress(int argc, VALUE *argv, VALUE self) {
|
|
|
1560
1575
|
return Qnil;
|
|
1561
1576
|
}
|
|
1562
1577
|
|
|
1578
|
+
static VALUE zstd_frame_dictionary_id(VALUE self, VALUE data) {
|
|
1579
|
+
(void)self;
|
|
1580
|
+
StringValue(data);
|
|
1581
|
+
|
|
1582
|
+
const void *src = RSTRING_PTR(data);
|
|
1583
|
+
size_t src_len = (size_t)RSTRING_LEN(data);
|
|
1584
|
+
size_t frame_size = ZSTD_findFrameCompressedSize(src, src_len);
|
|
1585
|
+
if (ZSTD_isError(frame_size) || frame_size != src_len)
|
|
1586
|
+
rb_raise(eDataError, "zstd: expected exactly one valid frame with no trailing bytes");
|
|
1587
|
+
|
|
1588
|
+
RB_GC_GUARD(data);
|
|
1589
|
+
return UINT2NUM(ZSTD_getDictID_fromFrame(src, src_len));
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1563
1592
|
static VALUE zstd_single_frame_info(VALUE self, VALUE data) {
|
|
1564
1593
|
(void)self;
|
|
1565
1594
|
StringValue(data);
|
|
@@ -1676,7 +1705,7 @@ static VALUE compress_decompress(int argc, VALUE *argv, VALUE self) {
|
|
|
1676
1705
|
|
|
1677
1706
|
enforce_output_and_ratio_limits(dsize, slen, limits.max_output_size,
|
|
1678
1707
|
limits.max_ratio_enabled, limits.max_ratio);
|
|
1679
|
-
|
|
1708
|
+
rb_binary_str_set_len(dst, dsize);
|
|
1680
1709
|
RB_GC_GUARD(data);
|
|
1681
1710
|
RB_GC_GUARD(dict_val);
|
|
1682
1711
|
return dst;
|
|
@@ -1700,7 +1729,7 @@ static VALUE compress_decompress(int argc, VALUE *argv, VALUE self) {
|
|
|
1700
1729
|
rb_raise(eDataError, "zstd decompress: %s", ZSTD_getErrorName(dsize));
|
|
1701
1730
|
enforce_output_and_ratio_limits(dsize, slen, limits.max_output_size,
|
|
1702
1731
|
limits.max_ratio_enabled, limits.max_ratio);
|
|
1703
|
-
|
|
1732
|
+
rb_binary_str_set_len(dst, dsize);
|
|
1704
1733
|
RB_GC_GUARD(data);
|
|
1705
1734
|
RB_GC_GUARD(dict_val);
|
|
1706
1735
|
return dst;
|
|
@@ -1773,7 +1802,7 @@ static VALUE compress_decompress(int argc, VALUE *argv, VALUE self) {
|
|
|
1773
1802
|
break;
|
|
1774
1803
|
}
|
|
1775
1804
|
|
|
1776
|
-
|
|
1805
|
+
rb_binary_str_set_len(dst, total_out);
|
|
1777
1806
|
RB_GC_GUARD(data);
|
|
1778
1807
|
RB_GC_GUARD(dict_val);
|
|
1779
1808
|
return dst;
|
|
@@ -1786,7 +1815,7 @@ static VALUE compress_decompress(int argc, VALUE *argv, VALUE self) {
|
|
|
1786
1815
|
alloc_size = limits.max_output_size < 4096 ? limits.max_output_size : 4096;
|
|
1787
1816
|
if (alloc_size == 0)
|
|
1788
1817
|
alloc_size = limits.max_output_size;
|
|
1789
|
-
VALUE dst = rb_binary_str_buf_reserve(
|
|
1818
|
+
VALUE dst = rb_binary_str_buf_reserve(alloc_size);
|
|
1790
1819
|
while (1) {
|
|
1791
1820
|
lz4frame_decompress_args_t args = {
|
|
1792
1821
|
.src = src,
|
|
@@ -1821,7 +1850,7 @@ static VALUE compress_decompress(int argc, VALUE *argv, VALUE self) {
|
|
|
1821
1850
|
LZ4F_getErrorName(args.error_code));
|
|
1822
1851
|
enforce_output_and_ratio_limits(args.result, slen, limits.max_output_size,
|
|
1823
1852
|
limits.max_ratio_enabled, limits.max_ratio);
|
|
1824
|
-
|
|
1853
|
+
rb_binary_str_set_len(dst, args.result);
|
|
1825
1854
|
RB_GC_GUARD(data);
|
|
1826
1855
|
return dst;
|
|
1827
1856
|
}
|
|
@@ -1876,7 +1905,7 @@ static VALUE compress_decompress(int argc, VALUE *argv, VALUE self) {
|
|
|
1876
1905
|
|
|
1877
1906
|
enforce_output_and_ratio_limits(args.out_offset, slen, limits.max_output_size,
|
|
1878
1907
|
limits.max_ratio_enabled, limits.max_ratio);
|
|
1879
|
-
|
|
1908
|
+
rb_binary_str_set_len(result, args.out_offset);
|
|
1880
1909
|
RB_GC_GUARD(data);
|
|
1881
1910
|
return result;
|
|
1882
1911
|
}
|
|
@@ -1962,7 +1991,7 @@ static VALUE compress_decompress(int argc, VALUE *argv, VALUE self) {
|
|
|
1962
1991
|
if (res != BROTLI_DECODER_RESULT_SUCCESS) {
|
|
1963
1992
|
rb_raise(eDataError, "brotli decompress failed");
|
|
1964
1993
|
}
|
|
1965
|
-
|
|
1994
|
+
rb_binary_str_set_len(dst, total_out);
|
|
1966
1995
|
RB_GC_GUARD(data);
|
|
1967
1996
|
RB_GC_GUARD(dict_val);
|
|
1968
1997
|
return dst;
|
|
@@ -2117,11 +2146,45 @@ static VALUE compress_version(VALUE self, VALUE algo_sym) {
|
|
|
2117
2146
|
_Static_assert(LZ4_RING_BUFFER_TOTAL == 2 * LZ4_RING_BUFFER_SIZE,
|
|
2118
2147
|
"ring buffer total must be exactly twice the window size");
|
|
2119
2148
|
|
|
2149
|
+
typedef struct {
|
|
2150
|
+
int *active;
|
|
2151
|
+
VALUE self;
|
|
2152
|
+
VALUE argument;
|
|
2153
|
+
VALUE (*operation)(VALUE, VALUE);
|
|
2154
|
+
} stream_operation_t;
|
|
2155
|
+
|
|
2156
|
+
static VALUE stream_operation_body(VALUE opaque) {
|
|
2157
|
+
stream_operation_t *call = (stream_operation_t *)(uintptr_t)opaque;
|
|
2158
|
+
return call->operation(call->self, call->argument);
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
static VALUE stream_operation_ensure(VALUE opaque) {
|
|
2162
|
+
stream_operation_t *call = (stream_operation_t *)(uintptr_t)opaque;
|
|
2163
|
+
*call->active = 0;
|
|
2164
|
+
return Qnil;
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
static VALUE stream_operation_call(int *active, VALUE self, VALUE argument,
|
|
2168
|
+
VALUE (*operation)(VALUE, VALUE)) {
|
|
2169
|
+
if (*active)
|
|
2170
|
+
rb_raise(eStreamError, "stream operation already in progress");
|
|
2171
|
+
|
|
2172
|
+
stream_operation_t call = {
|
|
2173
|
+
.active = active, .self = self, .argument = argument, .operation = operation};
|
|
2174
|
+
*active = 1;
|
|
2175
|
+
VALUE result = rb_ensure(stream_operation_body, (VALUE)(uintptr_t)&call,
|
|
2176
|
+
stream_operation_ensure, (VALUE)(uintptr_t)&call);
|
|
2177
|
+
RB_GC_GUARD(self);
|
|
2178
|
+
RB_GC_GUARD(argument);
|
|
2179
|
+
return result;
|
|
2180
|
+
}
|
|
2181
|
+
|
|
2120
2182
|
typedef struct {
|
|
2121
2183
|
compress_algo_t algo;
|
|
2122
2184
|
int level;
|
|
2123
2185
|
int closed;
|
|
2124
2186
|
int finished;
|
|
2187
|
+
int operation_active;
|
|
2125
2188
|
|
|
2126
2189
|
union {
|
|
2127
2190
|
ZSTD_CStream *zstd;
|
|
@@ -2165,6 +2228,9 @@ static size_t deflater_memsize(const void *ptr) {
|
|
|
2165
2228
|
return 0;
|
|
2166
2229
|
|
|
2167
2230
|
size_t s = sizeof(deflater_t);
|
|
2231
|
+
if (d->operation_active)
|
|
2232
|
+
return s;
|
|
2233
|
+
|
|
2168
2234
|
switch (d->algo) {
|
|
2169
2235
|
case ALGO_ZSTD:
|
|
2170
2236
|
if (d->ctx.zstd)
|
|
@@ -2311,7 +2377,7 @@ static VALUE lz4_compress_ring_block(deflater_t *d) {
|
|
|
2311
2377
|
|
|
2312
2378
|
write_le_u32((uint8_t *)out + 4, (uint32_t)csize);
|
|
2313
2379
|
|
|
2314
|
-
|
|
2380
|
+
rb_binary_str_set_len(output, 8 + csize);
|
|
2315
2381
|
d->lz4_ring.pending = 0;
|
|
2316
2382
|
|
|
2317
2383
|
if (d->lz4_ring.ring_offset >= LZ4_RING_BUFFER_SIZE) {
|
|
@@ -2321,7 +2387,7 @@ static VALUE lz4_compress_ring_block(deflater_t *d) {
|
|
|
2321
2387
|
return output;
|
|
2322
2388
|
}
|
|
2323
2389
|
|
|
2324
|
-
static VALUE
|
|
2390
|
+
static VALUE deflater_write_impl(VALUE self, VALUE chunk) {
|
|
2325
2391
|
deflater_t *d;
|
|
2326
2392
|
TypedData_Get_Struct(self, deflater_t, &deflater_type, d);
|
|
2327
2393
|
if (d->closed)
|
|
@@ -2391,7 +2457,7 @@ static VALUE deflater_write(VALUE self, VALUE chunk) {
|
|
|
2391
2457
|
}
|
|
2392
2458
|
result_len += output.pos;
|
|
2393
2459
|
}
|
|
2394
|
-
|
|
2460
|
+
rb_binary_str_set_len(result, result_len);
|
|
2395
2461
|
RB_GC_GUARD(chunk);
|
|
2396
2462
|
return result;
|
|
2397
2463
|
}
|
|
@@ -2457,7 +2523,7 @@ static VALUE deflater_write(VALUE self, VALUE chunk) {
|
|
|
2457
2523
|
}
|
|
2458
2524
|
}
|
|
2459
2525
|
}
|
|
2460
|
-
|
|
2526
|
+
rb_binary_str_set_len(result, result_len);
|
|
2461
2527
|
RB_GC_GUARD(chunk);
|
|
2462
2528
|
return result;
|
|
2463
2529
|
}
|
|
@@ -2503,7 +2569,7 @@ static VALUE deflater_write(VALUE self, VALUE chunk) {
|
|
|
2503
2569
|
}
|
|
2504
2570
|
}
|
|
2505
2571
|
}
|
|
2506
|
-
|
|
2572
|
+
rb_binary_str_set_len(result, result_len);
|
|
2507
2573
|
RB_GC_GUARD(chunk);
|
|
2508
2574
|
return result;
|
|
2509
2575
|
}
|
|
@@ -2511,7 +2577,14 @@ static VALUE deflater_write(VALUE self, VALUE chunk) {
|
|
|
2511
2577
|
return rb_binary_str_new("", 0);
|
|
2512
2578
|
}
|
|
2513
2579
|
|
|
2514
|
-
static VALUE
|
|
2580
|
+
static VALUE deflater_write(VALUE self, VALUE chunk) {
|
|
2581
|
+
deflater_t *d;
|
|
2582
|
+
TypedData_Get_Struct(self, deflater_t, &deflater_type, d);
|
|
2583
|
+
return stream_operation_call(&d->operation_active, self, chunk, deflater_write_impl);
|
|
2584
|
+
}
|
|
2585
|
+
|
|
2586
|
+
static VALUE deflater_flush_impl(VALUE self, VALUE unused) {
|
|
2587
|
+
(void)unused;
|
|
2515
2588
|
deflater_t *d;
|
|
2516
2589
|
TypedData_Get_Struct(self, deflater_t, &deflater_type, d);
|
|
2517
2590
|
if (d->closed)
|
|
@@ -2540,7 +2613,7 @@ static VALUE deflater_flush(VALUE self) {
|
|
|
2540
2613
|
result_len += output.pos;
|
|
2541
2614
|
} while (ret > 0);
|
|
2542
2615
|
|
|
2543
|
-
|
|
2616
|
+
rb_binary_str_set_len(result, result_len);
|
|
2544
2617
|
return result;
|
|
2545
2618
|
}
|
|
2546
2619
|
case ALGO_BROTLI: {
|
|
@@ -2572,7 +2645,7 @@ static VALUE deflater_flush(VALUE self) {
|
|
|
2572
2645
|
}
|
|
2573
2646
|
} while (BrotliEncoderHasMoreOutput(d->ctx.brotli));
|
|
2574
2647
|
|
|
2575
|
-
|
|
2648
|
+
rb_binary_str_set_len(result, result_len);
|
|
2576
2649
|
return result;
|
|
2577
2650
|
}
|
|
2578
2651
|
case ALGO_LZ4:
|
|
@@ -2581,7 +2654,14 @@ static VALUE deflater_flush(VALUE self) {
|
|
|
2581
2654
|
return rb_binary_str_new("", 0);
|
|
2582
2655
|
}
|
|
2583
2656
|
|
|
2584
|
-
static VALUE
|
|
2657
|
+
static VALUE deflater_flush(VALUE self) {
|
|
2658
|
+
deflater_t *d;
|
|
2659
|
+
TypedData_Get_Struct(self, deflater_t, &deflater_type, d);
|
|
2660
|
+
return stream_operation_call(&d->operation_active, self, Qnil, deflater_flush_impl);
|
|
2661
|
+
}
|
|
2662
|
+
|
|
2663
|
+
static VALUE deflater_finish_impl(VALUE self, VALUE unused) {
|
|
2664
|
+
(void)unused;
|
|
2585
2665
|
deflater_t *d;
|
|
2586
2666
|
TypedData_Get_Struct(self, deflater_t, &deflater_type, d);
|
|
2587
2667
|
if (d->closed)
|
|
@@ -2611,7 +2691,7 @@ static VALUE deflater_finish(VALUE self) {
|
|
|
2611
2691
|
result_len += output.pos;
|
|
2612
2692
|
} while (ret > 0);
|
|
2613
2693
|
|
|
2614
|
-
|
|
2694
|
+
rb_binary_str_set_len(result, result_len);
|
|
2615
2695
|
return result;
|
|
2616
2696
|
}
|
|
2617
2697
|
case ALGO_BROTLI: {
|
|
@@ -2644,7 +2724,7 @@ static VALUE deflater_finish(VALUE self) {
|
|
|
2644
2724
|
} while (BrotliEncoderHasMoreOutput(d->ctx.brotli) ||
|
|
2645
2725
|
!BrotliEncoderIsFinished(d->ctx.brotli));
|
|
2646
2726
|
|
|
2647
|
-
|
|
2727
|
+
rb_binary_str_set_len(result, result_len);
|
|
2648
2728
|
return result;
|
|
2649
2729
|
}
|
|
2650
2730
|
case ALGO_LZ4: {
|
|
@@ -2675,14 +2755,21 @@ static VALUE deflater_finish(VALUE self) {
|
|
|
2675
2755
|
write_le_u32((uint8_t *)out, 0);
|
|
2676
2756
|
result_len += 4;
|
|
2677
2757
|
|
|
2678
|
-
|
|
2758
|
+
rb_binary_str_set_len(result, result_len);
|
|
2679
2759
|
return result;
|
|
2680
2760
|
}
|
|
2681
2761
|
}
|
|
2682
2762
|
return rb_binary_str_new("", 0);
|
|
2683
2763
|
}
|
|
2684
2764
|
|
|
2685
|
-
static VALUE
|
|
2765
|
+
static VALUE deflater_finish(VALUE self) {
|
|
2766
|
+
deflater_t *d;
|
|
2767
|
+
TypedData_Get_Struct(self, deflater_t, &deflater_type, d);
|
|
2768
|
+
return stream_operation_call(&d->operation_active, self, Qnil, deflater_finish_impl);
|
|
2769
|
+
}
|
|
2770
|
+
|
|
2771
|
+
static VALUE deflater_reset_impl(VALUE self, VALUE unused) {
|
|
2772
|
+
(void)unused;
|
|
2686
2773
|
deflater_t *d;
|
|
2687
2774
|
TypedData_Get_Struct(self, deflater_t, &deflater_type, d);
|
|
2688
2775
|
|
|
@@ -2738,7 +2825,14 @@ static VALUE deflater_reset(VALUE self) {
|
|
|
2738
2825
|
return self;
|
|
2739
2826
|
}
|
|
2740
2827
|
|
|
2741
|
-
static VALUE
|
|
2828
|
+
static VALUE deflater_reset(VALUE self) {
|
|
2829
|
+
deflater_t *d;
|
|
2830
|
+
TypedData_Get_Struct(self, deflater_t, &deflater_type, d);
|
|
2831
|
+
return stream_operation_call(&d->operation_active, self, Qnil, deflater_reset_impl);
|
|
2832
|
+
}
|
|
2833
|
+
|
|
2834
|
+
static VALUE deflater_close_impl(VALUE self, VALUE unused) {
|
|
2835
|
+
(void)unused;
|
|
2742
2836
|
deflater_t *d;
|
|
2743
2837
|
TypedData_Get_Struct(self, deflater_t, &deflater_type, d);
|
|
2744
2838
|
if (d->closed)
|
|
@@ -2768,6 +2862,12 @@ static VALUE deflater_close(VALUE self) {
|
|
|
2768
2862
|
return Qnil;
|
|
2769
2863
|
}
|
|
2770
2864
|
|
|
2865
|
+
static VALUE deflater_close(VALUE self) {
|
|
2866
|
+
deflater_t *d;
|
|
2867
|
+
TypedData_Get_Struct(self, deflater_t, &deflater_type, d);
|
|
2868
|
+
return stream_operation_call(&d->operation_active, self, Qnil, deflater_close_impl);
|
|
2869
|
+
}
|
|
2870
|
+
|
|
2771
2871
|
static VALUE deflater_closed_p(VALUE self) {
|
|
2772
2872
|
deflater_t *d;
|
|
2773
2873
|
TypedData_Get_Struct(self, deflater_t, &deflater_type, d);
|
|
@@ -2778,6 +2878,7 @@ typedef struct {
|
|
|
2778
2878
|
compress_algo_t algo;
|
|
2779
2879
|
int closed;
|
|
2780
2880
|
int finished;
|
|
2881
|
+
int operation_active;
|
|
2781
2882
|
size_t max_output_size;
|
|
2782
2883
|
size_t total_output;
|
|
2783
2884
|
size_t total_input;
|
|
@@ -2824,6 +2925,9 @@ static size_t inflater_memsize(const void *ptr) {
|
|
|
2824
2925
|
return 0;
|
|
2825
2926
|
|
|
2826
2927
|
size_t s = sizeof(inflater_t);
|
|
2928
|
+
if (inf->operation_active)
|
|
2929
|
+
return s;
|
|
2930
|
+
|
|
2827
2931
|
switch (inf->algo) {
|
|
2828
2932
|
case ALGO_ZSTD:
|
|
2829
2933
|
if (inf->ctx.zstd)
|
|
@@ -2918,7 +3022,7 @@ static VALUE inflater_initialize(int argc, VALUE *argv, VALUE self) {
|
|
|
2918
3022
|
return self;
|
|
2919
3023
|
}
|
|
2920
3024
|
|
|
2921
|
-
static VALUE
|
|
3025
|
+
static VALUE inflater_write_impl(VALUE self, VALUE chunk) {
|
|
2922
3026
|
inflater_t *inf;
|
|
2923
3027
|
TypedData_Get_Struct(self, inflater_t, &inflater_type, inf);
|
|
2924
3028
|
if (inf->closed)
|
|
@@ -3003,7 +3107,7 @@ static VALUE inflater_write(VALUE self, VALUE chunk) {
|
|
|
3003
3107
|
"compressed input exceeds representable size");
|
|
3004
3108
|
inf->total_output = checked_add_size(inf->total_output, result_len,
|
|
3005
3109
|
"decompressed output exceeds representable size");
|
|
3006
|
-
|
|
3110
|
+
rb_binary_str_set_len(result, result_len);
|
|
3007
3111
|
RB_GC_GUARD(chunk);
|
|
3008
3112
|
return result;
|
|
3009
3113
|
}
|
|
@@ -3084,7 +3188,7 @@ static VALUE inflater_write(VALUE self, VALUE chunk) {
|
|
|
3084
3188
|
"compressed input exceeds representable size");
|
|
3085
3189
|
inf->total_output = checked_add_size(inf->total_output, result_len,
|
|
3086
3190
|
"decompressed output exceeds representable size");
|
|
3087
|
-
|
|
3191
|
+
rb_binary_str_set_len(result, result_len);
|
|
3088
3192
|
RB_GC_GUARD(chunk);
|
|
3089
3193
|
return result;
|
|
3090
3194
|
}
|
|
@@ -3187,7 +3291,7 @@ static VALUE inflater_write(VALUE self, VALUE chunk) {
|
|
|
3187
3291
|
inf->lz4_buf.offset = pos;
|
|
3188
3292
|
inf->total_output = checked_add_size(inf->total_output, result_len,
|
|
3189
3293
|
"decompressed output exceeds representable size");
|
|
3190
|
-
|
|
3294
|
+
rb_binary_str_set_len(result, result_len);
|
|
3191
3295
|
RB_GC_GUARD(chunk);
|
|
3192
3296
|
return result;
|
|
3193
3297
|
}
|
|
@@ -3195,7 +3299,14 @@ static VALUE inflater_write(VALUE self, VALUE chunk) {
|
|
|
3195
3299
|
return rb_binary_str_new("", 0);
|
|
3196
3300
|
}
|
|
3197
3301
|
|
|
3198
|
-
static VALUE
|
|
3302
|
+
static VALUE inflater_write(VALUE self, VALUE chunk) {
|
|
3303
|
+
inflater_t *inf;
|
|
3304
|
+
TypedData_Get_Struct(self, inflater_t, &inflater_type, inf);
|
|
3305
|
+
return stream_operation_call(&inf->operation_active, self, chunk, inflater_write_impl);
|
|
3306
|
+
}
|
|
3307
|
+
|
|
3308
|
+
static VALUE inflater_finish_impl(VALUE self, VALUE unused) {
|
|
3309
|
+
(void)unused;
|
|
3199
3310
|
inflater_t *inf;
|
|
3200
3311
|
TypedData_Get_Struct(self, inflater_t, &inflater_type, inf);
|
|
3201
3312
|
if (inf->closed)
|
|
@@ -3204,7 +3315,14 @@ static VALUE inflater_finish(VALUE self) {
|
|
|
3204
3315
|
return rb_binary_str_new("", 0);
|
|
3205
3316
|
}
|
|
3206
3317
|
|
|
3207
|
-
static VALUE
|
|
3318
|
+
static VALUE inflater_finish(VALUE self) {
|
|
3319
|
+
inflater_t *inf;
|
|
3320
|
+
TypedData_Get_Struct(self, inflater_t, &inflater_type, inf);
|
|
3321
|
+
return stream_operation_call(&inf->operation_active, self, Qnil, inflater_finish_impl);
|
|
3322
|
+
}
|
|
3323
|
+
|
|
3324
|
+
static VALUE inflater_reset_impl(VALUE self, VALUE unused) {
|
|
3325
|
+
(void)unused;
|
|
3208
3326
|
inflater_t *inf;
|
|
3209
3327
|
TypedData_Get_Struct(self, inflater_t, &inflater_type, inf);
|
|
3210
3328
|
|
|
@@ -3249,7 +3367,14 @@ static VALUE inflater_reset(VALUE self) {
|
|
|
3249
3367
|
return self;
|
|
3250
3368
|
}
|
|
3251
3369
|
|
|
3252
|
-
static VALUE
|
|
3370
|
+
static VALUE inflater_reset(VALUE self) {
|
|
3371
|
+
inflater_t *inf;
|
|
3372
|
+
TypedData_Get_Struct(self, inflater_t, &inflater_type, inf);
|
|
3373
|
+
return stream_operation_call(&inf->operation_active, self, Qnil, inflater_reset_impl);
|
|
3374
|
+
}
|
|
3375
|
+
|
|
3376
|
+
static VALUE inflater_close_impl(VALUE self, VALUE unused) {
|
|
3377
|
+
(void)unused;
|
|
3253
3378
|
inflater_t *inf;
|
|
3254
3379
|
TypedData_Get_Struct(self, inflater_t, &inflater_type, inf);
|
|
3255
3380
|
if (inf->closed)
|
|
@@ -3275,6 +3400,12 @@ static VALUE inflater_close(VALUE self) {
|
|
|
3275
3400
|
return Qnil;
|
|
3276
3401
|
}
|
|
3277
3402
|
|
|
3403
|
+
static VALUE inflater_close(VALUE self) {
|
|
3404
|
+
inflater_t *inf;
|
|
3405
|
+
TypedData_Get_Struct(self, inflater_t, &inflater_type, inf);
|
|
3406
|
+
return stream_operation_call(&inf->operation_active, self, Qnil, inflater_close_impl);
|
|
3407
|
+
}
|
|
3408
|
+
|
|
3278
3409
|
static VALUE inflater_closed_p(VALUE self) {
|
|
3279
3410
|
inflater_t *inf;
|
|
3280
3411
|
TypedData_Get_Struct(self, inflater_t, &inflater_type, inf);
|
|
@@ -3395,6 +3526,59 @@ static VALUE brotli_train_dictionary(int argc, VALUE *argv, VALUE self) {
|
|
|
3395
3526
|
return train_dictionary_internal(samples, parsed_opts.size, ALGO_BROTLI);
|
|
3396
3527
|
}
|
|
3397
3528
|
|
|
3529
|
+
typedef struct {
|
|
3530
|
+
FILE *file;
|
|
3531
|
+
VALUE path_value;
|
|
3532
|
+
const char *path;
|
|
3533
|
+
uint8_t *data;
|
|
3534
|
+
size_t size;
|
|
3535
|
+
int loaded;
|
|
3536
|
+
} dict_file_read_t;
|
|
3537
|
+
|
|
3538
|
+
static VALUE dict_file_read_body(VALUE opaque) {
|
|
3539
|
+
dict_file_read_t *read = (dict_file_read_t *)(uintptr_t)opaque;
|
|
3540
|
+
|
|
3541
|
+
if (fseek(read->file, 0, SEEK_END) != 0)
|
|
3542
|
+
rb_sys_fail(read->path);
|
|
3543
|
+
|
|
3544
|
+
long file_size = ftell(read->file);
|
|
3545
|
+
if (file_size < 0)
|
|
3546
|
+
rb_sys_fail(read->path);
|
|
3547
|
+
if (file_size == 0)
|
|
3548
|
+
rb_raise(eDataError, "dictionary file is empty: %s", read->path);
|
|
3549
|
+
if ((unsigned long long)file_size > DICT_FILE_MAX_SIZE)
|
|
3550
|
+
rb_raise(eDataError, "dictionary file too large (%ld bytes, max=%d)", file_size,
|
|
3551
|
+
(int)DICT_FILE_MAX_SIZE);
|
|
3552
|
+
if (fseek(read->file, 0, SEEK_SET) != 0)
|
|
3553
|
+
rb_sys_fail(read->path);
|
|
3554
|
+
|
|
3555
|
+
read->data = ALLOC_N(uint8_t, file_size);
|
|
3556
|
+
read->path = RSTRING_PTR(read->path_value);
|
|
3557
|
+
read->size = (size_t)file_size;
|
|
3558
|
+
size_t read_bytes = fread(read->data, 1, read->size, read->file);
|
|
3559
|
+
if (read_bytes != read->size) {
|
|
3560
|
+
xfree(read->data);
|
|
3561
|
+
read->data = NULL;
|
|
3562
|
+
rb_raise(eDataError, "failed to read dictionary: %s", read->path);
|
|
3563
|
+
}
|
|
3564
|
+
|
|
3565
|
+
read->loaded = 1;
|
|
3566
|
+
return Qnil;
|
|
3567
|
+
}
|
|
3568
|
+
|
|
3569
|
+
static VALUE dict_file_read_ensure(VALUE opaque) {
|
|
3570
|
+
dict_file_read_t *read = (dict_file_read_t *)(uintptr_t)opaque;
|
|
3571
|
+
if (read->file) {
|
|
3572
|
+
fclose(read->file);
|
|
3573
|
+
read->file = NULL;
|
|
3574
|
+
}
|
|
3575
|
+
if (!read->loaded && read->data) {
|
|
3576
|
+
xfree(read->data);
|
|
3577
|
+
read->data = NULL;
|
|
3578
|
+
}
|
|
3579
|
+
return Qnil;
|
|
3580
|
+
}
|
|
3581
|
+
|
|
3398
3582
|
static VALUE dict_load(int argc, VALUE *argv, VALUE self) {
|
|
3399
3583
|
VALUE path, opts;
|
|
3400
3584
|
scan_one_required_keywords(argc, argv, &path, &opts);
|
|
@@ -3411,40 +3595,23 @@ static VALUE dict_load(int argc, VALUE *argv, VALUE self) {
|
|
|
3411
3595
|
if (algo == ALGO_LZ4)
|
|
3412
3596
|
rb_raise(eUnsupportedError, "LZ4 does not support dictionaries");
|
|
3413
3597
|
|
|
3598
|
+
VALUE dict_obj = dict_alloc(cDictionary);
|
|
3599
|
+
dictionary_t *d;
|
|
3600
|
+
TypedData_Get_Struct(dict_obj, dictionary_t, &dictionary_type, d);
|
|
3601
|
+
|
|
3414
3602
|
const char *cpath = RSTRING_PTR(path);
|
|
3415
|
-
FILE *
|
|
3416
|
-
if (!
|
|
3603
|
+
FILE *file = fopen(cpath, "rb");
|
|
3604
|
+
if (!file)
|
|
3417
3605
|
rb_sys_fail(cpath);
|
|
3418
3606
|
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
if (file_size <= 0) {
|
|
3424
|
-
fclose(f);
|
|
3425
|
-
rb_raise(eDataError, "dictionary file is empty: %s", cpath);
|
|
3426
|
-
}
|
|
3427
|
-
if ((unsigned long long)file_size > DICT_FILE_MAX_SIZE) {
|
|
3428
|
-
fclose(f);
|
|
3429
|
-
rb_raise(eDataError, "dictionary file too large (%ld bytes, max=%d)", file_size,
|
|
3430
|
-
(int)DICT_FILE_MAX_SIZE);
|
|
3431
|
-
}
|
|
3432
|
-
|
|
3433
|
-
uint8_t *buf = ALLOC_N(uint8_t, file_size);
|
|
3434
|
-
size_t read_bytes = fread(buf, 1, file_size, f);
|
|
3435
|
-
fclose(f);
|
|
3436
|
-
|
|
3437
|
-
if ((long)read_bytes != file_size) {
|
|
3438
|
-
xfree(buf);
|
|
3439
|
-
rb_raise(eDataError, "failed to read dictionary: %s", cpath);
|
|
3440
|
-
}
|
|
3607
|
+
dict_file_read_t read = {.file = file, .path_value = path, .path = cpath};
|
|
3608
|
+
rb_ensure(dict_file_read_body, (VALUE)(uintptr_t)&read, dict_file_read_ensure,
|
|
3609
|
+
(VALUE)(uintptr_t)&read);
|
|
3441
3610
|
|
|
3442
|
-
VALUE dict_obj = dict_alloc(cDictionary);
|
|
3443
|
-
dictionary_t *d;
|
|
3444
|
-
TypedData_Get_Struct(dict_obj, dictionary_t, &dictionary_type, d);
|
|
3445
3611
|
d->algo = algo;
|
|
3446
|
-
d->data =
|
|
3447
|
-
d->size =
|
|
3612
|
+
d->data = read.data;
|
|
3613
|
+
d->size = read.size;
|
|
3614
|
+
read.data = NULL;
|
|
3448
3615
|
return dict_obj;
|
|
3449
3616
|
}
|
|
3450
3617
|
|
|
@@ -3471,6 +3638,20 @@ static VALUE dict_algo(VALUE self) {
|
|
|
3471
3638
|
return algo_to_sym(d->algo);
|
|
3472
3639
|
}
|
|
3473
3640
|
|
|
3641
|
+
static VALUE dict_bytes(VALUE self) {
|
|
3642
|
+
dictionary_t *d;
|
|
3643
|
+
TypedData_Get_Struct(self, dictionary_t, &dictionary_type, d);
|
|
3644
|
+
return rb_binary_str_new((const char *)d->data, d->size);
|
|
3645
|
+
}
|
|
3646
|
+
|
|
3647
|
+
static VALUE dict_zstd_id(VALUE self) {
|
|
3648
|
+
dictionary_t *d;
|
|
3649
|
+
TypedData_Get_Struct(self, dictionary_t, &dictionary_type, d);
|
|
3650
|
+
if (d->algo != ALGO_ZSTD)
|
|
3651
|
+
rb_raise(eUnsupportedError, "zstd_id is available only for zstd dictionaries");
|
|
3652
|
+
return UINT2NUM(ZSTD_getDictID_fromDict(d->data, d->size));
|
|
3653
|
+
}
|
|
3654
|
+
|
|
3474
3655
|
static VALUE dict_size(VALUE self) {
|
|
3475
3656
|
dictionary_t *d;
|
|
3476
3657
|
TypedData_Get_Struct(self, dictionary_t, &dictionary_type, d);
|
|
@@ -3508,6 +3689,8 @@ void Init_multi_compress(void) {
|
|
|
3508
3689
|
rb_define_module_function(mMultiCompress, "compress", compress_compress, -1);
|
|
3509
3690
|
rb_define_module_function(mMultiCompress, "decompress", compress_decompress, -1);
|
|
3510
3691
|
rb_define_module_function(mMultiCompress, "zstd_single_frame_info", zstd_single_frame_info, 1);
|
|
3692
|
+
rb_define_module_function(mMultiCompress, "zstd_frame_dictionary_id", zstd_frame_dictionary_id,
|
|
3693
|
+
1);
|
|
3511
3694
|
rb_define_module_function(mMultiCompress, "crc32", compress_crc32, -1);
|
|
3512
3695
|
rb_define_module_function(mMultiCompress, "adler32", compress_adler32, -1);
|
|
3513
3696
|
rb_define_module_function(mMultiCompress, "algorithms", compress_algorithms, 0);
|
|
@@ -3542,6 +3725,8 @@ void Init_multi_compress(void) {
|
|
|
3542
3725
|
rb_define_singleton_method(cDictionary, "load", dict_load, -1);
|
|
3543
3726
|
rb_define_method(cDictionary, "save", dict_save, 1);
|
|
3544
3727
|
rb_define_method(cDictionary, "algo", dict_algo, 0);
|
|
3728
|
+
rb_define_method(cDictionary, "bytes", dict_bytes, 0);
|
|
3729
|
+
rb_define_method(cDictionary, "zstd_id", dict_zstd_id, 0);
|
|
3545
3730
|
rb_define_method(cDictionary, "size", dict_size, 0);
|
|
3546
3731
|
rb_define_singleton_method(mZstd, "train_dictionary", zstd_train_dictionary, -1);
|
|
3547
3732
|
rb_define_singleton_method(mBrotli, "train_dictionary", brotli_train_dictionary, -1);
|