msgpack 1.3.3 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yaml +57 -0
  3. data/.rubocop.yml +2 -2
  4. data/ChangeLog +74 -0
  5. data/Gemfile +1 -1
  6. data/README.md +266 -0
  7. data/Rakefile +1 -9
  8. data/bench/bench.rb +78 -0
  9. data/bin/console +8 -0
  10. data/doclib/msgpack/factory.rb +47 -3
  11. data/doclib/msgpack/packer.rb +5 -4
  12. data/doclib/msgpack/unpacker.rb +2 -2
  13. data/ext/java/org/msgpack/jruby/Buffer.java +23 -16
  14. data/ext/java/org/msgpack/jruby/Decoder.java +46 -23
  15. data/ext/java/org/msgpack/jruby/Encoder.java +68 -30
  16. data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +37 -49
  17. data/ext/java/org/msgpack/jruby/ExtensionValue.java +5 -8
  18. data/ext/java/org/msgpack/jruby/Factory.java +47 -7
  19. data/ext/java/org/msgpack/jruby/Packer.java +29 -17
  20. data/ext/java/org/msgpack/jruby/Unpacker.java +72 -37
  21. data/ext/msgpack/buffer.c +42 -68
  22. data/ext/msgpack/buffer.h +59 -14
  23. data/ext/msgpack/buffer_class.c +90 -52
  24. data/ext/msgpack/compat.h +1 -111
  25. data/ext/msgpack/extconf.rb +45 -19
  26. data/ext/msgpack/factory_class.c +133 -43
  27. data/ext/msgpack/packer.c +60 -36
  28. data/ext/msgpack/packer.h +27 -25
  29. data/ext/msgpack/packer_class.c +84 -77
  30. data/ext/msgpack/packer_class.h +11 -0
  31. data/ext/msgpack/packer_ext_registry.c +24 -32
  32. data/ext/msgpack/packer_ext_registry.h +40 -33
  33. data/ext/msgpack/sysdep.h +5 -2
  34. data/ext/msgpack/unpacker.c +132 -115
  35. data/ext/msgpack/unpacker.h +23 -10
  36. data/ext/msgpack/unpacker_class.c +83 -78
  37. data/ext/msgpack/unpacker_class.h +11 -0
  38. data/ext/msgpack/unpacker_ext_registry.c +42 -18
  39. data/ext/msgpack/unpacker_ext_registry.h +23 -16
  40. data/lib/msgpack/bigint.rb +69 -0
  41. data/lib/msgpack/factory.rb +103 -0
  42. data/lib/msgpack/symbol.rb +21 -4
  43. data/lib/msgpack/time.rb +1 -1
  44. data/lib/msgpack/version.rb +4 -8
  45. data/lib/msgpack.rb +6 -12
  46. data/msgpack.gemspec +4 -6
  47. data/spec/bigint_spec.rb +26 -0
  48. data/spec/cruby/buffer_spec.rb +17 -0
  49. data/spec/factory_spec.rb +351 -12
  50. data/spec/msgpack_spec.rb +1 -1
  51. data/spec/packer_spec.rb +18 -0
  52. data/spec/spec_helper.rb +37 -3
  53. data/spec/timestamp_spec.rb +38 -0
  54. data/spec/unpacker_spec.rb +157 -4
  55. metadata +31 -61
  56. data/.travis.yml +0 -43
  57. data/README.rdoc +0 -225
  58. data/bench/pack.rb +0 -23
  59. data/bench/pack_log.rb +0 -33
  60. data/bench/pack_log_long.rb +0 -65
  61. data/bench/pack_symbols.rb +0 -28
  62. data/bench/run.sh +0 -14
  63. data/bench/run_long.sh +0 -35
  64. data/bench/run_symbols.sh +0 -26
  65. data/bench/unpack.rb +0 -21
  66. data/bench/unpack_log.rb +0 -34
  67. data/bench/unpack_log_long.rb +0 -67
@@ -33,35 +33,58 @@ static VALUE eUnexpectedTypeError;
33
33
  static VALUE eUnknownExtTypeError;
34
34
  static VALUE mTypeError; // obsoleted. only for backward compatibility. See #86.
35
35
 
36
- #define UNPACKER(from, name) \
37
- msgpack_unpacker_t *name = NULL; \
38
- Data_Get_Struct(from, msgpack_unpacker_t, name); \
39
- if(name == NULL) { \
40
- rb_raise(rb_eArgError, "NULL found for " # name " when shouldn't be."); \
41
- }
36
+ static VALUE sym_symbolize_keys;
37
+ static VALUE sym_freeze;
38
+ static VALUE sym_allow_unknown_ext;
42
39
 
43
- static void Unpacker_free(msgpack_unpacker_t* uk)
40
+ static void Unpacker_free(void *ptr)
44
41
  {
42
+ msgpack_unpacker_t* uk = ptr;
45
43
  if(uk == NULL) {
46
44
  return;
47
45
  }
48
- msgpack_unpacker_ext_registry_destroy(&uk->ext_registry);
46
+ msgpack_unpacker_ext_registry_release(uk->ext_registry);
49
47
  _msgpack_unpacker_destroy(uk);
50
48
  xfree(uk);
51
49
  }
52
50
 
53
- static void Unpacker_mark(msgpack_unpacker_t* uk)
51
+ static void Unpacker_mark(void *ptr)
54
52
  {
53
+ msgpack_unpacker_t* uk = ptr;
55
54
  msgpack_unpacker_mark(uk);
56
- msgpack_unpacker_ext_registry_mark(&uk->ext_registry);
55
+ msgpack_unpacker_ext_registry_mark(uk->ext_registry);
56
+ }
57
+
58
+ static size_t Unpacker_memsize(const void *ptr)
59
+ {
60
+ size_t total_size = sizeof(msgpack_unpacker_t);
61
+
62
+ const msgpack_unpacker_t* uk = ptr;
63
+ if (uk->ext_registry) {
64
+ total_size += sizeof(msgpack_unpacker_ext_registry_t) / (uk->ext_registry->borrow_count + 1);
65
+ }
66
+
67
+ total_size += (uk->stack->depth + 1) * sizeof(msgpack_unpacker_stack_t);
68
+
69
+ return total_size + msgpack_buffer_memsize(&uk->buffer);
57
70
  }
58
71
 
72
+ const rb_data_type_t unpacker_data_type = {
73
+ .wrap_struct_name = "msgpack:unpacker",
74
+ .function = {
75
+ .dmark = Unpacker_mark,
76
+ .dfree = Unpacker_free,
77
+ .dsize = Unpacker_memsize,
78
+ },
79
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
80
+ };
81
+
59
82
  VALUE MessagePack_Unpacker_alloc(VALUE klass)
60
83
  {
61
- msgpack_unpacker_t* uk = ZALLOC_N(msgpack_unpacker_t, 1);
84
+ msgpack_unpacker_t* uk;
85
+ VALUE self = TypedData_Make_Struct(klass, msgpack_unpacker_t, &unpacker_data_type, uk);
62
86
  _msgpack_unpacker_init(uk);
63
-
64
- VALUE self = Data_Wrap_Struct(klass, Unpacker_mark, Unpacker_free, uk);
87
+ uk->self = self;
65
88
  return self;
66
89
  }
67
90
 
@@ -84,7 +107,7 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
84
107
  } else if(argc == 2) {
85
108
  io = argv[0];
86
109
  options = argv[1];
87
- if(rb_type(options) != T_HASH) {
110
+ if(options != Qnil && rb_type(options) != T_HASH) {
88
111
  rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
89
112
  }
90
113
 
@@ -92,9 +115,8 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
92
115
  rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..2)", argc);
93
116
  }
94
117
 
95
- UNPACKER(self, uk);
118
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
96
119
 
97
- msgpack_unpacker_ext_registry_init(&uk->ext_registry);
98
120
  uk->buffer_ref = MessagePack_Buffer_wrap(UNPACKER_BUFFER_(uk), self);
99
121
 
100
122
  MessagePack_Buffer_set_options(UNPACKER_BUFFER_(uk), io, options);
@@ -102,10 +124,13 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
102
124
  if(options != Qnil) {
103
125
  VALUE v;
104
126
 
105
- v = rb_hash_aref(options, ID2SYM(rb_intern("symbolize_keys")));
127
+ v = rb_hash_aref(options, sym_symbolize_keys);
106
128
  msgpack_unpacker_set_symbolized_keys(uk, RTEST(v));
107
129
 
108
- v = rb_hash_aref(options, ID2SYM(rb_intern("allow_unknown_ext")));
130
+ v = rb_hash_aref(options, sym_freeze);
131
+ msgpack_unpacker_set_freeze(uk, RTEST(v));
132
+
133
+ v = rb_hash_aref(options, sym_allow_unknown_ext);
109
134
  msgpack_unpacker_set_allow_unknown_ext(uk, RTEST(v));
110
135
  }
111
136
 
@@ -114,17 +139,23 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
114
139
 
115
140
  static VALUE Unpacker_symbolized_keys_p(VALUE self)
116
141
  {
117
- UNPACKER(self, uk);
142
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
118
143
  return uk->symbolize_keys ? Qtrue : Qfalse;
119
144
  }
120
145
 
146
+ static VALUE Unpacker_freeze_p(VALUE self)
147
+ {
148
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
149
+ return uk->freeze ? Qtrue : Qfalse;
150
+ }
151
+
121
152
  static VALUE Unpacker_allow_unknown_ext_p(VALUE self)
122
153
  {
123
- UNPACKER(self, uk);
154
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
124
155
  return uk->allow_unknown_ext ? Qtrue : Qfalse;
125
156
  }
126
157
 
127
- static void raise_unpacker_error(int r)
158
+ NORETURN(static void raise_unpacker_error(int r))
128
159
  {
129
160
  switch(r) {
130
161
  case PRIMITIVE_EOF:
@@ -136,6 +167,7 @@ static void raise_unpacker_error(int r)
136
167
  case PRIMITIVE_UNEXPECTED_TYPE:
137
168
  rb_raise(eUnexpectedTypeError, "unexpected type");
138
169
  case PRIMITIVE_UNEXPECTED_EXT_TYPE:
170
+ // rb_bug("unexpected extension type");
139
171
  rb_raise(eUnknownExtTypeError, "unexpected extension type");
140
172
  default:
141
173
  rb_raise(eUnpackError, "logically unknown error %d", r);
@@ -144,13 +176,13 @@ static void raise_unpacker_error(int r)
144
176
 
145
177
  static VALUE Unpacker_buffer(VALUE self)
146
178
  {
147
- UNPACKER(self, uk);
179
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
148
180
  return uk->buffer_ref;
149
181
  }
150
182
 
151
183
  static VALUE Unpacker_read(VALUE self)
152
184
  {
153
- UNPACKER(self, uk);
185
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
154
186
 
155
187
  int r = msgpack_unpacker_read(uk, 0);
156
188
  if(r < 0) {
@@ -162,7 +194,7 @@ static VALUE Unpacker_read(VALUE self)
162
194
 
163
195
  static VALUE Unpacker_skip(VALUE self)
164
196
  {
165
- UNPACKER(self, uk);
197
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
166
198
 
167
199
  int r = msgpack_unpacker_skip(uk, 0);
168
200
  if(r < 0) {
@@ -174,7 +206,7 @@ static VALUE Unpacker_skip(VALUE self)
174
206
 
175
207
  static VALUE Unpacker_skip_nil(VALUE self)
176
208
  {
177
- UNPACKER(self, uk);
209
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
178
210
 
179
211
  int r = msgpack_unpacker_skip_nil(uk);
180
212
  if(r < 0) {
@@ -189,7 +221,7 @@ static VALUE Unpacker_skip_nil(VALUE self)
189
221
 
190
222
  static VALUE Unpacker_read_array_header(VALUE self)
191
223
  {
192
- UNPACKER(self, uk);
224
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
193
225
 
194
226
  uint32_t size;
195
227
  int r = msgpack_unpacker_read_array_header(uk, &size);
@@ -197,12 +229,12 @@ static VALUE Unpacker_read_array_header(VALUE self)
197
229
  raise_unpacker_error(r);
198
230
  }
199
231
 
200
- return ULONG2NUM(size);
232
+ return ULONG2NUM(size); // long at least 32 bits
201
233
  }
202
234
 
203
235
  static VALUE Unpacker_read_map_header(VALUE self)
204
236
  {
205
- UNPACKER(self, uk);
237
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
206
238
 
207
239
  uint32_t size;
208
240
  int r = msgpack_unpacker_read_map_header(uk, &size);
@@ -210,41 +242,13 @@ static VALUE Unpacker_read_map_header(VALUE self)
210
242
  raise_unpacker_error((int)r);
211
243
  }
212
244
 
213
- return ULONG2NUM(size);
245
+ return ULONG2NUM(size); // long at least 32 bits
214
246
  }
215
247
 
216
- static VALUE Unpacker_peek_next_type(VALUE self)
217
- {
218
- UNPACKER(self, uk);
219
-
220
- int r = msgpack_unpacker_peek_next_object_type(uk);
221
- if(r < 0) {
222
- raise_unpacker_error(r);
223
- }
224
-
225
- switch((enum msgpack_unpacker_object_type) r) {
226
- case TYPE_NIL:
227
- return rb_intern("nil");
228
- case TYPE_BOOLEAN:
229
- return rb_intern("boolean");
230
- case TYPE_INTEGER:
231
- return rb_intern("integer");
232
- case TYPE_FLOAT:
233
- return rb_intern("float");
234
- case TYPE_RAW:
235
- return rb_intern("raw");
236
- case TYPE_ARRAY:
237
- return rb_intern("array");
238
- case TYPE_MAP:
239
- return rb_intern("map");
240
- default:
241
- rb_raise(eUnpackError, "logically unknown type %d", r);
242
- }
243
- }
244
248
 
245
249
  static VALUE Unpacker_feed(VALUE self, VALUE data)
246
250
  {
247
- UNPACKER(self, uk);
251
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
248
252
 
249
253
  StringValue(data);
250
254
 
@@ -255,7 +259,7 @@ static VALUE Unpacker_feed(VALUE self, VALUE data)
255
259
 
256
260
  static VALUE Unpacker_feed_reference(VALUE self, VALUE data)
257
261
  {
258
- UNPACKER(self, uk);
262
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
259
263
 
260
264
  StringValue(data);
261
265
 
@@ -266,7 +270,7 @@ static VALUE Unpacker_feed_reference(VALUE self, VALUE data)
266
270
 
267
271
  static VALUE Unpacker_each_impl(VALUE self)
268
272
  {
269
- UNPACKER(self, uk);
273
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
270
274
 
271
275
  while(true) {
272
276
  int r = msgpack_unpacker_read(uk, 0);
@@ -287,15 +291,16 @@ static VALUE Unpacker_each_impl(VALUE self)
287
291
  }
288
292
  }
289
293
 
290
- static VALUE Unpacker_rescue_EOFError(VALUE self)
294
+ static VALUE Unpacker_rescue_EOFError(VALUE args, VALUE error)
291
295
  {
292
- UNUSED(self);
296
+ UNUSED(args);
297
+ UNUSED(error);
293
298
  return Qnil;
294
299
  }
295
300
 
296
301
  static VALUE Unpacker_each(VALUE self)
297
302
  {
298
- UNPACKER(self, uk);
303
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
299
304
 
300
305
  #ifdef RETURN_ENUMERATOR
301
306
  RETURN_ENUMERATOR(self, 0, 0);
@@ -326,7 +331,7 @@ static VALUE Unpacker_feed_each(VALUE self, VALUE data)
326
331
 
327
332
  static VALUE Unpacker_reset(VALUE self)
328
333
  {
329
- UNPACKER(self, uk);
334
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
330
335
 
331
336
  _msgpack_unpacker_reset(uk);
332
337
 
@@ -335,12 +340,14 @@ static VALUE Unpacker_reset(VALUE self)
335
340
 
336
341
  static VALUE Unpacker_registered_types_internal(VALUE self)
337
342
  {
338
- UNPACKER(self, uk);
343
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
339
344
 
340
345
  VALUE mapping = rb_hash_new();
341
- for(int i=0; i < 256; i++) {
342
- if(uk->ext_registry.array[i] != Qnil) {
343
- rb_hash_aset(mapping, INT2FIX(i - 128), uk->ext_registry.array[i]);
346
+ if (uk->ext_registry) {
347
+ for(int i=0; i < 256; i++) {
348
+ if(uk->ext_registry->array[i] != Qnil) {
349
+ rb_hash_aset(mapping, INT2FIX(i - 128), uk->ext_registry->array[i]);
350
+ }
344
351
  }
345
352
  }
346
353
 
@@ -349,7 +356,7 @@ static VALUE Unpacker_registered_types_internal(VALUE self)
349
356
 
350
357
  static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
351
358
  {
352
- UNPACKER(self, uk);
359
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
353
360
 
354
361
  int ext_type;
355
362
  VALUE proc;
@@ -360,12 +367,7 @@ static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
360
367
  case 1:
361
368
  /* register_type(0x7f) {|data| block... } */
362
369
  rb_need_block();
363
- #ifdef HAVE_RB_BLOCK_LAMBDA
364
370
  proc = rb_block_lambda();
365
- #else
366
- /* MRI 1.8 */
367
- proc = rb_block_proc();
368
- #endif
369
371
  arg = proc;
370
372
  ext_module = Qnil;
371
373
  break;
@@ -384,14 +386,14 @@ static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
384
386
  rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
385
387
  }
386
388
 
387
- msgpack_unpacker_ext_registry_put(&uk->ext_registry, ext_module, ext_type, proc, arg);
389
+ msgpack_unpacker_ext_registry_put(&uk->ext_registry, ext_module, ext_type, 0, proc, arg);
388
390
 
389
391
  return Qnil;
390
392
  }
391
393
 
392
394
  static VALUE Unpacker_full_unpack(VALUE self)
393
395
  {
394
- UNPACKER(self, uk);
396
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
395
397
 
396
398
  int r = msgpack_unpacker_read(uk, 0);
397
399
  if(r < 0) {
@@ -434,10 +436,15 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
434
436
 
435
437
  eUnknownExtTypeError = rb_define_class_under(mMessagePack, "UnknownExtTypeError", eUnpackError);
436
438
 
439
+ sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
440
+ sym_freeze = ID2SYM(rb_intern("freeze"));
441
+ sym_allow_unknown_ext = ID2SYM(rb_intern("allow_unknown_ext"));
442
+
437
443
  rb_define_alloc_func(cMessagePack_Unpacker, MessagePack_Unpacker_alloc);
438
444
 
439
445
  rb_define_method(cMessagePack_Unpacker, "initialize", MessagePack_Unpacker_initialize, -1);
440
446
  rb_define_method(cMessagePack_Unpacker, "symbolize_keys?", Unpacker_symbolized_keys_p, 0);
447
+ rb_define_method(cMessagePack_Unpacker, "freeze?", Unpacker_freeze_p, 0);
441
448
  rb_define_method(cMessagePack_Unpacker, "allow_unknown_ext?", Unpacker_allow_unknown_ext_p, 0);
442
449
  rb_define_method(cMessagePack_Unpacker, "buffer", Unpacker_buffer, 0);
443
450
  rb_define_method(cMessagePack_Unpacker, "read", Unpacker_read, 0);
@@ -446,7 +453,6 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
446
453
  rb_define_method(cMessagePack_Unpacker, "skip_nil", Unpacker_skip_nil, 0);
447
454
  rb_define_method(cMessagePack_Unpacker, "read_array_header", Unpacker_read_array_header, 0);
448
455
  rb_define_method(cMessagePack_Unpacker, "read_map_header", Unpacker_read_map_header, 0);
449
- //rb_define_method(cMessagePack_Unpacker, "peek_next_type", Unpacker_peek_next_type, 0); // TODO
450
456
  rb_define_method(cMessagePack_Unpacker, "feed", Unpacker_feed, 1);
451
457
  rb_define_method(cMessagePack_Unpacker, "feed_reference", Unpacker_feed_reference, 1);
452
458
  rb_define_method(cMessagePack_Unpacker, "each", Unpacker_each, 0);
@@ -464,4 +470,3 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
464
470
 
465
471
  rb_define_method(cMessagePack_Unpacker, "full_unpack", Unpacker_full_unpack, 0);
466
472
  }
467
-
@@ -20,6 +20,17 @@
20
20
 
21
21
  #include "unpacker.h"
22
22
 
23
+ extern const rb_data_type_t unpacker_data_type;
24
+
25
+ static inline msgpack_unpacker_t *MessagePack_Unpacker_get(VALUE object) {
26
+ msgpack_unpacker_t *unpacker;
27
+ TypedData_Get_Struct(object, msgpack_unpacker_t, &unpacker_data_type, unpacker);
28
+ if (!unpacker) {
29
+ rb_raise(rb_eArgError, "Uninitialized Unpacker object");
30
+ }
31
+ return unpacker;
32
+ }
33
+
23
34
  extern VALUE cMessagePack_Unpacker;
24
35
 
25
36
  void MessagePack_Unpacker_module_init(VALUE mMessagePack);
@@ -21,42 +21,66 @@
21
21
  static ID s_call;
22
22
  static ID s_dup;
23
23
 
24
- void msgpack_unpacker_ext_registry_static_init()
24
+ void msgpack_unpacker_ext_registry_static_init(void)
25
25
  {
26
26
  s_call = rb_intern("call");
27
27
  s_dup = rb_intern("dup");
28
28
  }
29
29
 
30
- void msgpack_unpacker_ext_registry_static_destroy()
30
+
31
+ void msgpack_unpacker_ext_registry_static_destroy(void)
31
32
  { }
32
33
 
33
- void msgpack_unpacker_ext_registry_init(msgpack_unpacker_ext_registry_t* ukrg)
34
+ void msgpack_unpacker_ext_registry_mark(msgpack_unpacker_ext_registry_t* ukrg)
34
35
  {
35
- for(int i=0; i < 256; i++) {
36
- ukrg->array[i] = Qnil;
36
+ if (ukrg) {
37
+ for(int i=0; i < 256; i++) {
38
+ if (ukrg->array[i] != Qnil) {
39
+ rb_gc_mark(ukrg->array[i]);
40
+ }
41
+ }
37
42
  }
38
43
  }
39
44
 
40
- void msgpack_unpacker_ext_registry_mark(msgpack_unpacker_ext_registry_t* ukrg)
45
+ msgpack_unpacker_ext_registry_t* msgpack_unpacker_ext_registry_cow(msgpack_unpacker_ext_registry_t* src)
41
46
  {
42
- for(int i=0; i < 256; i++) {
43
- rb_gc_mark(ukrg->array[i]);
47
+ msgpack_unpacker_ext_registry_t* dst;
48
+ if (src) {
49
+ if (src->borrow_count) {
50
+ dst = ALLOC(msgpack_unpacker_ext_registry_t);
51
+ dst->borrow_count = 0;
52
+ MEMCPY(dst->array, src->array, VALUE, 256);
53
+ msgpack_unpacker_ext_registry_release(src);
54
+ return dst;
55
+ } else {
56
+ return src;
57
+ }
58
+ } else {
59
+ dst = ALLOC(msgpack_unpacker_ext_registry_t);
60
+ dst->borrow_count = 0;
61
+ for(int i=0; i < 256; i++) {
62
+ dst->array[i] = Qnil;
63
+ }
64
+ return dst;
44
65
  }
45
66
  }
46
67
 
47
- void msgpack_unpacker_ext_registry_dup(msgpack_unpacker_ext_registry_t* src,
48
- msgpack_unpacker_ext_registry_t* dst)
68
+ void msgpack_unpacker_ext_registry_release(msgpack_unpacker_ext_registry_t* ukrg)
49
69
  {
50
- for(int i=0; i < 256; i++) {
51
- dst->array[i] = src->array[i];
70
+ if (ukrg) {
71
+ if (ukrg->borrow_count) {
72
+ ukrg->borrow_count--;
73
+ } else {
74
+ xfree(ukrg);
75
+ }
52
76
  }
53
77
  }
54
78
 
55
- VALUE msgpack_unpacker_ext_registry_put(msgpack_unpacker_ext_registry_t* ukrg,
56
- VALUE ext_module, int ext_type, VALUE proc, VALUE arg)
79
+ void msgpack_unpacker_ext_registry_put(msgpack_unpacker_ext_registry_t** ukrg,
80
+ VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg)
57
81
  {
58
- VALUE e = rb_ary_new3(3, ext_module, proc, arg);
59
- VALUE before = ukrg->array[ext_type + 128];
60
- ukrg->array[ext_type + 128] = e;
61
- return before;
82
+ msgpack_unpacker_ext_registry_t* ext_registry = msgpack_unpacker_ext_registry_cow(*ukrg);
83
+
84
+ ext_registry->array[ext_type + 128] = rb_ary_new3(4, ext_module, proc, arg, INT2FIX(flags));
85
+ *ukrg = ext_registry;
62
86
  }
@@ -21,39 +21,46 @@
21
21
  #include "compat.h"
22
22
  #include "ruby.h"
23
23
 
24
+ #define MSGPACK_EXT_RECURSIVE 0b0001
25
+
24
26
  struct msgpack_unpacker_ext_registry_t;
25
27
  typedef struct msgpack_unpacker_ext_registry_t msgpack_unpacker_ext_registry_t;
26
28
 
27
29
  struct msgpack_unpacker_ext_registry_t {
30
+ unsigned int borrow_count;
28
31
  VALUE array[256];
29
- //int bitmap;
30
32
  };
31
33
 
32
- void msgpack_unpacker_ext_registry_static_init();
34
+ void msgpack_unpacker_ext_registry_static_init(void);
33
35
 
34
- void msgpack_unpacker_ext_registry_static_destroy();
36
+ void msgpack_unpacker_ext_registry_static_destroy(void);
35
37
 
36
- void msgpack_unpacker_ext_registry_init(msgpack_unpacker_ext_registry_t* ukrg);
38
+ void msgpack_unpacker_ext_registry_release(msgpack_unpacker_ext_registry_t* ukrg);
37
39
 
38
- static inline void msgpack_unpacker_ext_registry_destroy(msgpack_unpacker_ext_registry_t* ukrg)
39
- { }
40
+ static inline void msgpack_unpacker_ext_registry_borrow(msgpack_unpacker_ext_registry_t* src, msgpack_unpacker_ext_registry_t** dst)
41
+ {
42
+ if (src) {
43
+ src->borrow_count++;
44
+ *dst = src;
45
+ }
46
+ }
40
47
 
41
48
  void msgpack_unpacker_ext_registry_mark(msgpack_unpacker_ext_registry_t* ukrg);
42
49
 
43
- void msgpack_unpacker_ext_registry_dup(msgpack_unpacker_ext_registry_t* src,
44
- msgpack_unpacker_ext_registry_t* dst);
45
-
46
- VALUE msgpack_unpacker_ext_registry_put(msgpack_unpacker_ext_registry_t* ukrg,
47
- VALUE ext_module, int ext_type, VALUE proc, VALUE arg);
50
+ void msgpack_unpacker_ext_registry_put(msgpack_unpacker_ext_registry_t** ukrg,
51
+ VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg);
48
52
 
49
53
  static inline VALUE msgpack_unpacker_ext_registry_lookup(msgpack_unpacker_ext_registry_t* ukrg,
50
- int ext_type)
54
+ int ext_type, int* ext_flags_result)
51
55
  {
52
- VALUE e = ukrg->array[ext_type + 128];
53
- if(e == Qnil) {
54
- return Qnil;
56
+ if (ukrg) {
57
+ VALUE entry = ukrg->array[ext_type + 128];
58
+ if (entry != Qnil) {
59
+ *ext_flags_result = FIX2INT(rb_ary_entry(entry, 3));
60
+ return rb_ary_entry(entry, 1);
61
+ }
55
62
  }
56
- return rb_ary_entry(e, 1);
63
+ return Qnil;
57
64
  }
58
65
 
59
66
  #endif
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MessagePack
4
+ module Bigint
5
+ # We split the bigint in 32bits chunks so that individual part fits into
6
+ # a MRI immediate Integer.
7
+ CHUNK_BITLENGTH = 32
8
+ FORMAT = 'CL>*'
9
+
10
+ if Integer.instance_method(:[]).arity != 1 # Ruby 2.7 and newer
11
+ # Starting from Ruby 2.7 we can address arbitrary bitranges inside an Integer with Integer#[]
12
+ # This allows to not allocate any Integer.
13
+ def self.to_msgpack_ext(bigint)
14
+ members = []
15
+
16
+ if bigint < 0
17
+ bigint = -bigint
18
+ members << 1
19
+ else
20
+ members << 0
21
+ end
22
+
23
+ offset = 0
24
+ length = bigint.bit_length
25
+ while offset < length
26
+ members << bigint[offset, CHUNK_BITLENGTH]
27
+ offset += CHUNK_BITLENGTH
28
+ end
29
+
30
+ members.pack(FORMAT)
31
+ end
32
+ else
33
+ # On 2.6 and older since we can't address arbitrary bitranges, so we fallback to shifting the bigint.
34
+ # This means that after each shift, we may allocate another Integer instance.
35
+ BASE = (2**CHUNK_BITLENGTH) - 1
36
+ def self.to_msgpack_ext(bigint)
37
+ members = []
38
+
39
+ if bigint < 0
40
+ bigint = -bigint
41
+ members << 1
42
+ else
43
+ members << 0
44
+ end
45
+
46
+ while bigint > 0
47
+ members << (bigint & BASE)
48
+ bigint = bigint >> CHUNK_BITLENGTH
49
+ end
50
+
51
+ members.pack(FORMAT)
52
+ end
53
+ end
54
+
55
+ def self.from_msgpack_ext(data)
56
+ parts = data.unpack(FORMAT)
57
+
58
+ sign = parts.shift
59
+ sum = parts.pop.to_i
60
+
61
+ parts.reverse_each do |part|
62
+ sum = sum << CHUNK_BITLENGTH
63
+ sum += part
64
+ end
65
+
66
+ sign == 0 ? sum : -sum
67
+ end
68
+ end
69
+ end