brotli 0.7.0 → 0.9.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/README.md +113 -1
- data/ext/brotli/brotli.c +908 -288
- data/ext/brotli/brotli.h +0 -5
- data/ext/brotli/buffer.c +43 -65
- data/ext/brotli/buffer.h +6 -9
- data/ext/brotli/extconf.rb +115 -50
- data/lib/brotli/reader.rb +167 -0
- data/lib/brotli/version.rb +1 -1
- data/lib/brotli/writer.rb +81 -0
- data/lib/brotli.rb +2 -0
- data/vendor/brotli/c/common/constants.c +7 -7
- data/vendor/brotli/c/common/constants.h +2 -5
- data/vendor/brotli/c/common/context.c +2 -2
- data/vendor/brotli/c/common/context.h +1 -2
- data/vendor/brotli/c/common/dictionary.c +4 -5856
- data/vendor/brotli/c/common/dictionary.h +1 -2
- data/vendor/brotli/c/common/dictionary_inc.h +5847 -0
- data/vendor/brotli/c/common/platform.c +0 -4
- data/vendor/brotli/c/common/platform.h +182 -43
- data/vendor/brotli/c/common/shared_dictionary.c +3 -7
- data/vendor/brotli/c/common/shared_dictionary_internal.h +1 -1
- data/vendor/brotli/c/common/static_init.h +56 -0
- data/vendor/brotli/c/common/transform.c +6 -4
- data/vendor/brotli/c/common/transform.h +1 -2
- data/vendor/brotli/c/common/version.h +3 -3
- data/vendor/brotli/c/dec/bit_reader.c +2 -3
- data/vendor/brotli/c/dec/bit_reader.h +0 -4
- data/vendor/brotli/c/dec/decode.c +128 -39
- data/vendor/brotli/c/dec/huffman.c +2 -5
- data/vendor/brotli/c/dec/huffman.h +0 -2
- data/vendor/brotli/c/dec/prefix.c +67 -0
- data/vendor/brotli/c/dec/prefix.h +18 -708
- data/vendor/brotli/c/dec/prefix_inc.h +707 -0
- data/vendor/brotli/c/dec/state.c +18 -15
- data/vendor/brotli/c/dec/state.h +2 -6
- data/vendor/brotli/c/dec/static_init.c +53 -0
- data/vendor/brotli/c/dec/static_init.h +30 -0
- data/vendor/brotli/c/enc/backward_references.c +32 -8
- data/vendor/brotli/c/enc/backward_references.h +1 -5
- data/vendor/brotli/c/enc/backward_references_hq.c +15 -15
- data/vendor/brotli/c/enc/backward_references_hq.h +1 -5
- data/vendor/brotli/c/enc/bit_cost.c +28 -4
- data/vendor/brotli/c/enc/bit_cost.h +8 -40
- data/vendor/brotli/c/enc/bit_cost_inc.h +1 -1
- data/vendor/brotli/c/enc/block_splitter.c +9 -12
- data/vendor/brotli/c/enc/block_splitter.h +0 -3
- data/vendor/brotli/c/enc/block_splitter_inc.h +14 -8
- data/vendor/brotli/c/enc/brotli_bit_stream.c +10 -9
- data/vendor/brotli/c/enc/brotli_bit_stream.h +0 -6
- data/vendor/brotli/c/enc/cluster.c +0 -2
- data/vendor/brotli/c/enc/cluster.h +0 -2
- data/vendor/brotli/c/enc/command.c +1 -1
- data/vendor/brotli/c/enc/command.h +8 -10
- data/vendor/brotli/c/enc/compound_dictionary.c +3 -5
- data/vendor/brotli/c/enc/compound_dictionary.h +1 -4
- data/vendor/brotli/c/enc/compress_fragment.c +3 -13
- data/vendor/brotli/c/enc/compress_fragment.h +0 -2
- data/vendor/brotli/c/enc/compress_fragment_two_pass.c +5 -15
- data/vendor/brotli/c/enc/compress_fragment_two_pass.h +0 -2
- data/vendor/brotli/c/enc/dictionary_hash.c +127 -1830
- data/vendor/brotli/c/enc/dictionary_hash.h +23 -3
- data/vendor/brotli/c/enc/dictionary_hash_inc.h +1829 -0
- data/vendor/brotli/c/enc/encode.c +77 -52
- data/vendor/brotli/c/enc/encoder_dict.c +9 -7
- data/vendor/brotli/c/enc/encoder_dict.h +2 -4
- data/vendor/brotli/c/enc/entropy_encode.c +3 -6
- data/vendor/brotli/c/enc/entropy_encode.h +2 -4
- data/vendor/brotli/c/enc/entropy_encode_static.h +18 -12
- data/vendor/brotli/c/enc/fast_log.c +1 -1
- data/vendor/brotli/c/enc/fast_log.h +2 -3
- data/vendor/brotli/c/enc/find_match_length.h +0 -2
- data/vendor/brotli/c/enc/hash.h +38 -31
- data/vendor/brotli/c/enc/hash_base.h +38 -0
- data/vendor/brotli/c/enc/hash_forgetful_chain_inc.h +11 -1
- data/vendor/brotli/c/enc/hash_longest_match64_inc.h +24 -7
- data/vendor/brotli/c/enc/hash_longest_match64_simd_inc.h +304 -0
- data/vendor/brotli/c/enc/hash_longest_match_inc.h +30 -11
- data/vendor/brotli/c/enc/hash_longest_match_quickly_inc.h +4 -0
- data/vendor/brotli/c/enc/hash_longest_match_simd_inc.h +278 -0
- data/vendor/brotli/c/enc/histogram.c +1 -0
- data/vendor/brotli/c/enc/histogram.h +0 -4
- data/vendor/brotli/c/enc/literal_cost.c +4 -6
- data/vendor/brotli/c/enc/literal_cost.h +0 -2
- data/vendor/brotli/c/enc/matching_tag_mask.h +69 -0
- data/vendor/brotli/c/enc/memory.c +0 -5
- data/vendor/brotli/c/enc/memory.h +0 -4
- data/vendor/brotli/c/enc/metablock.c +7 -9
- data/vendor/brotli/c/enc/metablock.h +3 -3
- data/vendor/brotli/c/enc/metablock_inc.h +4 -4
- data/vendor/brotli/c/enc/params.h +0 -1
- data/vendor/brotli/c/enc/prefix.h +0 -2
- data/vendor/brotli/c/enc/quality.h +17 -10
- data/vendor/brotli/c/enc/ringbuffer.h +1 -4
- data/vendor/brotli/c/enc/state.h +2 -2
- data/vendor/brotli/c/enc/static_dict.c +5 -11
- data/vendor/brotli/c/enc/static_dict.h +1 -3
- data/vendor/brotli/c/enc/static_dict_lut.c +224 -0
- data/vendor/brotli/c/enc/static_dict_lut.h +20 -5837
- data/vendor/brotli/c/enc/static_dict_lut_inc.h +5830 -0
- data/vendor/brotli/c/enc/static_init.c +59 -0
- data/vendor/brotli/c/enc/static_init.h +30 -0
- data/vendor/brotli/c/enc/utf8_util.c +1 -1
- data/vendor/brotli/c/enc/utf8_util.h +0 -2
- data/vendor/brotli/c/enc/write_bits.h +0 -2
- data/vendor/brotli/c/include/brotli/decode.h +1 -1
- data/vendor/brotli/c/include/brotli/encode.h +5 -1
- data/vendor/brotli/c/include/brotli/port.h +4 -7
- data/vendor/brotli/c/include/brotli/types.h +2 -2
- metadata +24 -28
- data/.github/workflows/main.yml +0 -37
- data/.github/workflows/publish.yml +0 -24
- data/.gitignore +0 -18
- data/.gitmodules +0 -3
- data/.rspec +0 -2
- data/Dockerfile +0 -38
- data/Gemfile +0 -10
- data/Rakefile +0 -42
- data/bin/before_install.sh +0 -9
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/brotli.gemspec +0 -27
- data/smoke.sh +0 -8
- data/test/brotli_test.rb +0 -183
- data/test/brotli_writer_test.rb +0 -93
- data/test/test_helper.rb +0 -9
- data/vendor/brotli/c/common/dictionary.bin +0 -432
- data/vendor/brotli/c/common/dictionary.bin.br +0 -0
data/ext/brotli/brotli.h
CHANGED
|
@@ -3,16 +3,11 @@
|
|
|
3
3
|
|
|
4
4
|
#include "ruby.h"
|
|
5
5
|
|
|
6
|
-
// ruby/thread.h is ruby 2.x
|
|
7
|
-
#ifdef HAVE_RUBY_THREAD_H
|
|
8
6
|
#include "ruby/thread.h"
|
|
9
|
-
#endif
|
|
10
7
|
|
|
11
8
|
#include "brotli/encode.h"
|
|
12
9
|
#include "brotli/decode.h"
|
|
13
|
-
#ifdef HAVE_BROTLI_SHARED_DICTIONARY_H
|
|
14
10
|
#include "brotli/shared_dictionary.h"
|
|
15
|
-
#endif
|
|
16
11
|
#include "buffer.h"
|
|
17
12
|
|
|
18
13
|
#endif /* BROTLI_H */
|
data/ext/brotli/buffer.c
CHANGED
|
@@ -1,90 +1,68 @@
|
|
|
1
1
|
#include "buffer.h"
|
|
2
2
|
#include "ruby/ruby.h"
|
|
3
|
-
#define INITIAL (1024)
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
buffer_t *buffer = ruby_xmalloc(sizeof(buffer_t));
|
|
8
|
-
if (buffer == NULL) {
|
|
9
|
-
return NULL;
|
|
10
|
-
}
|
|
4
|
+
#include <stdint.h>
|
|
5
|
+
#include <string.h>
|
|
11
6
|
|
|
7
|
+
#define BUFFER_INITIAL_SIZE 1024
|
|
8
|
+
|
|
9
|
+
buffer_t*
|
|
10
|
+
create_buffer(size_t initial)
|
|
11
|
+
{
|
|
12
|
+
buffer_t *buffer = ruby_xmalloc(sizeof(*buffer));
|
|
12
13
|
buffer->used = 0;
|
|
13
|
-
buffer->
|
|
14
|
-
buffer->expand_ratio = 130;
|
|
15
|
-
buffer->size = (size_t) (initial > 0 ? initial : INITIAL);
|
|
14
|
+
buffer->size = initial > 0 ? initial : BUFFER_INITIAL_SIZE;
|
|
16
15
|
buffer->ptr = ruby_xmalloc(buffer->size);
|
|
17
|
-
if (buffer->ptr == NULL) {
|
|
18
|
-
delete_buffer(buffer);
|
|
19
|
-
return NULL;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
16
|
return buffer;
|
|
23
17
|
}
|
|
24
18
|
|
|
25
19
|
void
|
|
26
|
-
delete_buffer(buffer_t* buffer)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
20
|
+
delete_buffer(buffer_t* buffer)
|
|
21
|
+
{
|
|
22
|
+
if (!buffer) {
|
|
23
|
+
return;
|
|
30
24
|
}
|
|
25
|
+
|
|
26
|
+
ruby_xfree(buffer->ptr);
|
|
31
27
|
ruby_xfree(buffer);
|
|
32
28
|
}
|
|
33
29
|
|
|
34
|
-
static
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
size_t size =
|
|
38
|
-
buffer->ptr = ruby_xrealloc(buffer->ptr, size);
|
|
39
|
-
buffer->size = size;
|
|
40
|
-
buffer->expand_count += 1;
|
|
41
|
-
return buffer;
|
|
42
|
-
}
|
|
30
|
+
static size_t
|
|
31
|
+
buffer_size_for(size_t current, size_t required)
|
|
32
|
+
{
|
|
33
|
+
size_t size = current > 0 ? current : BUFFER_INITIAL_SIZE;
|
|
43
34
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (expand_buffer(buffer, buffer->used + size) == NULL) {
|
|
48
|
-
return NULL;
|
|
35
|
+
while (size < required) {
|
|
36
|
+
if (size > SIZE_MAX / 2) {
|
|
37
|
+
return required;
|
|
49
38
|
}
|
|
39
|
+
size *= 2;
|
|
50
40
|
}
|
|
51
|
-
memcpy(buffer->ptr + buffer->used, ptr, size);
|
|
52
|
-
buffer->used += size;
|
|
53
|
-
return buffer;
|
|
54
|
-
}
|
|
55
41
|
|
|
56
|
-
|
|
57
|
-
|
|
42
|
+
return size;
|
|
43
|
+
}
|
|
58
44
|
|
|
59
|
-
void
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
buffer->used,
|
|
65
|
-
buffer->expand_count);
|
|
45
|
+
static void
|
|
46
|
+
expand_buffer(buffer_t* buffer, size_t required)
|
|
47
|
+
{
|
|
48
|
+
buffer->size = buffer_size_for(buffer->size, required);
|
|
49
|
+
buffer->ptr = ruby_xrealloc(buffer->ptr, buffer->size);
|
|
66
50
|
}
|
|
67
51
|
|
|
68
|
-
|
|
69
|
-
|
|
52
|
+
void
|
|
53
|
+
append_buffer(buffer_t* buffer, const void* ptr, size_t size)
|
|
70
54
|
{
|
|
71
|
-
|
|
55
|
+
size_t required;
|
|
56
|
+
|
|
57
|
+
if (size == 0) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
72
60
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
inspect_buffer(b);
|
|
78
|
-
append_buffer(b, "3333", 4);
|
|
79
|
-
inspect_buffer(b);
|
|
80
|
-
append_buffer(b, "4444", 4);
|
|
81
|
-
inspect_buffer(b);
|
|
82
|
-
append_buffer(b, "5555", 4);
|
|
83
|
-
inspect_buffer(b);
|
|
84
|
-
append_buffer(b, "66", 2);
|
|
85
|
-
inspect_buffer(b);
|
|
61
|
+
required = buffer->used + size;
|
|
62
|
+
if (required > buffer->size) {
|
|
63
|
+
expand_buffer(buffer, required);
|
|
64
|
+
}
|
|
86
65
|
|
|
87
|
-
|
|
88
|
-
|
|
66
|
+
memcpy(buffer->ptr + buffer->used, ptr, size);
|
|
67
|
+
buffer->used += size;
|
|
89
68
|
}
|
|
90
|
-
#endif
|
data/ext/brotli/buffer.h
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
#ifndef
|
|
2
|
-
#
|
|
3
|
-
|
|
1
|
+
#ifndef BUFFER_H
|
|
2
|
+
#define BUFFER_H 1
|
|
3
|
+
|
|
4
4
|
#include <stddef.h>
|
|
5
|
-
#include <string.h>
|
|
6
5
|
|
|
7
6
|
typedef struct {
|
|
8
7
|
char* ptr;
|
|
9
8
|
size_t size;
|
|
10
9
|
size_t used;
|
|
11
|
-
size_t expand_ratio;
|
|
12
|
-
size_t expand_count;
|
|
13
10
|
} buffer_t;
|
|
14
11
|
|
|
15
|
-
buffer_t* create_buffer(
|
|
12
|
+
buffer_t* create_buffer(size_t initial);
|
|
16
13
|
void delete_buffer(buffer_t* buffer);
|
|
17
|
-
|
|
14
|
+
void append_buffer(buffer_t* buffer, const void* ptr, size_t size);
|
|
18
15
|
|
|
19
|
-
#endif
|
|
16
|
+
#endif /* BUFFER_H */
|
data/ext/brotli/extconf.rb
CHANGED
|
@@ -1,66 +1,131 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require "mkmf"
|
|
2
4
|
require "fileutils"
|
|
3
5
|
require "rbconfig"
|
|
6
|
+
require "rubygems/version"
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
VENDORED_DIRS = %w[common dec enc include].freeze
|
|
9
|
+
MINIMUM_BROTLI_VERSION = Gem::Version.new("1.2.0")
|
|
10
|
+
BUILD_DIR = Dir.pwd
|
|
11
|
+
VENDORED_SOURCE_DIR = File.expand_path("../../vendor/brotli/c", __dir__)
|
|
6
12
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
have_header("brotli/decode.h"),
|
|
10
|
-
have_header("brotli/encode.h"),
|
|
11
|
-
pkg_config("libbrotlicommon"),
|
|
12
|
-
pkg_config("libbrotlidec"),
|
|
13
|
-
pkg_config("libbrotlienc")
|
|
14
|
-
].all? { |e| e }
|
|
15
|
-
|
|
16
|
-
have_header("brotli/shared_dictionary.h")
|
|
17
|
-
have_func("BrotliEncoderPrepareDictionary", "brotli/encode.h")
|
|
18
|
-
have_func("BrotliEncoderAttachPreparedDictionary", "brotli/encode.h")
|
|
19
|
-
have_func("BrotliDecoderAttachDictionary", "brotli/decode.h")
|
|
20
|
-
|
|
21
|
-
if enable_config("vendor")
|
|
22
|
-
have_dev_pkg = false
|
|
23
|
-
Logging::message "Use vendor brotli\n"
|
|
24
|
-
$defs << "-DHAVE_BROTLI_SHARED_DICTIONARY_H"
|
|
25
|
-
$defs << "-DHAVE_BROTLIENCODERPREPAREDICTIONARY"
|
|
26
|
-
$defs << "-DHAVE_BROTLIENCODERATTACHPREPAREDDICTIONARY"
|
|
27
|
-
$defs << "-DHAVE_BROTLIDECODERATTACHDICTIONARY"
|
|
13
|
+
def generated_vendored_dirs
|
|
14
|
+
VENDORED_DIRS.map { |dirname| File.join(BUILD_DIR, dirname) }
|
|
28
15
|
end
|
|
29
16
|
|
|
30
|
-
|
|
31
|
-
|
|
17
|
+
def remove_generated_vendored_dirs
|
|
18
|
+
generated_vendored_dirs.each { |path| FileUtils.rm_rf(path) }
|
|
19
|
+
end
|
|
32
20
|
|
|
33
|
-
|
|
21
|
+
def copy_vendored_sources
|
|
22
|
+
sources = Dir[File.join(VENDORED_SOURCE_DIR, "{common,dec,enc,include}", "**", "*.{c,h}")].sort
|
|
34
23
|
|
|
35
|
-
|
|
36
|
-
|
|
24
|
+
if sources.empty?
|
|
25
|
+
abort "ERROR: Vendored Brotli sources not found at #{VENDORED_SOURCE_DIR}.\n" \
|
|
26
|
+
"Install system libbrotli-dev >= #{MINIMUM_BROTLI_VERSION} or ensure vendor sources are present."
|
|
27
|
+
end
|
|
37
28
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
verbose: true
|
|
45
|
-
)
|
|
29
|
+
sources.each do |source|
|
|
30
|
+
relative_path = source.delete_prefix("#{VENDORED_SOURCE_DIR}/")
|
|
31
|
+
destination = File.join(BUILD_DIR, relative_path)
|
|
32
|
+
|
|
33
|
+
FileUtils.mkdir_p(File.dirname(destination))
|
|
34
|
+
FileUtils.cp(source, destination)
|
|
46
35
|
end
|
|
36
|
+
end
|
|
47
37
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
file[__DIR__ + File::SEPARATOR] = ""
|
|
52
|
-
srcs << file
|
|
53
|
-
objs << file.sub(/\.c\z/, "." + RbConfig::CONFIG["OBJEXT"])
|
|
38
|
+
def vendored_source_files
|
|
39
|
+
Dir[File.join(BUILD_DIR, "{common,dec,enc,include}", "**", "*.c")].sort.map do |path|
|
|
40
|
+
path.delete_prefix("#{BUILD_DIR}/")
|
|
54
41
|
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def add_vendored_sources_to_makefile
|
|
45
|
+
objext = RbConfig::CONFIG["OBJEXT"]
|
|
46
|
+
source_files = vendored_source_files
|
|
47
|
+
object_files = source_files.map { |path| path.sub(/\.c\z/, ".#{objext}") }
|
|
48
|
+
|
|
49
|
+
makefile = File.read("Makefile")
|
|
50
|
+
makefile = makefile
|
|
51
|
+
.sub(/^ORIG_SRCS = .*$/, "ORIG_SRCS = brotli.c buffer.c #{source_files.join(" ")}")
|
|
52
|
+
.sub(/^OBJS = .*$/, "OBJS = brotli.#{objext} buffer.#{objext} #{object_files.join(" ")}")
|
|
53
|
+
File.write("Makefile", makefile)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def mkmf_flags
|
|
57
|
+
{
|
|
58
|
+
cflags: $CFLAGS.dup,
|
|
59
|
+
cxxflags: $CXXFLAGS.dup,
|
|
60
|
+
cppflags: $CPPFLAGS.dup,
|
|
61
|
+
defs: $defs.dup,
|
|
62
|
+
incflags: $INCFLAGS.dup,
|
|
63
|
+
ldflags: $LDFLAGS.dup,
|
|
64
|
+
libs: $libs.dup,
|
|
65
|
+
local_libs: $LOCAL_LIBS.dup
|
|
66
|
+
}
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def restore_mkmf_flags(flags)
|
|
70
|
+
$CFLAGS = flags[:cflags]
|
|
71
|
+
$CXXFLAGS = flags[:cxxflags]
|
|
72
|
+
$CPPFLAGS = flags[:cppflags]
|
|
73
|
+
$defs = flags[:defs]
|
|
74
|
+
$INCFLAGS = flags[:incflags]
|
|
75
|
+
$LDFLAGS = flags[:ldflags]
|
|
76
|
+
$libs = flags[:libs]
|
|
77
|
+
$LOCAL_LIBS = flags[:local_libs]
|
|
78
|
+
end
|
|
55
79
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
80
|
+
def system_brotli_version
|
|
81
|
+
version = pkg_config("libbrotlicommon", "modversion")
|
|
82
|
+
Gem::Version.new(version) if version
|
|
83
|
+
rescue ArgumentError
|
|
84
|
+
nil
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def system_brotli_available?
|
|
88
|
+
flags = mkmf_flags
|
|
89
|
+
version = system_brotli_version
|
|
90
|
+
|
|
91
|
+
unless version && version >= MINIMUM_BROTLI_VERSION
|
|
92
|
+
Logging.message(
|
|
93
|
+
"System Brotli version %s is too old; need >= %s\n",
|
|
94
|
+
version || "unknown",
|
|
95
|
+
MINIMUM_BROTLI_VERSION
|
|
96
|
+
)
|
|
97
|
+
restore_mkmf_flags(flags)
|
|
98
|
+
return false
|
|
65
99
|
end
|
|
100
|
+
|
|
101
|
+
available = pkg_config("libbrotlicommon") &&
|
|
102
|
+
pkg_config("libbrotlidec") &&
|
|
103
|
+
pkg_config("libbrotlienc") &&
|
|
104
|
+
have_header("brotli/decode.h") &&
|
|
105
|
+
have_header("brotli/encode.h") &&
|
|
106
|
+
have_header("brotli/shared_dictionary.h") &&
|
|
107
|
+
have_func("BrotliEncoderPrepareDictionary", "brotli/encode.h") &&
|
|
108
|
+
have_func("BrotliEncoderAttachPreparedDictionary", "brotli/encode.h") &&
|
|
109
|
+
have_func("BrotliDecoderAttachDictionary", "brotli/decode.h")
|
|
110
|
+
|
|
111
|
+
restore_mkmf_flags(flags) unless available
|
|
112
|
+
available
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
dir_config("brotli")
|
|
116
|
+
have_func("rb_gc_mark_movable")
|
|
117
|
+
|
|
118
|
+
$CPPFLAGS << " -DOS_MACOSX" if RbConfig::CONFIG["host_os"] =~ /darwin|mac os/
|
|
119
|
+
|
|
120
|
+
remove_generated_vendored_dirs
|
|
121
|
+
|
|
122
|
+
use_vendored_brotli = enable_config("vendor", false) || !system_brotli_available?
|
|
123
|
+
|
|
124
|
+
if use_vendored_brotli
|
|
125
|
+
Logging.message "Using vendored Brotli sources\n"
|
|
126
|
+
copy_vendored_sources
|
|
127
|
+
$INCFLAGS << " -Ienc -Idec -Icommon -Iinclude"
|
|
66
128
|
end
|
|
129
|
+
|
|
130
|
+
create_makefile("brotli/brotli")
|
|
131
|
+
add_vendored_sources_to_makefile if use_vendored_brotli
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Brotli
|
|
4
|
+
class Reader
|
|
5
|
+
DEFAULT_READ_SIZE = 8192
|
|
6
|
+
|
|
7
|
+
def initialize(io, options = nil, **kwargs)
|
|
8
|
+
raise ArgumentError, "io should not be nil" if io.nil?
|
|
9
|
+
|
|
10
|
+
@io = io
|
|
11
|
+
@decompressor = Decompressor.new(normalize_options(options, kwargs))
|
|
12
|
+
@output_buffer = +""
|
|
13
|
+
@closed = false
|
|
14
|
+
@finished = false
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def read(length = nil, outbuf = nil)
|
|
18
|
+
ensure_open
|
|
19
|
+
|
|
20
|
+
if length.nil?
|
|
21
|
+
drain_stream
|
|
22
|
+
return replace_outbuf(outbuf, take_output)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
len = Integer(length)
|
|
26
|
+
raise ArgumentError, "negative length #{len} given" if len.negative?
|
|
27
|
+
return replace_outbuf(outbuf, +"") if len.zero?
|
|
28
|
+
|
|
29
|
+
fill_buffer(len, output_limit: len)
|
|
30
|
+
if @output_buffer.empty? && @finished
|
|
31
|
+
replace_outbuf(outbuf, +"") if outbuf
|
|
32
|
+
return nil
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
replace_outbuf(outbuf, take_output(len))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def readpartial(maxlen, outbuf = nil)
|
|
39
|
+
ensure_open
|
|
40
|
+
|
|
41
|
+
len = Integer(maxlen)
|
|
42
|
+
raise ArgumentError, "max length must be positive" unless len.positive?
|
|
43
|
+
|
|
44
|
+
until @finished || !@output_buffer.empty?
|
|
45
|
+
fill_buffer(1, output_limit: len, stop_after_output: true)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
if @output_buffer.empty?
|
|
49
|
+
replace_outbuf(outbuf, +"") if outbuf
|
|
50
|
+
raise EOFError, "end of file reached"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
replace_outbuf(outbuf, take_output(len))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def eof?
|
|
57
|
+
ensure_open
|
|
58
|
+
|
|
59
|
+
return false unless @output_buffer.empty?
|
|
60
|
+
|
|
61
|
+
fill_buffer(1, output_limit: 1, stop_after_output: true) unless @finished
|
|
62
|
+
@output_buffer.empty? && @finished
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def close
|
|
66
|
+
return @io if @closed
|
|
67
|
+
|
|
68
|
+
begin
|
|
69
|
+
@io.close if @io.respond_to?(:close)
|
|
70
|
+
ensure
|
|
71
|
+
@closed = true
|
|
72
|
+
@finished = true
|
|
73
|
+
@decompressor = nil
|
|
74
|
+
@output_buffer.clear
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
@io
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def closed?
|
|
81
|
+
@closed
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def ensure_open
|
|
87
|
+
raise Error, "Reader is closed" if @closed
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def replace_outbuf(outbuf, string)
|
|
91
|
+
return string unless outbuf
|
|
92
|
+
|
|
93
|
+
buffer = coerce_string(outbuf)
|
|
94
|
+
buffer.replace(string)
|
|
95
|
+
buffer
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def take_output(length = @output_buffer.bytesize)
|
|
99
|
+
return +"".b if length <= 0 || @output_buffer.empty?
|
|
100
|
+
|
|
101
|
+
if length >= @output_buffer.bytesize
|
|
102
|
+
output = @output_buffer
|
|
103
|
+
@output_buffer = +""
|
|
104
|
+
return output
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
@output_buffer.slice!(0, length)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def drain_stream
|
|
111
|
+
fill_buffer(@output_buffer.bytesize + 1) until @finished
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def fill_buffer(wanted, output_limit: nil, stop_after_output: false)
|
|
115
|
+
while @output_buffer.bytesize < wanted && !@finished
|
|
116
|
+
buffered = @output_buffer.bytesize
|
|
117
|
+
chunk = next_chunk
|
|
118
|
+
feed_chunk(chunk || +"", output_limit: remaining_output_limit(output_limit))
|
|
119
|
+
break if stop_after_output && !@output_buffer.empty?
|
|
120
|
+
|
|
121
|
+
next unless chunk.nil? || chunk.empty?
|
|
122
|
+
next if @finished || @output_buffer.bytesize > buffered || !@decompressor.can_accept_more_data
|
|
123
|
+
|
|
124
|
+
raise Error, "Unexpected end of compressed stream"
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def feed_chunk(chunk, output_limit: nil)
|
|
129
|
+
output = if output_limit&.positive?
|
|
130
|
+
@decompressor.process(chunk, output_buffer_limit: output_limit)
|
|
131
|
+
else
|
|
132
|
+
@decompressor.process(chunk)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
@output_buffer << output unless output.empty?
|
|
136
|
+
@finished = @decompressor.finished?
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def next_chunk
|
|
140
|
+
return +"".b unless @decompressor.can_accept_more_data
|
|
141
|
+
|
|
142
|
+
@io.respond_to?(:readpartial) ? @io.readpartial(DEFAULT_READ_SIZE) : @io.read(DEFAULT_READ_SIZE)
|
|
143
|
+
rescue EOFError
|
|
144
|
+
nil
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def remaining_output_limit(output_limit)
|
|
148
|
+
return unless output_limit
|
|
149
|
+
|
|
150
|
+
[output_limit - @output_buffer.bytesize, 0].max
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def normalize_options(options, kwargs)
|
|
154
|
+
return kwargs if options.nil?
|
|
155
|
+
|
|
156
|
+
unless options.is_a?(Hash)
|
|
157
|
+
raise TypeError, "no implicit conversion of #{options.class} into Hash"
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
kwargs.empty? ? options : options.merge(kwargs)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def coerce_string(value)
|
|
164
|
+
String.try_convert(value) || raise(TypeError, "no implicit conversion of #{value.class} into String")
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
data/lib/brotli/version.rb
CHANGED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Brotli
|
|
4
|
+
class Writer
|
|
5
|
+
def initialize(io, options = nil, **kwargs)
|
|
6
|
+
raise ArgumentError, "io should not be nil" if io.nil?
|
|
7
|
+
|
|
8
|
+
@io = io
|
|
9
|
+
@compressor = Compressor.new(normalize_options(options, kwargs))
|
|
10
|
+
@closed = false
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def write(data)
|
|
14
|
+
ensure_open
|
|
15
|
+
|
|
16
|
+
data = coerce_string(data)
|
|
17
|
+
write_output(@compressor.process(data))
|
|
18
|
+
data.bytesize
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def finish
|
|
22
|
+
ensure_open
|
|
23
|
+
|
|
24
|
+
write_output(@compressor.finish)
|
|
25
|
+
@io
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def flush
|
|
29
|
+
ensure_open
|
|
30
|
+
|
|
31
|
+
write_output(@compressor.flush)
|
|
32
|
+
@io.flush if @io.respond_to?(:flush)
|
|
33
|
+
self
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def close
|
|
37
|
+
return @io if @closed
|
|
38
|
+
|
|
39
|
+
begin
|
|
40
|
+
finish
|
|
41
|
+
ensure
|
|
42
|
+
begin
|
|
43
|
+
@io.close if @io.respond_to?(:close)
|
|
44
|
+
ensure
|
|
45
|
+
@closed = true
|
|
46
|
+
@compressor = nil
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
@io
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def closed?
|
|
54
|
+
@closed
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def ensure_open
|
|
60
|
+
raise Error, "Writer is closed" if @closed
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def write_output(output)
|
|
64
|
+
@io.write(output) unless output.empty?
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def normalize_options(options, kwargs)
|
|
68
|
+
return kwargs if options.nil?
|
|
69
|
+
|
|
70
|
+
unless options.is_a?(Hash)
|
|
71
|
+
raise TypeError, "no implicit conversion of #{options.class} into Hash"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
kwargs.empty? ? options : options.merge(kwargs)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def coerce_string(value)
|
|
78
|
+
String.try_convert(value) || raise(TypeError, "no implicit conversion of #{value.class} into String")
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
data/lib/brotli.rb
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
#include "constants.h"
|
|
8
8
|
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
const BROTLI_MODEL("small")
|
|
10
|
+
BrotliPrefixCodeRange _kBrotliPrefixCodeRanges[BROTLI_NUM_BLOCK_LEN_SYMBOLS] = {
|
|
11
|
+
{1, 2}, {5, 2}, {9, 2}, {13, 2}, {17, 3}, {25, 3},
|
|
12
|
+
{33, 3}, {41, 3}, {49, 4}, {65, 4}, {81, 4}, {97, 4},
|
|
13
|
+
{113, 5}, {145, 5}, {177, 5}, {209, 5}, {241, 6}, {305, 6},
|
|
14
|
+
{369, 7}, {497, 8}, {753, 9}, {1265, 10}, {2289, 11}, {4337, 12},
|
|
15
|
+
{8433, 13}, {16625, 24}};
|
|
@@ -12,9 +12,6 @@
|
|
|
12
12
|
#ifndef BROTLI_COMMON_CONSTANTS_H_
|
|
13
13
|
#define BROTLI_COMMON_CONSTANTS_H_
|
|
14
14
|
|
|
15
|
-
#include <brotli/port.h>
|
|
16
|
-
#include <brotli/types.h>
|
|
17
|
-
|
|
18
15
|
#include "platform.h"
|
|
19
16
|
|
|
20
17
|
/* Specification: 7.3. Encoding of the context map */
|
|
@@ -195,7 +192,7 @@ typedef struct {
|
|
|
195
192
|
} BrotliPrefixCodeRange;
|
|
196
193
|
|
|
197
194
|
/* "Soft-private", it is exported, but not "advertised" as API. */
|
|
198
|
-
BROTLI_COMMON_API extern const
|
|
199
|
-
|
|
195
|
+
BROTLI_COMMON_API extern const BROTLI_MODEL("small")
|
|
196
|
+
BrotliPrefixCodeRange _kBrotliPrefixCodeRanges[BROTLI_NUM_BLOCK_LEN_SYMBOLS];
|
|
200
197
|
|
|
201
198
|
#endif /* BROTLI_COMMON_CONSTANTS_H_ */
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#include "context.h"
|
|
2
2
|
|
|
3
|
-
#include
|
|
3
|
+
#include "platform.h"
|
|
4
4
|
|
|
5
5
|
/* Common context lookup table for all context modes. */
|
|
6
|
-
const uint8_t _kBrotliContextLookupTable[2048] = {
|
|
6
|
+
const BROTLI_MODEL("small") uint8_t _kBrotliContextLookupTable[2048] = {
|
|
7
7
|
/* CONTEXT_LSB6, last byte. */
|
|
8
8
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
9
9
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|