brotli 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 439249d900d92fdfbdba0c607d03b1cc52be123ed909bf7971d6c8b89c8134de
4
- data.tar.gz: 3ae1816fee964948daedfa0835f2098efd4526def10f855f6a3fcc415ad56ce1
3
+ metadata.gz: 6e39135e3c6e289c1b4f233d8e0bec31f1cfb6be48f63280b5a7609965b88459
4
+ data.tar.gz: 5f0bae9eb2e35baf822e7eff9e8432e24043893afe29c70506050d41c073bbaa
5
5
  SHA512:
6
- metadata.gz: 330cc7d4176f2ede18d615c7c51862131182c5e3826d164b3cced606a490924d44ef349ab746677e8f62f547a87601ddc65c5f95197a7cc43f53e87f1a7f448d
7
- data.tar.gz: 711194c375cd78bba734cb5ae4b89270ddcbaa8a457e3e45b055a6334a0a684d1f7351780c868a965c804cab306796949f5e915a60bbeb95f332b6900fea68a6
6
+ metadata.gz: 46ae27522c3cb015279531a8d6b91af3afcd40a0b61c552db76e7caa9562a547f8f4e2f09873f5e113314cbc0ffe811fcfdc9a0c02b84aa2df4ade1d005857e9
7
+ data.tar.gz: cc393196d928f8d761b83bf7f04415c7f1ddd1b2f113008063e9b99615004adf00af95171932d009efeeb0e6ad2f5edb3c26196610475b08a4e5db0d56e5e201
data/ext/brotli/brotli.c CHANGED
@@ -101,13 +101,11 @@ brotli_inflate_no_gvl(void *arg)
101
101
  buffer_t* buffer = args->buffer;
102
102
  BrotliDecoderState* s = args->s;
103
103
 
104
- #ifdef HAVE_BROTLIDECODERATTACHDICTIONARY
105
104
  /* Attach dictionary if provided */
106
105
  if (args->dict && args->dict_len > 0) {
107
106
  BrotliDecoderAttachDictionary(s, BROTLI_SHARED_DICTIONARY_RAW,
108
107
  args->dict_len, args->dict);
109
108
  }
110
- #endif
111
109
 
112
110
  for (;;) {
113
111
  r = BrotliDecoderDecompressStream(s,
@@ -133,6 +131,13 @@ brotli_inflate_no_gvl(void *arg)
133
131
  return arg;
134
132
  }
135
133
 
134
+ static VALUE
135
+ brotli_inflate_take_result(VALUE arg)
136
+ {
137
+ brotli_inflate_args_t *args = (brotli_inflate_args_t *)arg;
138
+ return rb_str_new(args->buffer->ptr, args->buffer->used);
139
+ }
140
+
136
141
  static VALUE
137
142
  brotli_inflate(int argc, VALUE *argv, VALUE self)
138
143
  {
@@ -141,7 +146,7 @@ brotli_inflate(int argc, VALUE *argv, VALUE self)
141
146
  VALUE value = Qnil;
142
147
  VALUE dict = Qnil;
143
148
  const char *error = NULL;
144
- brotli_inflate_args_t args;
149
+ brotli_inflate_args_t args = {0};
145
150
 
146
151
  (void)self;
147
152
 
@@ -153,6 +158,9 @@ brotli_inflate(int argc, VALUE *argv, VALUE self)
153
158
 
154
159
  StringValue(str);
155
160
  dict = brotli_hash_lookup(opts, id_dictionary);
161
+ if (!NIL_P(dict)) {
162
+ StringValue(dict);
163
+ }
156
164
 
157
165
  args.str = (uint8_t*)RSTRING_PTR(str);
158
166
  args.len = (size_t)RSTRING_LEN(str);
@@ -161,28 +169,24 @@ brotli_inflate(int argc, VALUE *argv, VALUE self)
161
169
  args.r = BROTLI_DECODER_RESULT_ERROR;
162
170
 
163
171
  if (!NIL_P(dict)) {
164
- #ifdef HAVE_BROTLIDECODERATTACHDICTIONARY
165
- StringValue(dict);
166
172
  args.dict = (uint8_t*)RSTRING_PTR(dict);
167
173
  args.dict_len = (size_t)RSTRING_LEN(dict);
168
- #else
169
- rb_raise(rb_eBrotli, "Dictionary support not available in this build");
170
- #endif
171
174
  } else {
172
175
  args.dict = NULL;
173
176
  args.dict_len = 0;
174
177
  }
175
178
 
176
- #ifdef HAVE_RUBY_THREAD_H
177
179
  rb_thread_call_without_gvl(brotli_inflate_no_gvl, &args, NULL, NULL);
178
- #else
179
- brotli_inflate_no_gvl(&args);
180
- #endif
181
180
  RB_GC_GUARD(str);
182
181
  RB_GC_GUARD(dict);
183
182
 
184
183
  if (args.r == BROTLI_DECODER_RESULT_SUCCESS) {
185
- value = rb_str_new(args.buffer->ptr, args.buffer->used);
184
+ int state = 0;
185
+ value = rb_protect(brotli_inflate_take_result, (VALUE)&args, &state);
186
+ if (state) {
187
+ brotli_inflate_cleanup(&args);
188
+ rb_jump_tag(state);
189
+ }
186
190
  } else if (args.r == BROTLI_DECODER_RESULT_ERROR) {
187
191
  error = BrotliDecoderErrorString(BrotliDecoderGetErrorCode(args.s));
188
192
  } else if (args.r == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) {
@@ -204,11 +208,11 @@ brotli_inflate(int argc, VALUE *argv, VALUE self)
204
208
  * deflate
205
209
  ******************************************************************************/
206
210
 
207
- static void
211
+ static const char *
208
212
  brotli_deflate_set_mode(BrotliEncoderState* s, VALUE value)
209
213
  {
210
214
  if (NIL_P(value)) {
211
- return;
215
+ return NULL;
212
216
  }
213
217
 
214
218
  if (value == ID2SYM(id_generic)) {
@@ -218,68 +222,99 @@ brotli_deflate_set_mode(BrotliEncoderState* s, VALUE value)
218
222
  } else if (value == ID2SYM(id_font)) {
219
223
  BrotliEncoderSetParameter(s, BROTLI_PARAM_MODE, BROTLI_MODE_FONT);
220
224
  } else {
221
- rb_raise(rb_eArgError, "invalid mode");
225
+ return "invalid mode";
222
226
  }
227
+
228
+ return NULL;
223
229
  }
224
230
 
225
- static void
231
+ static const char *
226
232
  brotli_deflate_set_quality(BrotliEncoderState* s, VALUE value)
227
233
  {
228
- int32_t param;
234
+ long param;
229
235
 
230
236
  if (NIL_P(value)) {
231
- return;
237
+ return NULL;
238
+ }
239
+
240
+ if (!FIXNUM_P(value)) {
241
+ return "invalid quality value. Should be 0 to 11.";
232
242
  }
233
243
 
234
- param = NUM2INT(value);
244
+ param = FIX2LONG(value);
235
245
  if (0 <= param && param <= 11) {
236
- BrotliEncoderSetParameter(s, BROTLI_PARAM_QUALITY, param);
246
+ BrotliEncoderSetParameter(s, BROTLI_PARAM_QUALITY, (uint32_t)param);
237
247
  } else {
238
- rb_raise(rb_eArgError, "invalid quality value. Should be 0 to 11.");
248
+ return "invalid quality value. Should be 0 to 11.";
239
249
  }
250
+
251
+ return NULL;
240
252
  }
241
253
 
242
- static void
254
+ static const char *
243
255
  brotli_deflate_set_lgwin(BrotliEncoderState* s, VALUE value)
244
256
  {
245
- int32_t param;
257
+ long param;
246
258
 
247
259
  if (NIL_P(value)) {
248
- return;
260
+ return NULL;
249
261
  }
250
262
 
251
- param = NUM2INT(value);
263
+ if (!FIXNUM_P(value)) {
264
+ return "invalid lgwin value. Should be 10 to 24.";
265
+ }
266
+
267
+ param = FIX2LONG(value);
252
268
  if (10 <= param && param <= 24) {
253
- BrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, param);
269
+ BrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, (uint32_t)param);
254
270
  } else {
255
- rb_raise(rb_eArgError, "invalid lgwin value. Should be 10 to 24.");
271
+ return "invalid lgwin value. Should be 10 to 24.";
256
272
  }
273
+
274
+ return NULL;
257
275
  }
258
276
 
259
- static void
277
+ static const char *
260
278
  brotli_deflate_set_lgblock(BrotliEncoderState* s, VALUE value)
261
279
  {
262
- int32_t param;
280
+ long param;
263
281
 
264
282
  if (NIL_P(value)) {
265
- return;
283
+ return NULL;
284
+ }
285
+
286
+ if (!FIXNUM_P(value)) {
287
+ return "invalid lgblock value. Should be 0 or 16 to 24.";
266
288
  }
267
289
 
268
- param = NUM2INT(value);
290
+ param = FIX2LONG(value);
269
291
  if (param == 0 || (16 <= param && param <= 24)) {
270
- BrotliEncoderSetParameter(s, BROTLI_PARAM_LGBLOCK, param);
292
+ BrotliEncoderSetParameter(s, BROTLI_PARAM_LGBLOCK, (uint32_t)param);
271
293
  } else {
272
- rb_raise(rb_eArgError, "invalid lgblock value. Should be 0 or 16 to 24.");
294
+ return "invalid lgblock value. Should be 0 or 16 to 24.";
273
295
  }
296
+
297
+ return NULL;
274
298
  }
275
299
 
276
- static void
300
+ static const char *
277
301
  brotli_deflate_parse_options(BrotliEncoderState* s, VALUE opts)
278
302
  {
279
- brotli_deflate_set_mode(s, brotli_hash_lookup(opts, id_mode));
280
- brotli_deflate_set_quality(s, brotli_hash_lookup(opts, id_quality));
281
- brotli_deflate_set_lgwin(s, brotli_hash_lookup(opts, id_lgwin));
282
- brotli_deflate_set_lgblock(s, brotli_hash_lookup(opts, id_lgblock));
303
+ const char *err;
304
+
305
+ err = brotli_deflate_set_mode(s, brotli_hash_lookup(opts, id_mode));
306
+ if (err) {
307
+ return err;
308
+ }
309
+ err = brotli_deflate_set_quality(s, brotli_hash_lookup(opts, id_quality));
310
+ if (err) {
311
+ return err;
312
+ }
313
+ err = brotli_deflate_set_lgwin(s, brotli_hash_lookup(opts, id_lgwin));
314
+ if (err) {
315
+ return err;
316
+ }
317
+ return brotli_deflate_set_lgblock(s, brotli_hash_lookup(opts, id_lgblock));
283
318
  }
284
319
 
285
320
  typedef struct {
@@ -288,9 +323,7 @@ typedef struct {
288
323
  BrotliEncoderState* s;
289
324
  buffer_t* buffer;
290
325
  BROTLI_BOOL finished;
291
- #if defined(HAVE_BROTLIENCODERPREPAREDICTIONARY) && defined(HAVE_BROTLIENCODERATTACHPREPAREDDICTIONARY)
292
326
  BrotliEncoderPreparedDictionary* prepared_dict;
293
- #endif
294
327
  } brotli_deflate_args_t;
295
328
 
296
329
  static void
@@ -302,12 +335,10 @@ brotli_deflate_cleanup(brotli_deflate_args_t* args)
302
335
  BrotliEncoderDestroyInstance(args->s);
303
336
  args->s = NULL;
304
337
  }
305
- #if defined(HAVE_BROTLIENCODERPREPAREDICTIONARY) && defined(HAVE_BROTLIENCODERATTACHPREPAREDDICTIONARY)
306
338
  if (args->prepared_dict) {
307
339
  BrotliEncoderDestroyPreparedDictionary(args->prepared_dict);
308
340
  args->prepared_dict = NULL;
309
341
  }
310
- #endif
311
342
  }
312
343
 
313
344
  static void*
@@ -347,6 +378,13 @@ brotli_deflate_no_gvl(void *arg)
347
378
  return arg;
348
379
  }
349
380
 
381
+ static VALUE
382
+ brotli_deflate_take_result(VALUE arg)
383
+ {
384
+ brotli_deflate_args_t *args = (brotli_deflate_args_t *)arg;
385
+ return rb_str_new(args->buffer->ptr, args->buffer->used);
386
+ }
387
+
350
388
  static VALUE
351
389
  brotli_deflate(int argc, VALUE *argv, VALUE self)
352
390
  {
@@ -354,8 +392,9 @@ brotli_deflate(int argc, VALUE *argv, VALUE self)
354
392
  VALUE opts = Qnil;
355
393
  VALUE value = Qnil;
356
394
  VALUE dict = Qnil;
357
- brotli_deflate_args_t args;
395
+ brotli_deflate_args_t args = {0};
358
396
  size_t max_compressed_size;
397
+ const char *err;
359
398
 
360
399
  (void)self;
361
400
 
@@ -365,21 +404,24 @@ brotli_deflate(int argc, VALUE *argv, VALUE self)
365
404
  }
366
405
  StringValue(str);
367
406
  dict = brotli_hash_lookup(opts, id_dictionary);
407
+ if (!NIL_P(dict)) {
408
+ StringValue(dict);
409
+ }
368
410
 
369
411
  args.str = (uint8_t*)RSTRING_PTR(str);
370
412
  args.len = (size_t)RSTRING_LEN(str);
371
413
  args.s = brotli_encoder_state_create();
372
- brotli_deflate_parse_options(args.s, opts);
414
+ err = brotli_deflate_parse_options(args.s, opts);
415
+ if (err) {
416
+ brotli_deflate_cleanup(&args);
417
+ rb_raise(rb_eArgError, "%s", err);
418
+ }
373
419
  max_compressed_size = BrotliEncoderMaxCompressedSize(args.len);
374
420
  args.buffer = create_buffer(max_compressed_size);
375
421
  args.finished = BROTLI_FALSE;
376
422
 
377
- #if defined(HAVE_BROTLIENCODERPREPAREDICTIONARY) && defined(HAVE_BROTLIENCODERATTACHPREPAREDDICTIONARY)
378
423
  args.prepared_dict = NULL;
379
- #endif
380
424
  if (!NIL_P(dict)) {
381
- #if defined(HAVE_BROTLIENCODERPREPAREDICTIONARY) && defined(HAVE_BROTLIENCODERATTACHPREPAREDDICTIONARY)
382
- StringValue(dict);
383
425
  args.prepared_dict = BrotliEncoderPrepareDictionary(
384
426
  BROTLI_SHARED_DICTIONARY_RAW,
385
427
  (size_t)RSTRING_LEN(dict),
@@ -396,21 +438,18 @@ brotli_deflate(int argc, VALUE *argv, VALUE self)
396
438
  brotli_deflate_cleanup(&args);
397
439
  rb_raise(rb_eBrotli, "Failed to attach dictionary for compression");
398
440
  }
399
- #else
400
- brotli_deflate_cleanup(&args);
401
- rb_raise(rb_eBrotli, "Dictionary support not available in this build");
402
- #endif
403
441
  }
404
442
 
405
- #ifdef HAVE_RUBY_THREAD_H
406
443
  rb_thread_call_without_gvl(brotli_deflate_no_gvl, &args, NULL, NULL);
407
- #else
408
- brotli_deflate_no_gvl(&args);
409
- #endif
410
444
  RB_GC_GUARD(str);
411
445
  RB_GC_GUARD(dict);
412
446
  if (args.finished == BROTLI_TRUE) {
413
- value = rb_str_new(args.buffer->ptr, args.buffer->used);
447
+ int state = 0;
448
+ value = rb_protect(brotli_deflate_take_result, (VALUE)&args, &state);
449
+ if (state) {
450
+ brotli_deflate_cleanup(&args);
451
+ rb_jump_tag(state);
452
+ }
414
453
  }
415
454
 
416
455
  brotli_deflate_cleanup(&args);
@@ -432,7 +471,7 @@ static VALUE brotli_version(VALUE klass) {
432
471
 
433
472
  (void)klass;
434
473
  snprintf(version, sizeof(version), "%u.%u.%u", ver >> 24, (ver >> 12) & 0xFFF, ver & 0xFFF);
435
- return rb_str_new2(version);
474
+ return rb_str_new_cstr(version);
436
475
  }
437
476
 
438
477
  /*******************************************************************************
@@ -462,9 +501,7 @@ brotli_copy_string_data(VALUE string, size_t* len)
462
501
 
463
502
  typedef struct {
464
503
  BrotliEncoderState* state;
465
- #if defined(HAVE_BROTLIENCODERPREPAREDICTIONARY) && defined(HAVE_BROTLIENCODERATTACHPREPAREDDICTIONARY)
466
504
  BrotliEncoderPreparedDictionary* prepared_dict;
467
- #endif
468
505
  uint8_t* dict_data;
469
506
  size_t dict_len;
470
507
  BROTLI_BOOL finished;
@@ -523,21 +560,13 @@ static void* decompress_no_gvl(void *ptr) {
523
560
  static void
524
561
  brotli_encoder_step(brotli_encoder_args_t *args)
525
562
  {
526
- #ifdef HAVE_RUBY_THREAD_H
527
563
  rb_thread_call_without_gvl(compress_no_gvl, (void*)args, NULL, NULL);
528
- #else
529
- compress_no_gvl((void*)args);
530
- #endif
531
564
  }
532
565
 
533
566
  static void
534
567
  brotli_decompressor_step(brotli_decoder_args_t *args)
535
568
  {
536
- #ifdef HAVE_RUBY_THREAD_H
537
569
  rb_thread_call_without_gvl(decompress_no_gvl, (void*)args, NULL, NULL);
538
- #else
539
- decompress_no_gvl((void*)args);
540
- #endif
541
570
  }
542
571
 
543
572
  static void
@@ -547,12 +576,10 @@ brotli_encoder_destroy(brotli_encoder_t* encoder)
547
576
  BrotliEncoderDestroyInstance(encoder->state);
548
577
  encoder->state = NULL;
549
578
  }
550
- #if defined(HAVE_BROTLIENCODERPREPAREDICTIONARY) && defined(HAVE_BROTLIENCODERATTACHPREPAREDDICTIONARY)
551
579
  if (encoder->prepared_dict) {
552
580
  BrotliEncoderDestroyPreparedDictionary(encoder->prepared_dict);
553
581
  encoder->prepared_dict = NULL;
554
582
  }
555
- #endif
556
583
  brotli_free(NULL, encoder->dict_data);
557
584
  encoder->dict_data = NULL;
558
585
  encoder->dict_len = 0;
@@ -587,7 +614,6 @@ brotli_encoder_attach_dictionary(brotli_encoder_t* encoder, VALUE opts)
587
614
  return;
588
615
  }
589
616
 
590
- #if defined(HAVE_BROTLIENCODERPREPAREDICTIONARY) && defined(HAVE_BROTLIENCODERATTACHPREPAREDDICTIONARY)
591
617
  encoder->dict_data = brotli_copy_string_data(dict, &encoder->dict_len);
592
618
  encoder->prepared_dict = BrotliEncoderPrepareDictionary(
593
619
  BROTLI_SHARED_DICTIONARY_RAW,
@@ -613,9 +639,6 @@ brotli_encoder_attach_dictionary(brotli_encoder_t* encoder, VALUE opts)
613
639
  encoder->dict_len = 0;
614
640
  rb_raise(rb_eBrotli, "Failed to attach dictionary for compression");
615
641
  }
616
- #else
617
- rb_raise(rb_eBrotli, "Dictionary support not available in this build");
618
- #endif
619
642
  }
620
643
 
621
644
  static VALUE
@@ -684,7 +707,7 @@ brotli_compressor_memsize(const void *p)
684
707
  static const rb_data_type_t brotli_compressor_data_type = {
685
708
  "brotli_compressor",
686
709
  { 0, brotli_compressor_free, brotli_compressor_memsize },
687
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
710
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
688
711
  };
689
712
 
690
713
  static VALUE
@@ -693,9 +716,7 @@ rb_compressor_alloc(VALUE klass)
693
716
  brotli_compressor_t *br;
694
717
  VALUE obj = TypedData_Make_Struct(klass, brotli_compressor_t, &brotli_compressor_data_type, br);
695
718
  br->encoder.state = NULL;
696
- #if defined(HAVE_BROTLIENCODERPREPAREDICTIONARY) && defined(HAVE_BROTLIENCODERATTACHPREPAREDDICTIONARY)
697
719
  br->encoder.prepared_dict = NULL;
698
- #endif
699
720
  br->encoder.dict_data = NULL;
700
721
  br->encoder.dict_len = 0;
701
722
  br->encoder.finished = BROTLI_FALSE;
@@ -715,12 +736,16 @@ rb_compressor_initialize(int argc, VALUE* argv, VALUE self)
715
736
  {
716
737
  VALUE opts = Qnil;
717
738
  brotli_compressor_t *br;
739
+ const char *err;
718
740
 
719
741
  rb_scan_args(argc, argv, "01", &opts);
720
742
 
721
743
  TypedData_Get_Struct(self, brotli_compressor_t, &brotli_compressor_data_type, br);
722
744
  brotli_encoder_reset(&br->encoder);
723
- brotli_deflate_parse_options(br->encoder.state, opts);
745
+ err = brotli_deflate_parse_options(br->encoder.state, opts);
746
+ if (err) {
747
+ rb_raise(rb_eArgError, "%s", err);
748
+ }
724
749
  brotli_encoder_attach_dictionary(&br->encoder, opts);
725
750
 
726
751
  return self;
@@ -896,7 +921,6 @@ brotli_decompressor_attach_dictionary(brotli_decompressor_t* br, VALUE opts)
896
921
  return;
897
922
  }
898
923
 
899
- #ifdef HAVE_BROTLIDECODERATTACHDICTIONARY
900
924
  br->dict_data = brotli_copy_string_data(dict, &br->dict_len);
901
925
  if (!BrotliDecoderAttachDictionary(br->state,
902
926
  BROTLI_SHARED_DICTIONARY_RAW,
@@ -907,9 +931,6 @@ brotli_decompressor_attach_dictionary(brotli_decompressor_t* br, VALUE opts)
907
931
  br->dict_len = 0;
908
932
  rb_raise(rb_eBrotli, "Failed to attach dictionary for decompression");
909
933
  }
910
- #else
911
- rb_raise(rb_eBrotli, "Dictionary support not available in this build");
912
- #endif
913
934
  }
914
935
 
915
936
  static VALUE
@@ -1156,9 +1177,7 @@ rb_decompressor_unused_data(VALUE self)
1156
1177
  void
1157
1178
  Init_brotli(void)
1158
1179
  {
1159
- #if HAVE_RB_EXT_RACTOR_SAFE
1160
1180
  rb_ext_ractor_safe(true);
1161
- #endif
1162
1181
 
1163
1182
  VALUE rb_mBrotli;
1164
1183
  rb_mBrotli = rb_define_module("Brotli");
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 */
@@ -1,60 +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
- dir_config("brotli")
6
- have_func("rb_gc_mark_movable")
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__)
7
12
 
8
- # libbrotli-dev
9
- have_dev_pkg = [
10
- have_header("brotli/decode.h"),
11
- have_header("brotli/encode.h"),
12
- pkg_config("libbrotlicommon"),
13
- pkg_config("libbrotlidec"),
14
- pkg_config("libbrotlienc")
15
- ].all? { |e| e }
16
-
17
- have_header("brotli/shared_dictionary.h")
18
- have_func("BrotliEncoderPrepareDictionary", "brotli/encode.h")
19
- have_func("BrotliEncoderAttachPreparedDictionary", "brotli/encode.h")
20
- have_func("BrotliDecoderAttachDictionary", "brotli/decode.h")
21
-
22
- if enable_config("vendor")
23
- have_dev_pkg = false
24
- Logging::message "Use vendor brotli\n"
25
- $defs << "-DHAVE_BROTLI_SHARED_DICTIONARY_H"
26
- $defs << "-DHAVE_BROTLIENCODERPREPAREDICTIONARY"
27
- $defs << "-DHAVE_BROTLIENCODERATTACHPREPAREDDICTIONARY"
28
- $defs << "-DHAVE_BROTLIDECODERATTACHDICTIONARY"
13
+ def generated_vendored_dirs
14
+ VENDORED_DIRS.map { |dirname| File.join(BUILD_DIR, dirname) }
29
15
  end
30
16
 
31
- $CPPFLAGS << " -DOS_MACOSX" if RbConfig::CONFIG["host_os"] =~ /darwin|mac os/
32
- $INCFLAGS << " -I$(srcdir)/enc -I$(srcdir)/dec -I$(srcdir)/common -I$(srcdir)/include" unless have_dev_pkg
17
+ def remove_generated_vendored_dirs
18
+ generated_vendored_dirs.each { |path| FileUtils.rm_rf(path) }
19
+ end
33
20
 
34
- create_makefile("brotli/brotli")
21
+ def copy_vendored_sources
22
+ sources = Dir[File.join(VENDORED_SOURCE_DIR, "{common,dec,enc,include}", "**", "*.{c,h}")].sort
35
23
 
36
- unless have_dev_pkg
37
- ext_dir = __dir__
38
- vendor_dir = File.expand_path("../../vendor/brotli/c", __dir__)
39
- objext = RbConfig::CONFIG["OBJEXT"]
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
28
+
29
+ sources.each do |source|
30
+ relative_path = source.delete_prefix("#{VENDORED_SOURCE_DIR}/")
31
+ destination = File.join(BUILD_DIR, relative_path)
40
32
 
41
- %w[enc dec common include].each do |dirname|
42
- FileUtils.rm_rf dirname
43
- FileUtils.mkdir_p dirname
44
- FileUtils.cp_r(File.join(vendor_dir, dirname), ext_dir)
33
+ FileUtils.mkdir_p(File.dirname(destination))
34
+ FileUtils.cp(source, destination)
45
35
  end
36
+ end
46
37
 
47
- srcs = []
48
- objs = []
49
- Dir[File.expand_path(File.join("{enc,dec,common,include}", "**", "*.c"), ext_dir)].sort.each do |file|
50
- file["#{ext_dir}#{File::SEPARATOR}"] = ""
51
- srcs << file
52
- objs << file.sub(/\.c\z/, ".#{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}/")
53
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}") }
54
48
 
55
49
  makefile = File.read("Makefile")
56
50
  makefile = makefile
57
- .sub(/^ORIG_SRCS = .*$/, "ORIG_SRCS = brotli.c buffer.c #{srcs.join(" ")}")
58
- .sub(/^OBJS = .*$/, "OBJS = brotli.#{objext} buffer.#{objext} #{objs.join(" ")}")
51
+ .sub(/^ORIG_SRCS = .*$/, "ORIG_SRCS = brotli.c buffer.c #{source_files.join(" ")}")
52
+ .sub(/^OBJS = .*$/, "OBJS = brotli.#{objext} buffer.#{objext} #{object_files.join(" ")}")
59
53
  File.write("Makefile", makefile)
60
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
79
+
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
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"
128
+ end
129
+
130
+ create_makefile("brotli/brotli")
131
+ add_vendored_sources_to_makefile if use_vendored_brotli
@@ -1,3 +1,3 @@
1
1
  module Brotli
2
- VERSION = '0.8.0'
2
+ VERSION = '0.9.0'
3
3
  end