brotli 0.2.3 → 0.5.0
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/.github/workflows/main.yml +37 -0
- data/.github/workflows/publish.yml +24 -0
- data/.gitmodules +1 -1
- data/Gemfile +6 -3
- data/README.md +2 -2
- data/Rakefile +16 -9
- data/brotli.gemspec +7 -13
- data/ext/brotli/brotli.c +210 -31
- data/ext/brotli/buffer.c +1 -7
- data/ext/brotli/buffer.h +1 -1
- data/ext/brotli/extconf.rb +25 -17
- data/lib/brotli/version.rb +1 -1
- data/test/brotli_test.rb +107 -0
- data/test/brotli_writer_test.rb +36 -0
- data/test/test_helper.rb +8 -0
- data/vendor/brotli/c/common/constants.c +15 -0
- data/vendor/brotli/c/common/constants.h +137 -0
- data/vendor/brotli/c/common/context.c +156 -0
- data/vendor/brotli/c/common/context.h +4 -152
- data/vendor/brotli/c/common/dictionary.bin.br +0 -0
- data/vendor/brotli/c/common/dictionary.c +14 -3
- data/vendor/brotli/c/common/platform.c +23 -0
- data/vendor/brotli/c/common/platform.h +95 -122
- data/vendor/brotli/c/common/shared_dictionary.c +521 -0
- data/vendor/brotli/c/common/shared_dictionary_internal.h +75 -0
- data/vendor/brotli/c/common/transform.c +60 -4
- data/vendor/brotli/c/common/transform.h +5 -0
- data/vendor/brotli/c/common/version.h +31 -6
- data/vendor/brotli/c/dec/bit_reader.c +34 -4
- data/vendor/brotli/c/dec/bit_reader.h +221 -107
- data/vendor/brotli/c/dec/decode.c +772 -403
- data/vendor/brotli/c/dec/huffman.c +7 -4
- data/vendor/brotli/c/dec/huffman.h +8 -13
- data/vendor/brotli/c/dec/prefix.h +1 -18
- data/vendor/brotli/c/dec/state.c +40 -21
- data/vendor/brotli/c/dec/state.h +201 -59
- data/vendor/brotli/c/enc/backward_references.c +88 -25
- data/vendor/brotli/c/enc/backward_references.h +10 -8
- data/vendor/brotli/c/enc/backward_references_hq.c +194 -80
- data/vendor/brotli/c/enc/backward_references_hq.h +17 -13
- data/vendor/brotli/c/enc/backward_references_inc.h +52 -16
- data/vendor/brotli/c/enc/bit_cost.c +8 -7
- data/vendor/brotli/c/enc/bit_cost.h +5 -4
- data/vendor/brotli/c/enc/block_splitter.c +40 -17
- data/vendor/brotli/c/enc/block_splitter.h +5 -4
- data/vendor/brotli/c/enc/block_splitter_inc.h +99 -49
- data/vendor/brotli/c/enc/brotli_bit_stream.c +142 -137
- data/vendor/brotli/c/enc/brotli_bit_stream.h +11 -6
- data/vendor/brotli/c/enc/cluster.c +10 -9
- data/vendor/brotli/c/enc/cluster.h +7 -6
- data/vendor/brotli/c/enc/cluster_inc.h +30 -22
- data/vendor/brotli/c/enc/command.c +28 -0
- data/vendor/brotli/c/enc/command.h +17 -16
- data/vendor/brotli/c/enc/compound_dictionary.c +207 -0
- data/vendor/brotli/c/enc/compound_dictionary.h +74 -0
- data/vendor/brotli/c/enc/compress_fragment.c +93 -83
- data/vendor/brotli/c/enc/compress_fragment.h +32 -7
- data/vendor/brotli/c/enc/compress_fragment_two_pass.c +100 -88
- data/vendor/brotli/c/enc/compress_fragment_two_pass.h +21 -3
- data/vendor/brotli/c/enc/dictionary_hash.c +1829 -1101
- data/vendor/brotli/c/enc/dictionary_hash.h +2 -1
- data/vendor/brotli/c/enc/encode.c +550 -416
- data/vendor/brotli/c/enc/encoder_dict.c +613 -5
- data/vendor/brotli/c/enc/encoder_dict.h +120 -4
- data/vendor/brotli/c/enc/entropy_encode.c +5 -2
- data/vendor/brotli/c/enc/entropy_encode.h +4 -3
- data/vendor/brotli/c/enc/entropy_encode_static.h +5 -2
- data/vendor/brotli/c/enc/fast_log.c +105 -0
- data/vendor/brotli/c/enc/fast_log.h +21 -101
- data/vendor/brotli/c/enc/find_match_length.h +17 -25
- data/vendor/brotli/c/enc/hash.h +350 -120
- data/vendor/brotli/c/enc/hash_composite_inc.h +71 -67
- data/vendor/brotli/c/enc/hash_forgetful_chain_inc.h +92 -51
- data/vendor/brotli/c/enc/hash_longest_match64_inc.h +79 -84
- data/vendor/brotli/c/enc/hash_longest_match_inc.h +53 -54
- data/vendor/brotli/c/enc/hash_longest_match_quickly_inc.h +93 -62
- data/vendor/brotli/c/enc/hash_rolling_inc.h +25 -29
- data/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +42 -40
- data/vendor/brotli/c/enc/histogram.c +4 -4
- data/vendor/brotli/c/enc/histogram.h +7 -6
- data/vendor/brotli/c/enc/literal_cost.c +20 -15
- data/vendor/brotli/c/enc/literal_cost.h +4 -2
- data/vendor/brotli/c/enc/memory.c +29 -5
- data/vendor/brotli/c/enc/memory.h +43 -14
- data/vendor/brotli/c/enc/metablock.c +95 -85
- data/vendor/brotli/c/enc/metablock.h +9 -8
- data/vendor/brotli/c/enc/metablock_inc.h +9 -7
- data/vendor/brotli/c/enc/params.h +7 -4
- data/vendor/brotli/c/enc/prefix.h +3 -2
- data/vendor/brotli/c/enc/quality.h +40 -3
- data/vendor/brotli/c/enc/ringbuffer.h +8 -4
- data/vendor/brotli/c/enc/state.h +104 -0
- data/vendor/brotli/c/enc/static_dict.c +60 -4
- data/vendor/brotli/c/enc/static_dict.h +3 -2
- data/vendor/brotli/c/enc/static_dict_lut.h +2 -0
- data/vendor/brotli/c/enc/utf8_util.c +2 -2
- data/vendor/brotli/c/enc/utf8_util.h +2 -1
- data/vendor/brotli/c/enc/write_bits.h +29 -26
- data/vendor/brotli/c/include/brotli/decode.h +67 -2
- data/vendor/brotli/c/include/brotli/encode.h +77 -3
- data/vendor/brotli/c/include/brotli/port.h +34 -3
- data/vendor/brotli/c/include/brotli/shared_dictionary.h +100 -0
- metadata +23 -97
- data/.travis.yml +0 -31
- data/docs/Brotli/Error.html +0 -124
- data/docs/Brotli.html +0 -485
- data/docs/_index.html +0 -122
- data/docs/class_list.html +0 -51
- data/docs/css/common.css +0 -1
- data/docs/css/full_list.css +0 -58
- data/docs/css/style.css +0 -496
- data/docs/file.README.html +0 -127
- data/docs/file_list.html +0 -56
- data/docs/frames.html +0 -17
- data/docs/index.html +0 -127
- data/docs/js/app.js +0 -292
- data/docs/js/full_list.js +0 -216
- data/docs/js/jquery.js +0 -4
- data/docs/method_list.html +0 -67
- data/docs/top-level-namespace.html +0 -110
- data/spec/brotli_spec.rb +0 -88
- data/spec/inflate_spec.rb +0 -75
- data/spec/spec_helper.rb +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97953895465e26d5937e5959f86954aa58de2d2221301bc64ff639e682565605
|
4
|
+
data.tar.gz: 4f26bccb546a19c743eea5b0fd9207f8e623bfd73f05e08f3dae275b76c51482
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b5e79aee2804a948da509247c56b1f79e9248927ec6430319b1d2b6202973ed41bca1ceba215f8d4954ad98a52637a91e49bfa316af4ab3d35fcb779f0e94aa3
|
7
|
+
data.tar.gz: 46d42e9297f79aef7481b068e43da47c60d45b0f781a0ceb1fc7626cdb9c59bc306feaab0b05321cba17e23256e492814f340725db8fb21dc9e4c84198507bf5
|
@@ -0,0 +1,37 @@
|
|
1
|
+
name: Ruby
|
2
|
+
|
3
|
+
on: [pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
build:
|
7
|
+
strategy:
|
8
|
+
fail-fast: false
|
9
|
+
matrix:
|
10
|
+
ruby: [2.7, 3.1, 3.2, 3.3]
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
steps:
|
13
|
+
- uses: actions/checkout@v4
|
14
|
+
with:
|
15
|
+
submodules: true
|
16
|
+
- name: Set up Ruby
|
17
|
+
uses: ruby/setup-ruby@v1
|
18
|
+
with:
|
19
|
+
ruby-version: ${{ matrix.ruby }}
|
20
|
+
bundler-cache: true
|
21
|
+
- name: Run the default task
|
22
|
+
run: |
|
23
|
+
bundle exec rake clobber
|
24
|
+
bundle exec rake compile -- --enable-vendor
|
25
|
+
bundle exec rake test
|
26
|
+
bundle exec rake build
|
27
|
+
gem install --no-document "$(ls pkg/brotli-*.gem)"
|
28
|
+
cat <<EOF | ruby
|
29
|
+
require "brotli"
|
30
|
+
if Brotli.inflate(Brotli.deflate(File.read("README.md"))) == File.read("README.md")
|
31
|
+
puts "OK"
|
32
|
+
exit 0
|
33
|
+
else
|
34
|
+
puts "NG"
|
35
|
+
exit 0
|
36
|
+
end
|
37
|
+
EOF
|
@@ -0,0 +1,24 @@
|
|
1
|
+
name: Publish Gem
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
tags:
|
6
|
+
- 'v*'
|
7
|
+
|
8
|
+
jobs:
|
9
|
+
build:
|
10
|
+
if: github.repository == 'miyucy/brotli'
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
permissions:
|
13
|
+
contents: write
|
14
|
+
id-token: write
|
15
|
+
steps:
|
16
|
+
- uses: actions/checkout@v4
|
17
|
+
with:
|
18
|
+
submodules: true
|
19
|
+
- name: Set up Ruby
|
20
|
+
uses: ruby/setup-ruby@v1
|
21
|
+
with:
|
22
|
+
ruby-version: ruby
|
23
|
+
bundler-cache: true
|
24
|
+
- uses: rubygems/release-gem@v1
|
data/.gitmodules
CHANGED
data/Gemfile
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
-
source
|
1
|
+
source "https://rubygems.org"
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in brotli.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
-
gem
|
7
|
-
gem
|
6
|
+
gem "rake", "~> 13.0"
|
7
|
+
gem "rake-compiler"
|
8
|
+
gem "test-unit", "~> 3.0"
|
9
|
+
gem "test-unit-rr"
|
10
|
+
gem "rantly"
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Brotli
|
1
|
+
# Brotli
|
2
2
|
|
3
3
|
Brotli is a Ruby implementation of the Brotli generic-purpose lossless
|
4
4
|
compression algorithm that compresses data using a combination of a modern
|
@@ -31,7 +31,7 @@ compressed = Brotli.deflate(string)
|
|
31
31
|
decompressed = Brotli.inflate(compressed)
|
32
32
|
```
|
33
33
|
|
34
|
-
See
|
34
|
+
See test/brotli_test.rb
|
35
35
|
|
36
36
|
## Development
|
37
37
|
|
data/Rakefile
CHANGED
@@ -1,18 +1,25 @@
|
|
1
|
+
require "bundler/setup"
|
1
2
|
require "bundler/gem_tasks"
|
2
|
-
require "
|
3
|
+
require "rake/clean"
|
4
|
+
require "rake/testtask"
|
3
5
|
require "rake/extensiontask"
|
4
|
-
require "yard"
|
5
6
|
|
6
|
-
|
7
|
+
CLEAN.include("ext/brotli/common")
|
8
|
+
CLEAN.include("ext/brotli/dec")
|
9
|
+
CLEAN.include("ext/brotli/enc")
|
10
|
+
CLEAN.include("ext/brotli/include")
|
7
11
|
|
8
|
-
|
9
|
-
|
10
|
-
|
12
|
+
Rake::TestTask.new(:test) do |t|
|
13
|
+
t.libs << "test"
|
14
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
15
|
+
t.warning = true
|
16
|
+
t.verbose = true
|
17
|
+
end
|
11
18
|
|
12
19
|
Rake::ExtensionTask.new("brotli") do |ext|
|
13
20
|
ext.lib_dir = "lib/brotli"
|
14
21
|
end
|
15
22
|
|
16
|
-
|
17
|
-
|
18
|
-
|
23
|
+
task :build => :compile
|
24
|
+
task :test => :compile
|
25
|
+
task :default => :test
|
data/brotli.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
4
|
+
require "brotli/version"
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "brotli"
|
@@ -9,25 +9,19 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["miyucy"]
|
10
10
|
spec.email = ["fistfvck@gmail.com"]
|
11
11
|
|
12
|
-
spec.summary =
|
13
|
-
spec.description =
|
12
|
+
spec.summary = "Brotli compressor/decompressor"
|
13
|
+
spec.description = "Brotli compressor/decompressor"
|
14
14
|
spec.homepage = "https://github.com/miyucy/brotli"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
17
|
-
spec.test_files = `git ls-files -z --
|
17
|
+
spec.test_files = `git ls-files -z -- test`.split("\x0")
|
18
18
|
spec.files = `git ls-files -z`.split("\x0")
|
19
19
|
spec.files -= spec.test_files
|
20
|
-
spec.files -= [
|
21
|
-
spec.files += Dir[
|
22
|
-
spec.files += [
|
20
|
+
spec.files -= ["vendor/brotli"]
|
21
|
+
spec.files += Dir["vendor/brotli/c/{common,enc,dec,include}/**/*"]
|
22
|
+
spec.files += ["vendor/brotli/LICENSE"]
|
23
23
|
spec.bindir = "exe"
|
24
24
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
25
|
spec.require_paths = ["lib"]
|
26
26
|
spec.extensions = ["ext/brotli/extconf.rb"]
|
27
|
-
|
28
|
-
spec.add_development_dependency "bundler"
|
29
|
-
spec.add_development_dependency "rake"
|
30
|
-
spec.add_development_dependency "rake-compiler"
|
31
|
-
spec.add_development_dependency "rspec"
|
32
|
-
spec.add_development_dependency "rantly"
|
33
27
|
end
|
data/ext/brotli/brotli.c
CHANGED
@@ -2,20 +2,19 @@
|
|
2
2
|
|
3
3
|
#define CSTR2SYM(x) ID2SYM(rb_intern(x))
|
4
4
|
|
5
|
-
static VALUE rb_mBrotli;
|
6
5
|
static VALUE rb_eBrotli;
|
7
6
|
|
8
|
-
static void*
|
7
|
+
static inline void*
|
9
8
|
brotli_alloc(void* opaque, size_t size)
|
10
9
|
{
|
11
|
-
return
|
10
|
+
return ruby_xmalloc(size);
|
12
11
|
}
|
13
12
|
|
14
|
-
static void
|
13
|
+
static inline void
|
15
14
|
brotli_free(void* opaque, void* address)
|
16
15
|
{
|
17
16
|
if (address) {
|
18
|
-
|
17
|
+
ruby_xfree(address);
|
19
18
|
}
|
20
19
|
}
|
21
20
|
|
@@ -138,11 +137,10 @@ brotli_deflate_set_mode(BrotliEncoderState* s, VALUE value)
|
|
138
137
|
static void
|
139
138
|
brotli_deflate_set_quality(BrotliEncoderState* s, VALUE value)
|
140
139
|
{
|
141
|
-
uint32_t param;
|
142
140
|
if (NIL_P(value)) {
|
143
141
|
return;
|
144
142
|
} else {
|
145
|
-
param = NUM2INT(value);
|
143
|
+
int32_t param = NUM2INT(value);
|
146
144
|
if (0 <= param && param <= 11) {
|
147
145
|
BrotliEncoderSetParameter(s, BROTLI_PARAM_QUALITY, param);
|
148
146
|
} else {
|
@@ -154,11 +152,10 @@ brotli_deflate_set_quality(BrotliEncoderState* s, VALUE value)
|
|
154
152
|
static void
|
155
153
|
brotli_deflate_set_lgwin(BrotliEncoderState* s, VALUE value)
|
156
154
|
{
|
157
|
-
uint32_t param;
|
158
155
|
if (NIL_P(value)) {
|
159
156
|
return;
|
160
157
|
} else {
|
161
|
-
param = NUM2INT(value);
|
158
|
+
int32_t param = NUM2INT(value);
|
162
159
|
if (10 <= param && param <= 24) {
|
163
160
|
BrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, param);
|
164
161
|
} else {
|
@@ -170,11 +167,10 @@ brotli_deflate_set_lgwin(BrotliEncoderState* s, VALUE value)
|
|
170
167
|
static void
|
171
168
|
brotli_deflate_set_lgblock(BrotliEncoderState* s, VALUE value)
|
172
169
|
{
|
173
|
-
uint32_t param;
|
174
170
|
if (NIL_P(value)) {
|
175
171
|
return;
|
176
172
|
} else {
|
177
|
-
param = NUM2INT(value);
|
173
|
+
int32_t param = NUM2INT(value);
|
178
174
|
if ((param == 0) || (16 <= param && param <= 24)) {
|
179
175
|
BrotliEncoderSetParameter(s, BROTLI_PARAM_LGBLOCK, param);
|
180
176
|
} else {
|
@@ -187,6 +183,7 @@ static BrotliEncoderState*
|
|
187
183
|
brotli_deflate_parse_options(BrotliEncoderState* s, VALUE opts)
|
188
184
|
{
|
189
185
|
if (!NIL_P(opts)) {
|
186
|
+
Check_Type(opts, T_HASH);
|
190
187
|
brotli_deflate_set_mode(s, rb_hash_aref(opts, CSTR2SYM("mode")));
|
191
188
|
brotli_deflate_set_quality(s, rb_hash_aref(opts, CSTR2SYM("quality")));
|
192
189
|
brotli_deflate_set_lgwin(s, rb_hash_aref(opts, CSTR2SYM("lgwin")));
|
@@ -241,26 +238,6 @@ brotli_deflate_no_gvl(void *arg)
|
|
241
238
|
return arg;
|
242
239
|
}
|
243
240
|
|
244
|
-
/*
|
245
|
-
* call-seq:
|
246
|
-
* Brotli.deflate(str, opts=nil) -> String
|
247
|
-
* @param [String] str
|
248
|
-
* string
|
249
|
-
* @param [Hash] opts
|
250
|
-
* options
|
251
|
-
* @option opts [Symbol] :mode
|
252
|
-
* Deflate mode
|
253
|
-
* * :generic
|
254
|
-
* * :text
|
255
|
-
* * :font
|
256
|
-
* @option opts [Integer] :quality
|
257
|
-
* quality 0-11
|
258
|
-
* @option opts [Integer] :lgwin
|
259
|
-
* lgwin 10-24
|
260
|
-
* @option opts [Integer] :lgblock
|
261
|
-
* lgblock 16-24 or 0
|
262
|
-
* @return [String] Deflated string
|
263
|
-
*/
|
264
241
|
static VALUE
|
265
242
|
brotli_deflate(int argc, VALUE *argv, VALUE self)
|
266
243
|
{
|
@@ -268,6 +245,10 @@ brotli_deflate(int argc, VALUE *argv, VALUE self)
|
|
268
245
|
brotli_deflate_args_t args;
|
269
246
|
|
270
247
|
rb_scan_args(argc, argv, "11", &str, &opts);
|
248
|
+
if (NIL_P(str)) {
|
249
|
+
rb_raise(rb_eArgError, "input should not be nil");
|
250
|
+
return Qnil;
|
251
|
+
}
|
271
252
|
StringValue(str);
|
272
253
|
|
273
254
|
args.str = (uint8_t*)RSTRING_PTR(str);
|
@@ -293,6 +274,185 @@ brotli_deflate(int argc, VALUE *argv, VALUE self)
|
|
293
274
|
return value;
|
294
275
|
}
|
295
276
|
|
277
|
+
/*******************************************************************************
|
278
|
+
* version
|
279
|
+
******************************************************************************/
|
280
|
+
|
281
|
+
static VALUE brotli_version(VALUE klass) {
|
282
|
+
uint32_t ver = BrotliEncoderVersion();
|
283
|
+
char version[255];
|
284
|
+
snprintf(version, sizeof(version), "%u.%u.%u", ver >> 24, (ver >> 12) & 0xFFF, ver & 0xFFF);
|
285
|
+
return rb_str_new2(version);
|
286
|
+
}
|
287
|
+
|
288
|
+
/*******************************************************************************
|
289
|
+
* Writer
|
290
|
+
******************************************************************************/
|
291
|
+
|
292
|
+
static ID id_write, id_flush, id_close;
|
293
|
+
|
294
|
+
struct brotli {
|
295
|
+
VALUE io;
|
296
|
+
BrotliEncoderState* state;
|
297
|
+
};
|
298
|
+
|
299
|
+
static void br_mark(void *p)
|
300
|
+
{
|
301
|
+
struct brotli *br = p;
|
302
|
+
rb_gc_mark(br->io);
|
303
|
+
}
|
304
|
+
|
305
|
+
static void br_free(void *p)
|
306
|
+
{
|
307
|
+
struct brotli* br = p;
|
308
|
+
BrotliEncoderDestroyInstance(br->state);
|
309
|
+
br->state = NULL;
|
310
|
+
br->io = Qnil;
|
311
|
+
ruby_xfree(br);
|
312
|
+
}
|
313
|
+
|
314
|
+
static size_t br_memsize(const void *p)
|
315
|
+
{
|
316
|
+
return sizeof(struct brotli);
|
317
|
+
}
|
318
|
+
|
319
|
+
static const rb_data_type_t brotli_data_type = {
|
320
|
+
"brotli",
|
321
|
+
{ br_mark, br_free, br_memsize },
|
322
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
323
|
+
};
|
324
|
+
|
325
|
+
typedef struct {
|
326
|
+
BrotliEncoderState* state;
|
327
|
+
BrotliEncoderOperation op;
|
328
|
+
size_t available_in;
|
329
|
+
const uint8_t* next_in;
|
330
|
+
} brotli_encoder_args_t;
|
331
|
+
|
332
|
+
static void* compress_no_gvl(void *ptr) {
|
333
|
+
brotli_encoder_args_t *args = ptr;
|
334
|
+
size_t zero = 0;
|
335
|
+
if (!BrotliEncoderCompressStream(args->state, args->op,
|
336
|
+
&args->available_in, &args->next_in,
|
337
|
+
&zero, NULL, NULL)) {
|
338
|
+
rb_raise(rb_eBrotli, "BrotliEncoderCompressStream failed");
|
339
|
+
}
|
340
|
+
return NULL;
|
341
|
+
}
|
342
|
+
|
343
|
+
static size_t push_output(struct brotli *br) {
|
344
|
+
size_t len = 0;
|
345
|
+
if (BrotliEncoderHasMoreOutput(br->state)) {
|
346
|
+
const uint8_t* out = BrotliEncoderTakeOutput(br->state, &len);
|
347
|
+
if (len > 0) {
|
348
|
+
rb_funcall(br->io, id_write, 1, rb_str_new((const char*)out, len));
|
349
|
+
}
|
350
|
+
}
|
351
|
+
return len;
|
352
|
+
}
|
353
|
+
|
354
|
+
static VALUE rb_writer_alloc(VALUE klass) {
|
355
|
+
struct brotli *br;
|
356
|
+
VALUE obj = TypedData_Make_Struct(klass, struct brotli, &brotli_data_type, br);
|
357
|
+
br->io = Qnil;
|
358
|
+
br->state = BrotliEncoderCreateInstance(brotli_alloc, brotli_free, NULL);
|
359
|
+
if (!br->state) {
|
360
|
+
rb_raise(rb_eNoMemError, "BrotliEncoderCreateInstance failed");
|
361
|
+
return Qnil;
|
362
|
+
}
|
363
|
+
return obj;
|
364
|
+
}
|
365
|
+
|
366
|
+
static VALUE rb_writer_initialize(int argc, VALUE* argv, VALUE self) {
|
367
|
+
VALUE io = Qnil;
|
368
|
+
VALUE opts = Qnil;
|
369
|
+
rb_scan_args(argc, argv, "11", &io, &opts);
|
370
|
+
if (NIL_P(io)) {
|
371
|
+
rb_raise(rb_eArgError, "io should not be nil");
|
372
|
+
return Qnil;
|
373
|
+
}
|
374
|
+
|
375
|
+
struct brotli *br;
|
376
|
+
TypedData_Get_Struct(self, struct brotli, &brotli_data_type, br);
|
377
|
+
brotli_deflate_parse_options(br->state, opts);
|
378
|
+
br->io = io;
|
379
|
+
return self;
|
380
|
+
}
|
381
|
+
|
382
|
+
static VALUE rb_writer_write(VALUE self, VALUE buf) {
|
383
|
+
struct brotli* br;
|
384
|
+
TypedData_Get_Struct(self, struct brotli, &brotli_data_type, br);
|
385
|
+
StringValue(buf);
|
386
|
+
|
387
|
+
const size_t total = (size_t)RSTRING_LEN(buf);
|
388
|
+
|
389
|
+
brotli_encoder_args_t args = {
|
390
|
+
.state = br->state,
|
391
|
+
.op = BROTLI_OPERATION_PROCESS,
|
392
|
+
.available_in = total,
|
393
|
+
.next_in = (uint8_t*)RSTRING_PTR(buf)
|
394
|
+
};
|
395
|
+
|
396
|
+
while (args.available_in > 0) {
|
397
|
+
rb_thread_call_without_gvl(compress_no_gvl, (void*)&args, NULL, NULL);
|
398
|
+
push_output(br);
|
399
|
+
}
|
400
|
+
|
401
|
+
return SIZET2NUM(total);
|
402
|
+
}
|
403
|
+
|
404
|
+
static VALUE rb_writer_finish(VALUE self) {
|
405
|
+
struct brotli* br;
|
406
|
+
TypedData_Get_Struct(self, struct brotli, &brotli_data_type, br);
|
407
|
+
|
408
|
+
brotli_encoder_args_t args = {
|
409
|
+
.state = br->state,
|
410
|
+
.op = BROTLI_OPERATION_FINISH,
|
411
|
+
.available_in = 0,
|
412
|
+
.next_in = NULL
|
413
|
+
};
|
414
|
+
|
415
|
+
while (!BrotliEncoderIsFinished(br->state)) {
|
416
|
+
rb_thread_call_without_gvl(compress_no_gvl, (void*)&args, NULL, NULL);
|
417
|
+
push_output(br);
|
418
|
+
}
|
419
|
+
return br->io;
|
420
|
+
}
|
421
|
+
|
422
|
+
static VALUE rb_writer_flush(VALUE self) {
|
423
|
+
struct brotli *br;
|
424
|
+
TypedData_Get_Struct(self, struct brotli, &brotli_data_type, br);
|
425
|
+
|
426
|
+
brotli_encoder_args_t args = {
|
427
|
+
.state = br->state,
|
428
|
+
.op = BROTLI_OPERATION_FLUSH,
|
429
|
+
.available_in = 0,
|
430
|
+
.next_in = NULL
|
431
|
+
};
|
432
|
+
|
433
|
+
do {
|
434
|
+
rb_thread_call_without_gvl(compress_no_gvl, (void*)&args, NULL, NULL);
|
435
|
+
push_output(br);
|
436
|
+
} while (BrotliEncoderHasMoreOutput(br->state));
|
437
|
+
|
438
|
+
if (rb_respond_to(br->io, id_flush)) {
|
439
|
+
rb_funcall(br->io, id_flush, 0);
|
440
|
+
}
|
441
|
+
return self;
|
442
|
+
}
|
443
|
+
|
444
|
+
static VALUE rb_writer_close(VALUE self) {
|
445
|
+
struct brotli* br;
|
446
|
+
TypedData_Get_Struct(self, struct brotli, &brotli_data_type, br);
|
447
|
+
|
448
|
+
rb_writer_finish(self);
|
449
|
+
|
450
|
+
if (rb_respond_to(br->io, id_close)) {
|
451
|
+
rb_funcall(br->io, id_close, 0);
|
452
|
+
}
|
453
|
+
return br->io;
|
454
|
+
}
|
455
|
+
|
296
456
|
/*******************************************************************************
|
297
457
|
* entry
|
298
458
|
******************************************************************************/
|
@@ -300,8 +460,27 @@ brotli_deflate(int argc, VALUE *argv, VALUE self)
|
|
300
460
|
void
|
301
461
|
Init_brotli(void)
|
302
462
|
{
|
463
|
+
#if HAVE_RB_EXT_RACTOR_SAFE
|
464
|
+
rb_ext_ractor_safe(true);
|
465
|
+
#endif
|
466
|
+
|
467
|
+
VALUE rb_mBrotli;
|
468
|
+
VALUE rb_Writer;
|
303
469
|
rb_mBrotli = rb_define_module("Brotli");
|
304
470
|
rb_eBrotli = rb_define_class_under(rb_mBrotli, "Error", rb_eStandardError);
|
471
|
+
rb_global_variable(&rb_eBrotli);
|
305
472
|
rb_define_singleton_method(rb_mBrotli, "deflate", RUBY_METHOD_FUNC(brotli_deflate), -1);
|
306
473
|
rb_define_singleton_method(rb_mBrotli, "inflate", RUBY_METHOD_FUNC(brotli_inflate), 1);
|
474
|
+
rb_define_singleton_method(rb_mBrotli, "version", RUBY_METHOD_FUNC(brotli_version), 0);
|
475
|
+
// Brotli::Writer
|
476
|
+
id_write = rb_intern("write");
|
477
|
+
id_flush = rb_intern("flush");
|
478
|
+
id_close = rb_intern("close");
|
479
|
+
rb_Writer = rb_define_class_under(rb_mBrotli, "Writer", rb_cObject);
|
480
|
+
rb_define_alloc_func(rb_Writer, rb_writer_alloc);
|
481
|
+
rb_define_method(rb_Writer, "initialize", RUBY_METHOD_FUNC(rb_writer_initialize), -1);
|
482
|
+
rb_define_method(rb_Writer, "write", RUBY_METHOD_FUNC(rb_writer_write), 1);
|
483
|
+
rb_define_method(rb_Writer, "finish", RUBY_METHOD_FUNC(rb_writer_finish), 0);
|
484
|
+
rb_define_method(rb_Writer, "flush", RUBY_METHOD_FUNC(rb_writer_flush), 0);
|
485
|
+
rb_define_method(rb_Writer, "close", RUBY_METHOD_FUNC(rb_writer_close), 0);
|
307
486
|
}
|
data/ext/brotli/buffer.c
CHANGED
@@ -34,13 +34,7 @@ static
|
|
34
34
|
buffer_t*
|
35
35
|
expand_buffer(buffer_t* const buffer, const size_t need) {
|
36
36
|
size_t size = need * buffer->expand_ratio / 100;
|
37
|
-
|
38
|
-
if (ptr == NULL) {
|
39
|
-
return NULL;
|
40
|
-
}
|
41
|
-
memcpy(ptr, buffer->ptr, buffer->size);
|
42
|
-
free(buffer->ptr);
|
43
|
-
buffer->ptr = ptr;
|
37
|
+
buffer->ptr = realloc(buffer->ptr, size);
|
44
38
|
buffer->size = size;
|
45
39
|
buffer->expand_count += 1;
|
46
40
|
return buffer;
|
data/ext/brotli/buffer.h
CHANGED
data/ext/brotli/extconf.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "mkmf"
|
2
|
+
require "fileutils"
|
3
|
+
require "rbconfig"
|
4
4
|
|
5
5
|
dir_config("brotli")
|
6
6
|
|
@@ -13,36 +13,44 @@ have_dev_pkg = [
|
|
13
13
|
pkg_config("libbrotlienc")
|
14
14
|
].all? { |e| e }
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
if enable_config("vendor")
|
17
|
+
have_dev_pkg = false
|
18
|
+
Logging::message "Use vendor brotli\n"
|
19
19
|
end
|
20
20
|
|
21
|
-
|
21
|
+
$CPPFLAGS << " -DOS_MACOSX" if RbConfig::CONFIG["host_os"] =~ /darwin|mac os/
|
22
|
+
$INCFLAGS << " -I$(srcdir)/enc -I$(srcdir)/dec -I$(srcdir)/common -I$(srcdir)/include" unless have_dev_pkg
|
23
|
+
|
24
|
+
create_makefile("brotli/brotli")
|
22
25
|
|
23
26
|
unless have_dev_pkg
|
24
|
-
__DIR__ = File.expand_path(File.dirname
|
27
|
+
__DIR__ = File.expand_path(File.dirname(__FILE__))
|
25
28
|
|
26
29
|
%w[enc dec common include].each do |dirname|
|
30
|
+
FileUtils.rm_rf dirname
|
27
31
|
FileUtils.mkdir_p dirname
|
28
|
-
FileUtils.cp_r
|
32
|
+
FileUtils.cp_r(
|
33
|
+
File.expand_path(File.join(__DIR__, "..", "..", "vendor", "brotli", "c", dirname), __DIR__),
|
34
|
+
__DIR__,
|
35
|
+
verbose: true
|
36
|
+
)
|
29
37
|
end
|
30
38
|
|
31
39
|
srcs = []
|
32
40
|
objs = []
|
33
|
-
Dir[File.expand_path(File.join(
|
34
|
-
file[__DIR__ + File::SEPARATOR] =
|
41
|
+
Dir[File.expand_path(File.join("{enc,dec,common,include}", "**", "*.c"), __DIR__)].sort.each do |file|
|
42
|
+
file[__DIR__ + File::SEPARATOR] = ""
|
35
43
|
srcs << file
|
36
|
-
objs << file.sub(/\.c\z/,
|
44
|
+
objs << file.sub(/\.c\z/, "." + RbConfig::CONFIG["OBJEXT"])
|
37
45
|
end
|
38
46
|
|
39
|
-
File.open(
|
40
|
-
obj_ext = RbConfig::CONFIG[
|
41
|
-
src =
|
47
|
+
File.open("Makefile", "r+") do |f|
|
48
|
+
obj_ext = RbConfig::CONFIG["OBJEXT"]
|
49
|
+
src = "ORIG_SRCS = brotli.c buffer.c"
|
42
50
|
obj = "OBJS = brotli.#{obj_ext} buffer.#{obj_ext}"
|
43
51
|
txt = f.read
|
44
|
-
|
45
|
-
|
52
|
+
.sub(/^ORIG_SRCS = .*$/, "#{src} #{srcs.join(" ")}")
|
53
|
+
.sub(/^OBJS = .*$/, "#{obj} #{objs.join(" ")}")
|
46
54
|
f.rewind
|
47
55
|
f.write txt
|
48
56
|
end
|
data/lib/brotli/version.rb
CHANGED