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