msgpack 1.4.2 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yaml +57 -0
  3. data/ChangeLog +60 -0
  4. data/README.md +25 -1
  5. data/Rakefile +1 -2
  6. data/bench/bench.rb +78 -0
  7. data/bin/console +8 -0
  8. data/doclib/msgpack/factory.rb +47 -3
  9. data/doclib/msgpack/packer.rb +5 -4
  10. data/doclib/msgpack/unpacker.rb +2 -2
  11. data/ext/java/org/msgpack/jruby/Buffer.java +23 -16
  12. data/ext/java/org/msgpack/jruby/Decoder.java +29 -21
  13. data/ext/java/org/msgpack/jruby/Encoder.java +68 -30
  14. data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +37 -49
  15. data/ext/java/org/msgpack/jruby/ExtensionValue.java +5 -8
  16. data/ext/java/org/msgpack/jruby/Factory.java +47 -7
  17. data/ext/java/org/msgpack/jruby/Packer.java +29 -17
  18. data/ext/java/org/msgpack/jruby/Unpacker.java +66 -42
  19. data/ext/msgpack/buffer.c +38 -57
  20. data/ext/msgpack/buffer.h +19 -10
  21. data/ext/msgpack/buffer_class.c +90 -52
  22. data/ext/msgpack/compat.h +0 -99
  23. data/ext/msgpack/extconf.rb +9 -22
  24. data/ext/msgpack/factory_class.c +133 -43
  25. data/ext/msgpack/packer.c +60 -36
  26. data/ext/msgpack/packer.h +27 -18
  27. data/ext/msgpack/packer_class.c +84 -77
  28. data/ext/msgpack/packer_class.h +11 -0
  29. data/ext/msgpack/packer_ext_registry.c +24 -32
  30. data/ext/msgpack/packer_ext_registry.h +40 -33
  31. data/ext/msgpack/sysdep.h +5 -2
  32. data/ext/msgpack/unpacker.c +128 -97
  33. data/ext/msgpack/unpacker.h +17 -10
  34. data/ext/msgpack/unpacker_class.c +75 -80
  35. data/ext/msgpack/unpacker_class.h +11 -0
  36. data/ext/msgpack/unpacker_ext_registry.c +42 -18
  37. data/ext/msgpack/unpacker_ext_registry.h +23 -16
  38. data/lib/msgpack/bigint.rb +69 -0
  39. data/lib/msgpack/factory.rb +103 -0
  40. data/lib/msgpack/symbol.rb +21 -4
  41. data/lib/msgpack/time.rb +1 -1
  42. data/lib/msgpack/version.rb +1 -1
  43. data/lib/msgpack.rb +5 -7
  44. data/msgpack.gemspec +2 -2
  45. data/spec/bigint_spec.rb +26 -0
  46. data/spec/cruby/buffer_spec.rb +17 -0
  47. data/spec/factory_spec.rb +351 -12
  48. data/spec/msgpack_spec.rb +1 -1
  49. data/spec/packer_spec.rb +18 -0
  50. data/spec/spec_helper.rb +20 -3
  51. data/spec/timestamp_spec.rb +38 -0
  52. data/spec/unpacker_spec.rb +54 -4
  53. metadata +25 -41
  54. data/.travis.yml +0 -39
  55. data/bench/pack.rb +0 -23
  56. data/bench/pack_log.rb +0 -33
  57. data/bench/pack_log_long.rb +0 -65
  58. data/bench/pack_symbols.rb +0 -28
  59. data/bench/run.sh +0 -14
  60. data/bench/run_long.sh +0 -35
  61. data/bench/run_symbols.sh +0 -26
  62. data/bench/unpack.rb +0 -21
  63. data/bench/unpack_log.rb +0 -34
  64. 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,13 +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("freeze")));
130
+ v = rb_hash_aref(options, sym_freeze);
109
131
  msgpack_unpacker_set_freeze(uk, RTEST(v));
110
132
 
111
- v = rb_hash_aref(options, ID2SYM(rb_intern("allow_unknown_ext")));
133
+ v = rb_hash_aref(options, sym_allow_unknown_ext);
112
134
  msgpack_unpacker_set_allow_unknown_ext(uk, RTEST(v));
113
135
  }
114
136
 
@@ -117,23 +139,23 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
117
139
 
118
140
  static VALUE Unpacker_symbolized_keys_p(VALUE self)
119
141
  {
120
- UNPACKER(self, uk);
142
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
121
143
  return uk->symbolize_keys ? Qtrue : Qfalse;
122
144
  }
123
145
 
124
146
  static VALUE Unpacker_freeze_p(VALUE self)
125
147
  {
126
- UNPACKER(self, uk);
148
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
127
149
  return uk->freeze ? Qtrue : Qfalse;
128
150
  }
129
151
 
130
152
  static VALUE Unpacker_allow_unknown_ext_p(VALUE self)
131
153
  {
132
- UNPACKER(self, uk);
154
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
133
155
  return uk->allow_unknown_ext ? Qtrue : Qfalse;
134
156
  }
135
157
 
136
- static void raise_unpacker_error(int r)
158
+ NORETURN(static void raise_unpacker_error(int r))
137
159
  {
138
160
  switch(r) {
139
161
  case PRIMITIVE_EOF:
@@ -145,6 +167,7 @@ static void raise_unpacker_error(int r)
145
167
  case PRIMITIVE_UNEXPECTED_TYPE:
146
168
  rb_raise(eUnexpectedTypeError, "unexpected type");
147
169
  case PRIMITIVE_UNEXPECTED_EXT_TYPE:
170
+ // rb_bug("unexpected extension type");
148
171
  rb_raise(eUnknownExtTypeError, "unexpected extension type");
149
172
  default:
150
173
  rb_raise(eUnpackError, "logically unknown error %d", r);
@@ -153,13 +176,13 @@ static void raise_unpacker_error(int r)
153
176
 
154
177
  static VALUE Unpacker_buffer(VALUE self)
155
178
  {
156
- UNPACKER(self, uk);
179
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
157
180
  return uk->buffer_ref;
158
181
  }
159
182
 
160
183
  static VALUE Unpacker_read(VALUE self)
161
184
  {
162
- UNPACKER(self, uk);
185
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
163
186
 
164
187
  int r = msgpack_unpacker_read(uk, 0);
165
188
  if(r < 0) {
@@ -171,7 +194,7 @@ static VALUE Unpacker_read(VALUE self)
171
194
 
172
195
  static VALUE Unpacker_skip(VALUE self)
173
196
  {
174
- UNPACKER(self, uk);
197
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
175
198
 
176
199
  int r = msgpack_unpacker_skip(uk, 0);
177
200
  if(r < 0) {
@@ -183,7 +206,7 @@ static VALUE Unpacker_skip(VALUE self)
183
206
 
184
207
  static VALUE Unpacker_skip_nil(VALUE self)
185
208
  {
186
- UNPACKER(self, uk);
209
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
187
210
 
188
211
  int r = msgpack_unpacker_skip_nil(uk);
189
212
  if(r < 0) {
@@ -198,7 +221,7 @@ static VALUE Unpacker_skip_nil(VALUE self)
198
221
 
199
222
  static VALUE Unpacker_read_array_header(VALUE self)
200
223
  {
201
- UNPACKER(self, uk);
224
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
202
225
 
203
226
  uint32_t size;
204
227
  int r = msgpack_unpacker_read_array_header(uk, &size);
@@ -206,12 +229,12 @@ static VALUE Unpacker_read_array_header(VALUE self)
206
229
  raise_unpacker_error(r);
207
230
  }
208
231
 
209
- return ULONG2NUM(size);
232
+ return ULONG2NUM(size); // long at least 32 bits
210
233
  }
211
234
 
212
235
  static VALUE Unpacker_read_map_header(VALUE self)
213
236
  {
214
- UNPACKER(self, uk);
237
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
215
238
 
216
239
  uint32_t size;
217
240
  int r = msgpack_unpacker_read_map_header(uk, &size);
@@ -219,41 +242,13 @@ static VALUE Unpacker_read_map_header(VALUE self)
219
242
  raise_unpacker_error((int)r);
220
243
  }
221
244
 
222
- return ULONG2NUM(size);
245
+ return ULONG2NUM(size); // long at least 32 bits
223
246
  }
224
247
 
225
- static VALUE Unpacker_peek_next_type(VALUE self)
226
- {
227
- UNPACKER(self, uk);
228
-
229
- int r = msgpack_unpacker_peek_next_object_type(uk);
230
- if(r < 0) {
231
- raise_unpacker_error(r);
232
- }
233
-
234
- switch((enum msgpack_unpacker_object_type) r) {
235
- case TYPE_NIL:
236
- return rb_intern("nil");
237
- case TYPE_BOOLEAN:
238
- return rb_intern("boolean");
239
- case TYPE_INTEGER:
240
- return rb_intern("integer");
241
- case TYPE_FLOAT:
242
- return rb_intern("float");
243
- case TYPE_RAW:
244
- return rb_intern("raw");
245
- case TYPE_ARRAY:
246
- return rb_intern("array");
247
- case TYPE_MAP:
248
- return rb_intern("map");
249
- default:
250
- rb_raise(eUnpackError, "logically unknown type %d", r);
251
- }
252
- }
253
248
 
254
249
  static VALUE Unpacker_feed(VALUE self, VALUE data)
255
250
  {
256
- UNPACKER(self, uk);
251
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
257
252
 
258
253
  StringValue(data);
259
254
 
@@ -264,7 +259,7 @@ static VALUE Unpacker_feed(VALUE self, VALUE data)
264
259
 
265
260
  static VALUE Unpacker_feed_reference(VALUE self, VALUE data)
266
261
  {
267
- UNPACKER(self, uk);
262
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
268
263
 
269
264
  StringValue(data);
270
265
 
@@ -275,7 +270,7 @@ static VALUE Unpacker_feed_reference(VALUE self, VALUE data)
275
270
 
276
271
  static VALUE Unpacker_each_impl(VALUE self)
277
272
  {
278
- UNPACKER(self, uk);
273
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
279
274
 
280
275
  while(true) {
281
276
  int r = msgpack_unpacker_read(uk, 0);
@@ -296,15 +291,16 @@ static VALUE Unpacker_each_impl(VALUE self)
296
291
  }
297
292
  }
298
293
 
299
- static VALUE Unpacker_rescue_EOFError(VALUE self)
294
+ static VALUE Unpacker_rescue_EOFError(VALUE args, VALUE error)
300
295
  {
301
- UNUSED(self);
296
+ UNUSED(args);
297
+ UNUSED(error);
302
298
  return Qnil;
303
299
  }
304
300
 
305
301
  static VALUE Unpacker_each(VALUE self)
306
302
  {
307
- UNPACKER(self, uk);
303
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
308
304
 
309
305
  #ifdef RETURN_ENUMERATOR
310
306
  RETURN_ENUMERATOR(self, 0, 0);
@@ -335,7 +331,7 @@ static VALUE Unpacker_feed_each(VALUE self, VALUE data)
335
331
 
336
332
  static VALUE Unpacker_reset(VALUE self)
337
333
  {
338
- UNPACKER(self, uk);
334
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
339
335
 
340
336
  _msgpack_unpacker_reset(uk);
341
337
 
@@ -344,12 +340,14 @@ static VALUE Unpacker_reset(VALUE self)
344
340
 
345
341
  static VALUE Unpacker_registered_types_internal(VALUE self)
346
342
  {
347
- UNPACKER(self, uk);
343
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
348
344
 
349
345
  VALUE mapping = rb_hash_new();
350
- for(int i=0; i < 256; i++) {
351
- if(uk->ext_registry.array[i] != Qnil) {
352
- 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
+ }
353
351
  }
354
352
  }
355
353
 
@@ -358,7 +356,7 @@ static VALUE Unpacker_registered_types_internal(VALUE self)
358
356
 
359
357
  static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
360
358
  {
361
- UNPACKER(self, uk);
359
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
362
360
 
363
361
  int ext_type;
364
362
  VALUE proc;
@@ -369,12 +367,7 @@ static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
369
367
  case 1:
370
368
  /* register_type(0x7f) {|data| block... } */
371
369
  rb_need_block();
372
- #ifdef HAVE_RB_BLOCK_LAMBDA
373
370
  proc = rb_block_lambda();
374
- #else
375
- /* MRI 1.8 */
376
- proc = rb_block_proc();
377
- #endif
378
371
  arg = proc;
379
372
  ext_module = Qnil;
380
373
  break;
@@ -393,14 +386,14 @@ static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
393
386
  rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
394
387
  }
395
388
 
396
- 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);
397
390
 
398
391
  return Qnil;
399
392
  }
400
393
 
401
394
  static VALUE Unpacker_full_unpack(VALUE self)
402
395
  {
403
- UNPACKER(self, uk);
396
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
404
397
 
405
398
  int r = msgpack_unpacker_read(uk, 0);
406
399
  if(r < 0) {
@@ -443,6 +436,10 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
443
436
 
444
437
  eUnknownExtTypeError = rb_define_class_under(mMessagePack, "UnknownExtTypeError", eUnpackError);
445
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
+
446
443
  rb_define_alloc_func(cMessagePack_Unpacker, MessagePack_Unpacker_alloc);
447
444
 
448
445
  rb_define_method(cMessagePack_Unpacker, "initialize", MessagePack_Unpacker_initialize, -1);
@@ -456,7 +453,6 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
456
453
  rb_define_method(cMessagePack_Unpacker, "skip_nil", Unpacker_skip_nil, 0);
457
454
  rb_define_method(cMessagePack_Unpacker, "read_array_header", Unpacker_read_array_header, 0);
458
455
  rb_define_method(cMessagePack_Unpacker, "read_map_header", Unpacker_read_map_header, 0);
459
- //rb_define_method(cMessagePack_Unpacker, "peek_next_type", Unpacker_peek_next_type, 0); // TODO
460
456
  rb_define_method(cMessagePack_Unpacker, "feed", Unpacker_feed, 1);
461
457
  rb_define_method(cMessagePack_Unpacker, "feed_reference", Unpacker_feed_reference, 1);
462
458
  rb_define_method(cMessagePack_Unpacker, "each", Unpacker_each, 0);
@@ -474,4 +470,3 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
474
470
 
475
471
  rb_define_method(cMessagePack_Unpacker, "full_unpack", Unpacker_full_unpack, 0);
476
472
  }
477
-
@@ -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