ruby-brs 1.0.1 → 1.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
| [![Travis test status](https://travis-ci.com/andrew-aladev/ruby-brs.svg?branch=master)](https://travis-ci.com/andrew-aladev/ruby-brs) | [![AppVeyor test status](https://ci.appveyor.com/api/projects/status/github/andrew-aladev/ruby-brs?branch=master&svg=true)](https://ci.appveyor.com/project/andrew-aladev/ruby-brs/branch/master) | [![Circle test status](https://circleci.com/gh/andrew-aladev/ruby-brs/tree/master.svg?style=shield)](https://circleci.com/gh/andrew-aladev/ruby-brs/tree/master) | [![Codecov](https://codecov.io/gh/andrew-aladev/ruby-brs/branch/master/graph/badge.svg)](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,
|