ruby-brs 1.0.1 → 1.1.4
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 +73 -71
- data/ext/brs_ext/buffer.c +17 -5
- data/ext/brs_ext/buffer.h +12 -0
- data/ext/brs_ext/common.h +3 -0
- data/ext/brs_ext/error.c +2 -3
- data/ext/brs_ext/error.h +1 -1
- data/ext/brs_ext/io.c +93 -77
- data/ext/brs_ext/main.c +0 -1
- data/ext/brs_ext/option.c +23 -19
- data/ext/brs_ext/option.h +9 -10
- data/ext/brs_ext/stream/compressor.c +22 -23
- data/ext/brs_ext/stream/compressor.h +3 -3
- data/ext/brs_ext/stream/decompressor.c +18 -20
- data/ext/brs_ext/stream/decompressor.h +3 -3
- data/ext/brs_ext/string.c +30 -45
- data/ext/extconf.rb +45 -30
- data/lib/brs.rb +1 -0
- data/lib/brs/file.rb +6 -0
- data/lib/brs/option.rb +14 -7
- data/lib/brs/stream/abstract.rb +9 -12
- data/lib/brs/stream/raw/abstract.rb +6 -2
- data/lib/brs/stream/raw/compressor.rb +10 -8
- data/lib/brs/stream/raw/decompressor.rb +1 -5
- data/lib/brs/stream/reader.rb +71 -52
- data/lib/brs/stream/reader_helpers.rb +2 -0
- data/lib/brs/stream/writer.rb +10 -5
- data/lib/brs/stream/writer_helpers.rb +8 -10
- data/lib/brs/string.rb +2 -0
- data/lib/brs/validation.rb +15 -2
- data/lib/brs/version.rb +1 -1
- metadata +63 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 169f9d5837ac233e808610055a4edee6c5e133c78bd1047e951c218bd731e74d
|
4
|
+
data.tar.gz: bd9ddc4653f00f5a5dd855a14f5c2b8013fd90ffce741334f523197621cacb15
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f7014703dbf00857e5c829aef7742c85d6251858047ed7bb234ec6b18c433615a5c72f0a48ce943cd34c9074f4104af23077beb27763ad6d8d68aa2a0cace6a
|
7
|
+
data.tar.gz: 581c2b4e7d0b2cbab7c8b54427c05305238ecda8ef8e6f1a98493e01176f7e98b5a0f1009ec2f95beeb54ed6562511a08994ae24d7f75d0fed4ac7017f7eb21c
|
data/README.md
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
# Ruby bindings for brotli library
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
| Travis | AppVeyor | Circle | Codecov |
|
4
|
+
| :---: | :---: | :---: | :---: |
|
5
|
+
| [](https://travis-ci.com/andrew-aladev/ruby-brs) | [](https://ci.appveyor.com/project/andrew-aladev/ruby-brs/branch/master) | [](https://circleci.com/gh/andrew-aladev/ruby-brs/tree/master) | [](https://codecov.io/gh/andrew-aladev/ruby-brs) |
|
5
6
|
|
6
7
|
See [brotli library](https://github.com/google/brotli).
|
7
8
|
|
8
9
|
## Installation
|
9
10
|
|
10
|
-
Please install brotli library first.
|
11
|
+
Please install brotli library first, use latest 1.0.0+ version.
|
11
12
|
|
12
13
|
```sh
|
13
14
|
gem install ruby-brs
|
@@ -20,6 +21,8 @@ rake gem
|
|
20
21
|
gem install pkg/ruby-brs-*.gem
|
21
22
|
```
|
22
23
|
|
24
|
+
You can also use [overlay](https://github.com/andrew-aladev/overlay) for gentoo.
|
25
|
+
|
23
26
|
## Usage
|
24
27
|
|
25
28
|
There are simple APIs: `String` and `File`. Also you can use generic streaming API: `Stream::Writer` and `Stream::Reader`.
|
@@ -35,6 +38,27 @@ BRS::File.decompress "file.txt.br", "file.txt"
|
|
35
38
|
|
36
39
|
BRS::Stream::Writer.open("file.txt.br") { |writer| writer << "sample string" }
|
37
40
|
puts BRS::Stream::Reader.open("file.txt.br") { |reader| reader.read }
|
41
|
+
|
42
|
+
writer = BRS::Stream::Writer.new output_socket
|
43
|
+
begin
|
44
|
+
bytes_written = writer.write_nonblock "sample string"
|
45
|
+
# handle "bytes_written"
|
46
|
+
rescue IO::WaitWritable
|
47
|
+
# handle wait
|
48
|
+
ensure
|
49
|
+
writer.close
|
50
|
+
end
|
51
|
+
|
52
|
+
reader = BRS::Stream::Reader.new input_socket
|
53
|
+
begin
|
54
|
+
puts reader.read_nonblock(512)
|
55
|
+
rescue IO::WaitReadable
|
56
|
+
# handle wait
|
57
|
+
rescue ::EOFError
|
58
|
+
# handle eof
|
59
|
+
ensure
|
60
|
+
reader.close
|
61
|
+
end
|
38
62
|
```
|
39
63
|
|
40
64
|
You can create and read `tar.br` archives with `minitar` for example.
|
@@ -61,72 +85,38 @@ end
|
|
61
85
|
|
62
86
|
## Options
|
63
87
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
88
|
+
| Option | Values | Default | Description |
|
89
|
+
|------------------------------------|--------------|--------------|-------------|
|
90
|
+
| `source_buffer_length` | `0 - inf` | `0 (auto)` | internal buffer length for source data |
|
91
|
+
| `destination_buffer_length` | `0 - inf` | `0 (auto)` | internal buffer length for description data |
|
92
|
+
| `mode` | `MODES` | `:generic` | compressor mode |
|
93
|
+
| `quality` | `0 - 11` | `11` | compression level |
|
94
|
+
| `lgwin` | `10 - 24` | `22` | compressor window size |
|
95
|
+
| `lgblock` | `16 - 24` | `nil (auto)` | compressor input block size |
|
96
|
+
| `disable_literal_context_modeling` | `true/false` | `false` | disables literal context modeling format |
|
97
|
+
| `disable_ring_buffer_reallocation` | `true/false` | `false` | disables ring buffer reallocation |
|
98
|
+
| `size_hint` | `0 - inf` | `0 (auto)` | size of input (if known) |
|
99
|
+
| `large_window` | `true/false` | `false` | enables large window |
|
70
100
|
|
71
101
|
There are internal buffers for compressed and decompressed data.
|
72
|
-
For example you want to use 1 KB as
|
73
|
-
You want to use 256 B as
|
102
|
+
For example you want to use 1 KB as `source_buffer_length` for compressor - please use 256 B as `destination_buffer_length`.
|
103
|
+
You want to use 256 B as `source_buffer_length` for decompressor - please use 1 KB as `destination_buffer_length`.
|
74
104
|
|
75
|
-
|
76
|
-
0 means automatic buffer length selection.
|
105
|
+
`String` and `File` will set `:size_hint` automaticaly.
|
77
106
|
|
78
|
-
|
79
|
-
:mode
|
80
|
-
```
|
107
|
+
You can also read brotli docs for more info about options.
|
81
108
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
Values: 0 - 11, default value: 11.
|
89
|
-
|
90
|
-
```
|
91
|
-
:lgwin
|
92
|
-
```
|
93
|
-
|
94
|
-
Values: 10 - 24, default value: 22.
|
95
|
-
|
96
|
-
```
|
97
|
-
:lgblock
|
98
|
-
```
|
99
|
-
|
100
|
-
Values: 16 - 24, default value: none.
|
101
|
-
|
102
|
-
```
|
103
|
-
:disable_literal_context_modeling
|
104
|
-
```
|
105
|
-
|
106
|
-
Values: true/false, default value: false.
|
107
|
-
|
108
|
-
```
|
109
|
-
:disable_ring_buffer_reallocation
|
110
|
-
```
|
111
|
-
|
112
|
-
Values: true/false, default value: false.
|
113
|
-
|
114
|
-
```
|
115
|
-
:size_hint
|
116
|
-
```
|
117
|
-
|
118
|
-
Values: 0 - infinity, default value: 0.
|
119
|
-
|
120
|
-
```
|
121
|
-
:large_window
|
122
|
-
```
|
123
|
-
|
124
|
-
Values: true/false, default value: false.
|
125
|
-
|
126
|
-
Please read brotli docs for more info about options.
|
109
|
+
| Option | Related constants |
|
110
|
+
|-----------|-------------------|
|
111
|
+
| `mode` | `BRS::Option::MODES = %i[text font generic]` |
|
112
|
+
| `quality` | `BRS::Option::MIN_QUALITY = 0`, `BRS::Option::MAX_QUALITY = 11` |
|
113
|
+
| `lgwin` | `BRS::Option::MIN_LGWIN = 10`, `BRS::Option::MAX_LGWIN = 24` |
|
114
|
+
| `lgblock` | `BRS::Option::MIN_LGBLOCK = 16`, `BRS::Option::MAX_LGBLOCK = 24` |
|
127
115
|
|
128
116
|
Possible compressor options:
|
129
117
|
```
|
118
|
+
:source_buffer_length
|
119
|
+
:destination_buffer_length
|
130
120
|
:mode
|
131
121
|
:quality
|
132
122
|
:lgwin
|
@@ -138,6 +128,8 @@ Possible compressor options:
|
|
138
128
|
|
139
129
|
Possible decompressor options:
|
140
130
|
```
|
131
|
+
:source_buffer_length
|
132
|
+
:destination_buffer_length
|
141
133
|
:disable_ring_buffer_reallocation
|
142
134
|
:large_window
|
143
135
|
```
|
@@ -151,7 +143,7 @@ data = BRS::String.compress "sample string", :quality => 5
|
|
151
143
|
puts BRS::String.decompress(data, :disable_ring_buffer_reallocation => true)
|
152
144
|
```
|
153
145
|
|
154
|
-
|
146
|
+
HTTP encoding (`Content-Encoding: br`) using default options:
|
155
147
|
|
156
148
|
```ruby
|
157
149
|
require "brs"
|
@@ -187,7 +179,7 @@ File maintains both source and destination buffers, it accepts both `source_buff
|
|
187
179
|
|
188
180
|
## Stream::Writer
|
189
181
|
|
190
|
-
Its behaviour is similar to builtin [`Zlib::GzipWriter`](https://ruby-doc.org/stdlib-2.
|
182
|
+
Its behaviour is similar to builtin [`Zlib::GzipWriter`](https://ruby-doc.org/stdlib-2.7.0/libdoc/zlib/rdoc/Zlib/GzipWriter.html).
|
191
183
|
|
192
184
|
Writer maintains destination buffer only, so it accepts `destination_buffer_length` option only.
|
193
185
|
|
@@ -198,6 +190,8 @@ Writer maintains destination buffer only, so it accepts `destination_buffer_leng
|
|
198
190
|
Open file path and create stream writer associated with opened file.
|
199
191
|
Data will be transcoded to `:external_encoding` using `:transcode_options` before compressing.
|
200
192
|
|
193
|
+
It may be tricky to use both `:size_hint` and `:transcode_options`. You have to provide size of transcoded input.
|
194
|
+
|
201
195
|
```
|
202
196
|
::new(destination_io, options = {}, :external_encoding => nil, :transcode_options => {})
|
203
197
|
```
|
@@ -205,6 +199,8 @@ Data will be transcoded to `:external_encoding` using `:transcode_options` befor
|
|
205
199
|
Create stream writer associated with destination io.
|
206
200
|
Data will be transcoded to `:external_encoding` using `:transcode_options` before compressing.
|
207
201
|
|
202
|
+
It may be tricky to use both `:size_hint` and `:transcode_options`. You have to provide size of transcoded input.
|
203
|
+
|
208
204
|
```
|
209
205
|
#set_encoding(external_encoding, nil, transcode_options)
|
210
206
|
```
|
@@ -221,7 +217,7 @@ Set another encodings, `nil` is just for compatibility with `IO`.
|
|
221
217
|
#tell
|
222
218
|
```
|
223
219
|
|
224
|
-
See [`IO`](https://ruby-doc.org/core-2.
|
220
|
+
See [`IO`](https://ruby-doc.org/core-2.7.0/IO.html) docs.
|
225
221
|
|
226
222
|
```
|
227
223
|
#write(*objects)
|
@@ -231,7 +227,7 @@ See [`IO`](https://ruby-doc.org/core-2.6.1/IO.html) docs.
|
|
231
227
|
#closed?
|
232
228
|
```
|
233
229
|
|
234
|
-
See [`Zlib::GzipWriter`](https://ruby-doc.org/stdlib-2.
|
230
|
+
See [`Zlib::GzipWriter`](https://ruby-doc.org/stdlib-2.7.0/libdoc/zlib/rdoc/Zlib/GzipWriter.html) docs.
|
235
231
|
|
236
232
|
```
|
237
233
|
#write_nonblock(object, *options)
|
@@ -253,11 +249,11 @@ Behaviour is the same as `IO#write_nonblock` method.
|
|
253
249
|
#puts(*objects)
|
254
250
|
```
|
255
251
|
|
256
|
-
Typical helpers, see [`Zlib::GzipWriter`](https://ruby-doc.org/stdlib-2.
|
252
|
+
Typical helpers, see [`Zlib::GzipWriter`](https://ruby-doc.org/stdlib-2.7.0/libdoc/zlib/rdoc/Zlib/GzipWriter.html) docs.
|
257
253
|
|
258
254
|
## Stream::Reader
|
259
255
|
|
260
|
-
Its behaviour is similar to builtin [`Zlib::GzipReader`](https://ruby-doc.org/stdlib-2.
|
256
|
+
Its behaviour is similar to builtin [`Zlib::GzipReader`](https://ruby-doc.org/stdlib-2.7.0/libdoc/zlib/rdoc/Zlib/GzipReader.html).
|
261
257
|
|
262
258
|
Reader maintains both source and destination buffers, it accepts both `source_buffer_length` and `destination_buffer_length` options.
|
263
259
|
|
@@ -292,7 +288,7 @@ Set another encodings.
|
|
292
288
|
#tell
|
293
289
|
```
|
294
290
|
|
295
|
-
See [`IO`](https://ruby-doc.org/core-2.
|
291
|
+
See [`IO`](https://ruby-doc.org/core-2.7.0/IO.html) docs.
|
296
292
|
|
297
293
|
```
|
298
294
|
#read(bytes_to_read = nil, out_buffer = nil)
|
@@ -302,14 +298,14 @@ See [`IO`](https://ruby-doc.org/core-2.6.1/IO.html) docs.
|
|
302
298
|
#closed?
|
303
299
|
```
|
304
300
|
|
305
|
-
See [`Zlib::GzipReader`](https://ruby-doc.org/stdlib-2.
|
301
|
+
See [`Zlib::GzipReader`](https://ruby-doc.org/stdlib-2.7.0/libdoc/zlib/rdoc/Zlib/GzipReader.html) docs.
|
306
302
|
|
307
303
|
```
|
308
304
|
#readpartial(bytes_to_read = nil, out_buffer = nil)
|
309
305
|
#read_nonblock(bytes_to_read, out_buffer = nil, *options)
|
310
306
|
```
|
311
307
|
|
312
|
-
See [`IO`](https://ruby-doc.org/core-2.
|
308
|
+
See [`IO`](https://ruby-doc.org/core-2.7.0/IO.html) docs.
|
313
309
|
|
314
310
|
```
|
315
311
|
#getbyte
|
@@ -332,7 +328,13 @@ See [`IO`](https://ruby-doc.org/core-2.6.1/IO.html) docs.
|
|
332
328
|
#ungetline(line)
|
333
329
|
```
|
334
330
|
|
335
|
-
Typical helpers, see [`Zlib::GzipReader`](https://ruby-doc.org/stdlib-2.
|
331
|
+
Typical helpers, see [`Zlib::GzipReader`](https://ruby-doc.org/stdlib-2.7.0/libdoc/zlib/rdoc/Zlib/GzipReader.html) docs.
|
332
|
+
|
333
|
+
## CI
|
334
|
+
|
335
|
+
See universal test script [scripts/ci_test.sh](scripts/ci_test.sh) for CI.
|
336
|
+
Please visit [scripts/test-images](scripts/test-images).
|
337
|
+
You can run this test script using many native and cross images.
|
336
338
|
|
337
339
|
## License
|
338
340
|
|
data/ext/brs_ext/buffer.c
CHANGED
@@ -5,12 +5,24 @@
|
|
5
5
|
|
6
6
|
#include "ruby.h"
|
7
7
|
|
8
|
+
VALUE brs_ext_create_string_buffer(VALUE length)
|
9
|
+
{
|
10
|
+
return rb_str_new(NULL, NUM2SIZET(length));
|
11
|
+
}
|
12
|
+
|
13
|
+
VALUE brs_ext_resize_string_buffer(VALUE args)
|
14
|
+
{
|
15
|
+
VALUE buffer = rb_ary_entry(args, 0);
|
16
|
+
VALUE length = rb_ary_entry(args, 1);
|
17
|
+
return rb_str_resize(buffer, NUM2SIZET(length));
|
18
|
+
}
|
19
|
+
|
8
20
|
void brs_ext_buffer_exports(VALUE root_module)
|
9
21
|
{
|
10
|
-
VALUE
|
22
|
+
VALUE module = rb_define_module_under(root_module, "Buffer");
|
11
23
|
|
12
|
-
rb_define_const(
|
13
|
-
rb_define_const(
|
14
|
-
rb_define_const(
|
15
|
-
rb_define_const(
|
24
|
+
rb_define_const(module, "DEFAULT_SOURCE_BUFFER_LENGTH_FOR_COMPRESSOR", SIZET2NUM(BRS_DEFAULT_SOURCE_BUFFER_LENGTH_FOR_COMPRESSOR));
|
25
|
+
rb_define_const(module, "DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_COMPRESSOR", SIZET2NUM(BRS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_COMPRESSOR));
|
26
|
+
rb_define_const(module, "DEFAULT_SOURCE_BUFFER_LENGTH_FOR_DECOMPRESSOR", SIZET2NUM(BRS_DEFAULT_SOURCE_BUFFER_LENGTH_FOR_DECOMPRESSOR));
|
27
|
+
rb_define_const(module, "DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_DECOMPRESSOR", SIZET2NUM(BRS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_DECOMPRESSOR));
|
16
28
|
}
|
data/ext/brs_ext/buffer.h
CHANGED
@@ -12,6 +12,18 @@
|
|
12
12
|
#define BRS_DEFAULT_SOURCE_BUFFER_LENGTH_FOR_DECOMPRESSOR (1 << 16) // 64 KB
|
13
13
|
#define BRS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_DECOMPRESSOR (1 << 18) // 256 KB
|
14
14
|
|
15
|
+
VALUE brs_ext_create_string_buffer(VALUE length);
|
16
|
+
|
17
|
+
#define BRS_EXT_CREATE_STRING_BUFFER(buffer, length, exception) \
|
18
|
+
VALUE buffer = rb_protect(brs_ext_create_string_buffer, SIZET2NUM(length), &exception);
|
19
|
+
|
20
|
+
VALUE brs_ext_resize_string_buffer(VALUE args);
|
21
|
+
|
22
|
+
#define BRS_EXT_RESIZE_STRING_BUFFER(buffer, length, exception) \
|
23
|
+
VALUE args = rb_ary_new_from_args(2, buffer, SIZET2NUM(length)); \
|
24
|
+
buffer = rb_protect(brs_ext_resize_string_buffer, args, &exception); \
|
25
|
+
RB_GC_GUARD(args);
|
26
|
+
|
15
27
|
void brs_ext_buffer_exports(VALUE root_module);
|
16
28
|
|
17
29
|
#endif // BRS_EXT_BUFFER_H
|
data/ext/brs_ext/common.h
CHANGED
data/ext/brs_ext/error.c
CHANGED
@@ -5,7 +5,6 @@
|
|
5
5
|
|
6
6
|
#include <brotli/decode.h>
|
7
7
|
|
8
|
-
#include "brs_ext/common.h"
|
9
8
|
#include "ruby.h"
|
10
9
|
|
11
10
|
brs_ext_result_t brs_ext_get_decompressor_error(BrotliDecoderErrorCode error_code)
|
@@ -47,9 +46,9 @@ static inline NORETURN(void raise(const char* name, const char* description))
|
|
47
46
|
rb_raise(error, "%s", description);
|
48
47
|
}
|
49
48
|
|
50
|
-
void brs_ext_raise_error(brs_ext_result_t
|
49
|
+
void brs_ext_raise_error(brs_ext_result_t ext_result)
|
51
50
|
{
|
52
|
-
switch (
|
51
|
+
switch (ext_result) {
|
53
52
|
case BRS_EXT_ERROR_ALLOCATE_FAILED:
|
54
53
|
raise("AllocateError", "allocate error");
|
55
54
|
case BRS_EXT_ERROR_VALIDATE_FAILED:
|
data/ext/brs_ext/error.h
CHANGED
@@ -29,6 +29,6 @@ enum {
|
|
29
29
|
|
30
30
|
brs_ext_result_t brs_ext_get_decompressor_error(BrotliDecoderErrorCode error_code);
|
31
31
|
|
32
|
-
NORETURN(void brs_ext_raise_error(brs_ext_result_t
|
32
|
+
NORETURN(void brs_ext_raise_error(brs_ext_result_t ext_result));
|
33
33
|
|
34
34
|
#endif // BRS_EXT_ERROR_H
|
data/ext/brs_ext/io.c
CHANGED
@@ -5,13 +5,12 @@
|
|
5
5
|
|
6
6
|
#include <brotli/decode.h>
|
7
7
|
#include <brotli/encode.h>
|
8
|
-
#include <
|
8
|
+
#include <brotli/types.h>
|
9
9
|
#include <stdio.h>
|
10
10
|
#include <stdlib.h>
|
11
11
|
#include <string.h>
|
12
12
|
|
13
13
|
#include "brs_ext/buffer.h"
|
14
|
-
#include "brs_ext/common.h"
|
15
14
|
#include "brs_ext/error.h"
|
16
15
|
#include "brs_ext/io.h"
|
17
16
|
#include "brs_ext/macro.h"
|
@@ -25,7 +24,7 @@ enum {
|
|
25
24
|
|
26
25
|
// -- file --
|
27
26
|
|
28
|
-
static inline brs_ext_result_t read_file(FILE* source_file,
|
27
|
+
static inline brs_ext_result_t read_file(FILE* source_file, brs_ext_byte_t* source_buffer, size_t* source_length_ptr, size_t source_buffer_length)
|
29
28
|
{
|
30
29
|
size_t read_length = fread(source_buffer, 1, source_buffer_length, source_file);
|
31
30
|
if (read_length == 0 && feof(source_file)) {
|
@@ -41,7 +40,7 @@ static inline brs_ext_result_t read_file(FILE* source_file, uint8_t* source_buff
|
|
41
40
|
return 0;
|
42
41
|
}
|
43
42
|
|
44
|
-
static inline brs_ext_result_t write_file(FILE* destination_file,
|
43
|
+
static inline brs_ext_result_t write_file(FILE* destination_file, brs_ext_byte_t* destination_buffer, size_t destination_length)
|
45
44
|
{
|
46
45
|
size_t written_length = fwrite(destination_buffer, 1, destination_length, destination_file);
|
47
46
|
if (written_length != destination_length) {
|
@@ -54,15 +53,15 @@ static inline brs_ext_result_t write_file(FILE* destination_file, uint8_t* desti
|
|
54
53
|
// -- buffer --
|
55
54
|
|
56
55
|
static inline brs_ext_result_t create_buffers(
|
57
|
-
|
58
|
-
|
56
|
+
brs_ext_byte_t** source_buffer_ptr, size_t source_buffer_length,
|
57
|
+
brs_ext_byte_t** destination_buffer_ptr, size_t destination_buffer_length)
|
59
58
|
{
|
60
|
-
|
59
|
+
brs_ext_byte_t* source_buffer = malloc(source_buffer_length);
|
61
60
|
if (source_buffer == NULL) {
|
62
61
|
return BRS_EXT_ERROR_ALLOCATE_FAILED;
|
63
62
|
}
|
64
63
|
|
65
|
-
|
64
|
+
brs_ext_byte_t* destination_buffer = malloc(destination_buffer_length);
|
66
65
|
if (destination_buffer == NULL) {
|
67
66
|
free(source_buffer);
|
68
67
|
return BRS_EXT_ERROR_ALLOCATE_FAILED;
|
@@ -81,12 +80,12 @@ static inline brs_ext_result_t create_buffers(
|
|
81
80
|
// Algorithm can use same buffer again.
|
82
81
|
|
83
82
|
static inline brs_ext_result_t read_more_source(
|
84
|
-
FILE*
|
85
|
-
const
|
86
|
-
|
83
|
+
FILE* source_file,
|
84
|
+
const brs_ext_byte_t** source_ptr, size_t* source_length_ptr,
|
85
|
+
brs_ext_byte_t* source_buffer, size_t source_buffer_length)
|
87
86
|
{
|
88
|
-
const
|
89
|
-
size_t
|
87
|
+
const brs_ext_byte_t* source = *source_ptr;
|
88
|
+
size_t source_length = *source_length_ptr;
|
90
89
|
|
91
90
|
if (source != source_buffer) {
|
92
91
|
if (source_length != 0) {
|
@@ -103,8 +102,8 @@ static inline brs_ext_result_t read_more_source(
|
|
103
102
|
return BRS_EXT_ERROR_NOT_ENOUGH_SOURCE_BUFFER;
|
104
103
|
}
|
105
104
|
|
106
|
-
|
107
|
-
size_t
|
105
|
+
brs_ext_byte_t* remaining_source_buffer = source_buffer + source_length;
|
106
|
+
size_t new_source_length;
|
108
107
|
|
109
108
|
brs_ext_result_t ext_result = read_file(source_file, remaining_source_buffer, &new_source_length, remaining_source_buffer_length);
|
110
109
|
if (ext_result != 0) {
|
@@ -116,37 +115,51 @@ static inline brs_ext_result_t read_more_source(
|
|
116
115
|
return 0;
|
117
116
|
}
|
118
117
|
|
119
|
-
#define BUFFERED_READ_SOURCE(function, ...)
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
}
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
118
|
+
#define BUFFERED_READ_SOURCE(function, ...) \
|
119
|
+
do { \
|
120
|
+
bool is_function_called = false; \
|
121
|
+
\
|
122
|
+
while (true) { \
|
123
|
+
ext_result = read_more_source( \
|
124
|
+
source_file, \
|
125
|
+
&source, &source_length, \
|
126
|
+
source_buffer, source_buffer_length); \
|
127
|
+
\
|
128
|
+
if (ext_result == BRS_EXT_FILE_READ_FINISHED) { \
|
129
|
+
if (source_length != 0) { \
|
130
|
+
/* Brotli won't provide any remainder by design. */ \
|
131
|
+
return BRS_EXT_ERROR_READ_IO; \
|
132
|
+
} \
|
133
|
+
break; \
|
134
|
+
} \
|
135
|
+
else if (ext_result != 0) { \
|
136
|
+
return ext_result; \
|
137
|
+
} \
|
138
|
+
\
|
139
|
+
ext_result = function(__VA_ARGS__); \
|
140
|
+
if (ext_result != 0) { \
|
141
|
+
return ext_result; \
|
142
|
+
} \
|
143
|
+
\
|
144
|
+
is_function_called = true; \
|
145
|
+
} \
|
146
|
+
\
|
147
|
+
if (!is_function_called) { \
|
148
|
+
/* Function should be called at least once. */ \
|
149
|
+
ext_result = function(__VA_ARGS__); \
|
150
|
+
if (ext_result != 0) { \
|
151
|
+
return ext_result; \
|
152
|
+
} \
|
153
|
+
} \
|
154
|
+
} while (false);
|
142
155
|
|
143
156
|
// Algorithm has written data into destination buffer.
|
144
157
|
// We need to write this data into file.
|
145
158
|
// Than algorithm can use same buffer again.
|
146
159
|
|
147
160
|
static inline brs_ext_result_t flush_destination_buffer(
|
148
|
-
FILE*
|
149
|
-
|
161
|
+
FILE* destination_file,
|
162
|
+
brs_ext_byte_t* destination_buffer, size_t* destination_length_ptr, size_t destination_buffer_length)
|
150
163
|
{
|
151
164
|
if (*destination_length_ptr == 0) {
|
152
165
|
// We want to write more data at once, than buffer has.
|
@@ -163,7 +176,7 @@ static inline brs_ext_result_t flush_destination_buffer(
|
|
163
176
|
return 0;
|
164
177
|
}
|
165
178
|
|
166
|
-
static inline brs_ext_result_t write_remaining_destination(FILE* destination_file,
|
179
|
+
static inline brs_ext_result_t write_remaining_destination(FILE* destination_file, brs_ext_byte_t* destination_buffer, size_t destination_length)
|
167
180
|
{
|
168
181
|
if (destination_length == 0) {
|
169
182
|
return 0;
|
@@ -188,18 +201,19 @@ static inline brs_ext_result_t write_remaining_destination(FILE* destination_fil
|
|
188
201
|
// -- compress --
|
189
202
|
|
190
203
|
static inline brs_ext_result_t buffered_compress(
|
191
|
-
BrotliEncoderState*
|
192
|
-
const
|
193
|
-
FILE* destination_file,
|
204
|
+
BrotliEncoderState* state_ptr,
|
205
|
+
const brs_ext_byte_t** source_ptr, size_t* source_length_ptr,
|
206
|
+
FILE* destination_file, brs_ext_byte_t* destination_buffer, size_t* destination_length_ptr, size_t destination_buffer_length)
|
194
207
|
{
|
208
|
+
BROTLI_BOOL result;
|
195
209
|
brs_ext_result_t ext_result;
|
196
210
|
|
197
211
|
while (true) {
|
198
|
-
|
199
|
-
size_t
|
200
|
-
size_t
|
212
|
+
brs_ext_byte_t* remaining_destination_buffer = destination_buffer + *destination_length_ptr;
|
213
|
+
size_t remaining_destination_buffer_length = destination_buffer_length - *destination_length_ptr;
|
214
|
+
size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length;
|
201
215
|
|
202
|
-
|
216
|
+
result = BrotliEncoderCompressStream(
|
203
217
|
state_ptr,
|
204
218
|
BROTLI_OPERATION_PROCESS,
|
205
219
|
source_length_ptr, source_ptr,
|
@@ -232,19 +246,20 @@ static inline brs_ext_result_t buffered_compress(
|
|
232
246
|
|
233
247
|
static inline brs_ext_result_t buffered_compressor_finish(
|
234
248
|
BrotliEncoderState* state_ptr,
|
235
|
-
FILE* destination_file,
|
249
|
+
FILE* destination_file, brs_ext_byte_t* destination_buffer, size_t* destination_length_ptr, size_t destination_buffer_length)
|
236
250
|
{
|
251
|
+
BROTLI_BOOL result;
|
237
252
|
brs_ext_result_t ext_result;
|
238
253
|
|
239
|
-
const
|
240
|
-
size_t
|
254
|
+
const brs_ext_byte_t* source = NULL;
|
255
|
+
size_t source_length = 0;
|
241
256
|
|
242
257
|
while (true) {
|
243
|
-
|
244
|
-
size_t
|
245
|
-
size_t
|
258
|
+
brs_ext_byte_t* remaining_destination_buffer = destination_buffer + *destination_length_ptr;
|
259
|
+
size_t remaining_destination_buffer_length = destination_buffer_length - *destination_length_ptr;
|
260
|
+
size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length;
|
246
261
|
|
247
|
-
|
262
|
+
result = BrotliEncoderCompressStream(
|
248
263
|
state_ptr,
|
249
264
|
BROTLI_OPERATION_FINISH,
|
250
265
|
&source_length, &source,
|
@@ -277,14 +292,14 @@ static inline brs_ext_result_t buffered_compressor_finish(
|
|
277
292
|
|
278
293
|
static inline brs_ext_result_t compress(
|
279
294
|
BrotliEncoderState* state_ptr,
|
280
|
-
FILE* source_file,
|
281
|
-
FILE* destination_file,
|
295
|
+
FILE* source_file, brs_ext_byte_t* source_buffer, size_t source_buffer_length,
|
296
|
+
FILE* destination_file, brs_ext_byte_t* destination_buffer, size_t destination_buffer_length)
|
282
297
|
{
|
283
298
|
brs_ext_result_t ext_result;
|
284
299
|
|
285
|
-
const
|
286
|
-
size_t
|
287
|
-
size_t
|
300
|
+
const brs_ext_byte_t* source = source_buffer;
|
301
|
+
size_t source_length = 0;
|
302
|
+
size_t destination_length = 0;
|
288
303
|
|
289
304
|
BUFFERED_READ_SOURCE(
|
290
305
|
buffered_compress,
|
@@ -330,8 +345,8 @@ VALUE brs_ext_compress_io(VALUE BRS_EXT_UNUSED(self), VALUE source, VALUE destin
|
|
330
345
|
destination_buffer_length = BRS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_COMPRESSOR;
|
331
346
|
}
|
332
347
|
|
333
|
-
|
334
|
-
|
348
|
+
brs_ext_byte_t* source_buffer;
|
349
|
+
brs_ext_byte_t* destination_buffer;
|
335
350
|
|
336
351
|
ext_result = create_buffers(
|
337
352
|
&source_buffer, source_buffer_length,
|
@@ -364,18 +379,19 @@ VALUE brs_ext_compress_io(VALUE BRS_EXT_UNUSED(self), VALUE source, VALUE destin
|
|
364
379
|
// -- decompress --
|
365
380
|
|
366
381
|
static inline brs_ext_result_t buffered_decompress(
|
367
|
-
BrotliDecoderState*
|
368
|
-
const
|
369
|
-
FILE* destination_file,
|
382
|
+
BrotliDecoderState* state_ptr,
|
383
|
+
const brs_ext_byte_t** source_ptr, size_t* source_length_ptr,
|
384
|
+
FILE* destination_file, brs_ext_byte_t* destination_buffer, size_t* destination_length_ptr, size_t destination_buffer_length)
|
370
385
|
{
|
371
|
-
|
386
|
+
BrotliDecoderResult result;
|
387
|
+
brs_ext_result_t ext_result;
|
372
388
|
|
373
389
|
while (true) {
|
374
|
-
|
375
|
-
size_t
|
376
|
-
size_t
|
390
|
+
brs_ext_byte_t* remaining_destination_buffer = destination_buffer + *destination_length_ptr;
|
391
|
+
size_t remaining_destination_buffer_length = destination_buffer_length - *destination_length_ptr;
|
392
|
+
size_t prev_remaining_destination_buffer_length = remaining_destination_buffer_length;
|
377
393
|
|
378
|
-
|
394
|
+
result = BrotliDecoderDecompressStream(
|
379
395
|
state_ptr,
|
380
396
|
source_length_ptr, source_ptr,
|
381
397
|
&remaining_destination_buffer_length, &remaining_destination_buffer,
|
@@ -411,14 +427,14 @@ static inline brs_ext_result_t buffered_decompress(
|
|
411
427
|
|
412
428
|
static inline brs_ext_result_t decompress(
|
413
429
|
BrotliDecoderState* state_ptr,
|
414
|
-
FILE* source_file,
|
415
|
-
FILE* destination_file,
|
430
|
+
FILE* source_file, brs_ext_byte_t* source_buffer, size_t source_buffer_length,
|
431
|
+
FILE* destination_file, brs_ext_byte_t* destination_buffer, size_t destination_buffer_length)
|
416
432
|
{
|
417
433
|
brs_ext_result_t ext_result;
|
418
434
|
|
419
|
-
const
|
420
|
-
size_t
|
421
|
-
size_t
|
435
|
+
const brs_ext_byte_t* source = source_buffer;
|
436
|
+
size_t source_length = 0;
|
437
|
+
size_t destination_length = 0;
|
422
438
|
|
423
439
|
BUFFERED_READ_SOURCE(
|
424
440
|
buffered_decompress,
|
@@ -456,8 +472,8 @@ VALUE brs_ext_decompress_io(VALUE BRS_EXT_UNUSED(self), VALUE source, VALUE dest
|
|
456
472
|
destination_buffer_length = BRS_DEFAULT_DESTINATION_BUFFER_LENGTH_FOR_DECOMPRESSOR;
|
457
473
|
}
|
458
474
|
|
459
|
-
|
460
|
-
|
475
|
+
brs_ext_byte_t* source_buffer;
|
476
|
+
brs_ext_byte_t* destination_buffer;
|
461
477
|
|
462
478
|
ext_result = create_buffers(
|
463
479
|
&source_buffer, source_buffer_length,
|