msgpack 1.7.1 → 1.7.3

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: c2caf680ff4cafade89a14da270f52528ba2a862cea237ad028ba27fa6a93e9b
4
- data.tar.gz: 01d8cc906d925acbd32a88c22f6ace7f5534a0b447be1736ea58cfdf9abb85b6
3
+ metadata.gz: fe6adcd787be2f8c3e9459d46c3baa4ad81c5b08bdcaeb9bfec9a80c9a4540c6
4
+ data.tar.gz: 76d6be5a37a2b6e225ad995e6b0f670d0489839a98b678c9332837bd082e7d7e
5
5
  SHA512:
6
- metadata.gz: 48fcd12bfb13741d88a17e1a261cd742c903ba53cb1959a88b7083c2344817d90cfa898e775c136d785fbfcdd76be14b6dc5fc8ba3638a13ecabbb2d1387dbee
7
- data.tar.gz: 310f3ea573cf41b15c47bc0033121496bd8ab7a723ef3667a96a38bc286feb79536ac5aeb8d27c3c71568149f93c8f36cc9ca8e050595e27ff87762cbccfe2dd
6
+ metadata.gz: 36b0e748e7b54baad2ecef8c1c071a82cf3e6bd26540fd433a3c71f1e77afe341188594a26bfed817f84af10ef4f613ded14fc0a8448a77dc4978683cf7c35d1
7
+ data.tar.gz: 45ce3770a12b3580945ba3dd42d40ab8ba24a167f675f71d57bb42af6cf4ab204d7cc7960925ea78556988f523886fd92b431789a174e0529143ab0908d52418
data/ChangeLog CHANGED
@@ -1,3 +1,12 @@
1
+ 2024-10-03 1.7.3
2
+
3
+ * Limit initial containers pre-allocation to `SHRT_MAX` (32k) entries.
4
+
5
+ 2023-07-18 1.7.2:
6
+
7
+ * Fix a potential GC bug when packing data using recursive extensions and buffers containing over 512KkiB of data (See #341).
8
+ * Fix a regression where feeding an empty string to an Unpacker would be considered like the end of the buffer.
9
+
1
10
  2023-05-19 1.7.1:
2
11
 
3
12
  * Fix JRuby 9.4 compatibility.
data/README.md CHANGED
@@ -8,15 +8,24 @@ and typical short strings only require an extra byte in addition to the strings
8
8
  If you ever wished to use JSON for convenience (storing an image with metadata) but could
9
9
  not for technical reasons (binary data, size, speed...), MessagePack is a perfect replacement.
10
10
 
11
- require 'msgpack'
12
- msg = [1,2,3].to_msgpack #=> "\x93\x01\x02\x03"
13
- MessagePack.unpack(msg) #=> [1,2,3]
11
+ ```ruby
12
+ require 'msgpack'
13
+ msg = [1,2,3].to_msgpack #=> "\x93\x01\x02\x03"
14
+ MessagePack.unpack(msg) #=> [1,2,3]
15
+ ```
16
+
17
+ Add msgpack to your Gemfile to install with Bundler:
18
+
19
+ ```ruby
20
+ # Gemfile
21
+ gem 'msgpack'
22
+ ```
14
23
 
15
- Use RubyGems to install:
24
+ Or, use RubyGems to install:
16
25
 
17
26
  gem install msgpack
18
27
 
19
- or build msgpack-ruby and install:
28
+ Or, build msgpack-ruby and install from a checked-out msgpack-ruby repository:
20
29
 
21
30
  bundle
22
31
  rake
@@ -27,11 +36,11 @@ or build msgpack-ruby and install:
27
36
 
28
37
  * Create REST API returing MessagePack using Rails + [RABL](https://github.com/nesquena/rabl)
29
38
  * Store objects efficiently serialized by msgpack on memcached or Redis
30
- * In fact Redis supports msgpack in [EVAL-scripts](http://redis.io/commands/eval)
39
+ * In fact Redis supports msgpack in [EVAL-scripts](https://redis.io/docs/latest/commands/eval/)
31
40
  * Upload data in efficient format from mobile devices such as smartphones
32
41
  * MessagePack works on iPhone/iPad and Android. See also [Objective-C](https://github.com/msgpack/msgpack-objectivec) and [Java](https://github.com/msgpack/msgpack-java) implementations
33
42
  * Design a portable protocol to communicate with embedded devices
34
- * Check also [Fluentd](http://fluentd.org/) which is a log collector which uses msgpack for the log format (they say it uses JSON but actually it's msgpack, which is compatible with JSON)
43
+ * Check also [Fluentd](https://www.fluentd.org) which is a log collector which uses msgpack for the log format (they say it uses JSON but actually it's msgpack, which is compatible with JSON)
35
44
  * Exchange objects between software components written in different languages
36
45
  * You'll need a flexible but efficient format so that components exchange objects while keeping compatibility
37
46
 
@@ -128,9 +137,9 @@ being serialized altogether by throwing an exception:
128
137
 
129
138
  ```ruby
130
139
  class Symbol
131
- def to_msgpack_ext
132
- raise "Serialization of symbols prohibited"
133
- end
140
+ def to_msgpack_ext
141
+ raise "Serialization of symbols prohibited"
142
+ end
134
143
  end
135
144
 
136
145
  MessagePack::DefaultFactory.register_type(0x00, Symbol)
@@ -276,8 +285,8 @@ If this directory has Gemfile.lock (generated with MRI), remove it beforehand.
276
285
 
277
286
  ## Updating documents
278
287
 
279
- Online documents (http://ruby.msgpack.org) is generated from gh-pages branch.
280
- Following commands update documents in gh-pages branch:
288
+ Online documentation (https://ruby.msgpack.org) is generated from the gh-pages branch.
289
+ To update documents in gh-pages branch:
281
290
 
282
291
  bundle exec rake doc
283
292
  git checkout gh-pages
@@ -54,8 +54,8 @@ public class ExtensionRegistry {
54
54
  return hash;
55
55
  }
56
56
 
57
- public void put(RubyModule mod, int typeId, boolean recursive, IRubyObject packerProc, IRubyObject packerArg, IRubyObject unpackerProc, IRubyObject unpackerArg) {
58
- ExtensionEntry entry = new ExtensionEntry(mod, typeId, recursive, packerProc, packerArg, unpackerProc, unpackerArg);
57
+ public void put(RubyModule mod, int typeId, boolean recursive, IRubyObject packerProc, IRubyObject unpackerProc) {
58
+ ExtensionEntry entry = new ExtensionEntry(mod, typeId, recursive, packerProc, unpackerProc);
59
59
  extensionsByModule.put(mod, entry);
60
60
  extensionsByTypeId[typeId + 128] = entry;
61
61
  extensionsByAncestor.clear();
@@ -114,18 +114,14 @@ public class ExtensionRegistry {
114
114
  private final int typeId;
115
115
  private final boolean recursive;
116
116
  private final IRubyObject packerProc;
117
- private final IRubyObject packerArg;
118
117
  private final IRubyObject unpackerProc;
119
- private final IRubyObject unpackerArg;
120
118
 
121
- public ExtensionEntry(RubyModule mod, int typeId, boolean recursive, IRubyObject packerProc, IRubyObject packerArg, IRubyObject unpackerProc, IRubyObject unpackerArg) {
119
+ public ExtensionEntry(RubyModule mod, int typeId, boolean recursive, IRubyObject packerProc, IRubyObject unpackerProc) {
122
120
  this.mod = mod;
123
121
  this.typeId = typeId;
124
122
  this.recursive = recursive;
125
123
  this.packerProc = packerProc;
126
- this.packerArg = packerArg;
127
124
  this.unpackerProc = unpackerProc;
128
- this.unpackerArg = unpackerArg;
129
125
  }
130
126
 
131
127
  public RubyModule getExtensionModule() {
@@ -157,11 +153,11 @@ public class ExtensionRegistry {
157
153
  }
158
154
 
159
155
  public RubyArray<?> toPackerTuple(ThreadContext ctx) {
160
- return ctx.runtime.newArray(new IRubyObject[] {ctx.runtime.newFixnum(typeId), packerProc, packerArg});
156
+ return ctx.runtime.newArray(new IRubyObject[] {ctx.runtime.newFixnum(typeId), packerProc});
161
157
  }
162
158
 
163
159
  public RubyArray<?> toUnpackerTuple(ThreadContext ctx) {
164
- return ctx.runtime.newArray(new IRubyObject[] {mod, unpackerProc, unpackerArg});
160
+ return ctx.runtime.newArray(new IRubyObject[] {mod, unpackerProc});
165
161
  }
166
162
 
167
163
  public IRubyObject[] toPackerProcTypeIdPair(ThreadContext ctx) {
@@ -80,43 +80,15 @@ public class Factory extends RubyObject {
80
80
  });
81
81
  }
82
82
 
83
- @JRubyMethod(name = "register_type", required = 2, optional = 1)
84
- public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args) {
83
+ @JRubyMethod(name = "register_type_internal", required = 3, visibility = PRIVATE)
84
+ public IRubyObject registerTypeInternal(ThreadContext ctx, IRubyObject type, IRubyObject mod, IRubyObject opts) {
85
85
  testFrozen("MessagePack::Factory");
86
86
 
87
87
  Ruby runtime = ctx.runtime;
88
- IRubyObject type = args[0];
89
- IRubyObject mod = args[1];
90
-
91
- IRubyObject packerArg;
92
- IRubyObject unpackerArg;
93
-
94
- RubyHash options = null;
95
-
96
- if (args.length == 2) {
97
- packerArg = runtime.newSymbol("to_msgpack_ext");
98
- unpackerArg = runtime.newSymbol("from_msgpack_ext");
99
- } else if (args.length == 3) {
100
- if (args[args.length - 1] instanceof RubyHash) {
101
- options = (RubyHash) args[args.length - 1];
102
- packerArg = options.fastARef(runtime.newSymbol("packer"));
103
- if (packerArg != null && packerArg.isNil()) {
104
- packerArg = null;
105
- }
106
- unpackerArg = options.fastARef(runtime.newSymbol("unpacker"));
107
- if (unpackerArg != null && unpackerArg.isNil()) {
108
- unpackerArg = null;
109
- }
110
- IRubyObject optimizedSymbolsParsingArg = options.fastARef(runtime.newSymbol("optimized_symbols_parsing"));
111
- if (optimizedSymbolsParsingArg != null && optimizedSymbolsParsingArg.isTrue()) {
112
- throw runtime.newArgumentError("JRuby implementation does not support the optimized_symbols_parsing option");
113
- }
114
- } else {
115
- throw runtime.newArgumentError(String.format("expected Hash but found %s.", args[args.length - 1].getType().getName()));
116
- }
117
- } else {
118
- throw runtime.newArgumentError(String.format("wrong number of arguments (%d for 2..3)", 2 + args.length));
119
- }
88
+ RubyHash options = (RubyHash) opts;
89
+
90
+ IRubyObject packerProc = options.fastARef(runtime.newSymbol("packer"));
91
+ IRubyObject unpackerProc = options.fastARef(runtime.newSymbol("unpacker"));
120
92
 
121
93
  long typeId = ((RubyFixnum) type).getLongValue();
122
94
  if (typeId < -128 || typeId > 127) {
@@ -128,21 +100,6 @@ public class Factory extends RubyObject {
128
100
  }
129
101
  RubyModule extModule = (RubyModule) mod;
130
102
 
131
- IRubyObject packerProc = runtime.getNil();
132
- IRubyObject unpackerProc = runtime.getNil();
133
- if (packerArg != null) {
134
- packerProc = packerArg.callMethod(ctx, "to_proc");
135
- }
136
- if (unpackerArg != null) {
137
- if (unpackerArg instanceof RubyString || unpackerArg instanceof RubySymbol) {
138
- unpackerProc = extModule.method(unpackerArg.callMethod(ctx, "to_sym"));
139
- } else if (unpackerArg instanceof RubyProc || unpackerArg instanceof RubyMethod) {
140
- unpackerProc = unpackerArg;
141
- } else {
142
- unpackerProc = unpackerArg.callMethod(ctx, "method", runtime.newSymbol("call"));
143
- }
144
- }
145
-
146
103
  boolean recursive = false;
147
104
  if (options != null) {
148
105
  IRubyObject recursiveExtensionArg = options.fastARef(runtime.newSymbol("recursive"));
@@ -151,7 +108,7 @@ public class Factory extends RubyObject {
151
108
  }
152
109
  }
153
110
 
154
- extensionRegistry.put(extModule, (int) typeId, recursive, packerProc, packerArg, unpackerProc, unpackerArg);
111
+ extensionRegistry.put(extModule, (int) typeId, recursive, packerProc, unpackerProc);
155
112
 
156
113
  if (extModule == runtime.getSymbol() && !packerProc.isNil()) {
157
114
  hasSymbolExtType = true;
@@ -93,28 +93,11 @@ public class Packer extends RubyObject {
93
93
  return registry.toInternalPackerRegistry(ctx);
94
94
  }
95
95
 
96
- @JRubyMethod(name = "register_type", required = 2, optional = 1)
97
- public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Block block) {
96
+ @JRubyMethod(name = "register_type_internal", required = 3, visibility = PRIVATE)
97
+ public IRubyObject registerType(ThreadContext ctx, IRubyObject type, IRubyObject mod, IRubyObject proc) {
98
98
  testFrozen("MessagePack::Packer");
99
99
 
100
100
  Ruby runtime = ctx.runtime;
101
- IRubyObject type = args[0];
102
- IRubyObject mod = args[1];
103
-
104
- IRubyObject arg;
105
- IRubyObject proc;
106
- if (args.length == 2) {
107
- if (! block.isGiven()) {
108
- throw runtime.newLocalJumpErrorNoBlock();
109
- }
110
- proc = block.getProcObject();
111
- arg = proc;
112
- } else if (args.length == 3) {
113
- arg = args[2];
114
- proc = arg.callMethod(ctx, "to_proc");
115
- } else {
116
- throw runtime.newArgumentError(String.format("wrong number of arguments (%d for 2..3)", 2 + args.length));
117
- }
118
101
 
119
102
  long typeId = ((RubyFixnum) type).getLongValue();
120
103
  if (typeId < -128 || typeId > 127) {
@@ -126,7 +109,7 @@ public class Packer extends RubyObject {
126
109
  }
127
110
  RubyModule extModule = (RubyModule) mod;
128
111
 
129
- registry.put(extModule, (int) typeId, false, proc, arg, null, null);
112
+ registry.put(extModule, (int) typeId, false, proc, null);
130
113
 
131
114
  if (extModule == runtime.getSymbol() && !proc.isNil()) {
132
115
  encoder.hasSymbolExtType = true;
@@ -126,39 +126,23 @@ public class Unpacker extends RubyObject {
126
126
  return registry.toInternalUnpackerRegistry(ctx);
127
127
  }
128
128
 
129
- @JRubyMethod(name = "register_type", required = 1, optional = 2)
130
- public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Block block) {
129
+ @JRubyMethod(name = "register_type_internal", required = 3, visibility = PRIVATE)
130
+ public IRubyObject registerTypeInternal(ThreadContext ctx, IRubyObject type, IRubyObject mod, IRubyObject proc) {
131
131
  testFrozen("MessagePack::Unpacker");
132
132
 
133
133
  Ruby runtime = ctx.runtime;
134
- IRubyObject type = args[0];
135
-
136
- RubyModule extModule;
137
- IRubyObject arg;
138
- IRubyObject proc;
139
- if (args.length == 1) {
140
- if (! block.isGiven()) {
141
- throw runtime.newLocalJumpErrorNoBlock();
142
- }
143
- proc = RubyProc.newProc(runtime, block, block.type);
144
- if (proc == null)
145
- System.err.println("proc from Block is null");
146
- arg = proc;
147
- extModule = null;
148
- } else if (args.length == 3) {
149
- extModule = (RubyModule) args[1];
150
- arg = args[2];
151
- proc = extModule.method(arg);
152
- } else {
153
- throw runtime.newArgumentError(String.format("wrong number of arguments (%d for 1 or 3)", 2 + args.length));
154
- }
155
134
 
156
135
  long typeId = ((RubyFixnum) type).getLongValue();
157
136
  if (typeId < -128 || typeId > 127) {
158
137
  throw runtime.newRangeError(String.format("integer %d too big to convert to `signed char'", typeId));
159
138
  }
160
139
 
161
- registry.put(extModule, (int) typeId, false, null, null, proc, arg);
140
+ RubyModule extModule = null;
141
+ if (mod != runtime.getNil()) {
142
+ extModule = (RubyModule)mod;
143
+ }
144
+
145
+ registry.put(extModule, (int) typeId, false, null, proc);
162
146
  return runtime.getNil();
163
147
  }
164
148
 
data/ext/msgpack/buffer.c CHANGED
@@ -251,12 +251,14 @@ bool _msgpack_buffer_read_all2(msgpack_buffer_t* b, char* buffer, size_t length)
251
251
 
252
252
  static inline msgpack_buffer_chunk_t* _msgpack_buffer_alloc_new_chunk(msgpack_buffer_t* b)
253
253
  {
254
- msgpack_buffer_chunk_t* reuse = b->free_list;
255
- if(reuse == NULL) {
256
- return xmalloc(sizeof(msgpack_buffer_chunk_t));
254
+ msgpack_buffer_chunk_t* chunk = b->free_list;
255
+ if (chunk) {
256
+ b->free_list = b->free_list->next;
257
+ } else {
258
+ chunk = xmalloc(sizeof(msgpack_buffer_chunk_t));
257
259
  }
258
- b->free_list = b->free_list->next;
259
- return reuse;
260
+ memset(chunk, 0, sizeof(msgpack_buffer_chunk_t));
261
+ return chunk;
260
262
  }
261
263
 
262
264
  static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
data/ext/msgpack/buffer.h CHANGED
@@ -268,7 +268,9 @@ static inline size_t msgpack_buffer_append_string(msgpack_buffer_t* b, VALUE str
268
268
  static inline size_t msgpack_buffer_append_string_reference(msgpack_buffer_t* b, VALUE string)
269
269
  {
270
270
  size_t length = RSTRING_LEN(string);
271
- _msgpack_buffer_append_long_string(b, string);
271
+ if (length > 0) {
272
+ _msgpack_buffer_append_long_string(b, string);
273
+ }
272
274
  return length;
273
275
  }
274
276
 
@@ -21,7 +21,8 @@
21
21
  #include "buffer.h"
22
22
  #include "buffer_class.h"
23
23
 
24
- VALUE cMessagePack_Buffer;
24
+ VALUE cMessagePack_Buffer = Qnil;
25
+ VALUE cMessagePack_HeldBuffer = Qnil;
25
26
 
26
27
  static ID s_read;
27
28
  static ID s_readpartial;
@@ -34,6 +35,73 @@ static VALUE sym_read_reference_threshold;
34
35
  static VALUE sym_write_reference_threshold;
35
36
  static VALUE sym_io_buffer_size;
36
37
 
38
+ typedef struct msgpack_held_buffer_t msgpack_held_buffer_t;
39
+ struct msgpack_held_buffer_t {
40
+ size_t size;
41
+ VALUE mapped_strings[];
42
+ };
43
+
44
+ static void HeldBuffer_mark(void *data)
45
+ {
46
+ msgpack_held_buffer_t* held_buffer = (msgpack_held_buffer_t*)data;
47
+ for (size_t index = 0; index < held_buffer->size; index++) {
48
+ rb_gc_mark(held_buffer->mapped_strings[index]);
49
+ }
50
+ }
51
+
52
+ static size_t HeldBuffer_memsize(const void *data)
53
+ {
54
+ const msgpack_held_buffer_t* held_buffer = (msgpack_held_buffer_t*)data;
55
+ return sizeof(size_t) + sizeof(VALUE) * held_buffer->size;
56
+ }
57
+
58
+ static const rb_data_type_t held_buffer_data_type = {
59
+ .wrap_struct_name = "msgpack:held_buffer",
60
+ .function = {
61
+ .dmark = HeldBuffer_mark,
62
+ .dfree = RUBY_TYPED_DEFAULT_FREE,
63
+ .dsize = HeldBuffer_memsize,
64
+ },
65
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
66
+ };
67
+
68
+ VALUE MessagePack_Buffer_hold(msgpack_buffer_t* buffer)
69
+ {
70
+ size_t mapped_strings_count = 0;
71
+ msgpack_buffer_chunk_t* c = buffer->head;
72
+ while (c != &buffer->tail) {
73
+ if (c->mapped_string != NO_MAPPED_STRING) {
74
+ mapped_strings_count++;
75
+ }
76
+ c = c->next;
77
+ }
78
+ if (c->mapped_string != NO_MAPPED_STRING) {
79
+ mapped_strings_count++;
80
+ }
81
+
82
+ if (mapped_strings_count == 0) {
83
+ return Qnil;
84
+ }
85
+
86
+ msgpack_held_buffer_t* held_buffer = xmalloc(sizeof(msgpack_held_buffer_t) + mapped_strings_count * sizeof(VALUE));
87
+
88
+ c = buffer->head;
89
+ mapped_strings_count = 0;
90
+ while (c != &buffer->tail) {
91
+ if (c->mapped_string != NO_MAPPED_STRING) {
92
+ held_buffer->mapped_strings[mapped_strings_count] = c->mapped_string;
93
+ mapped_strings_count++;
94
+ }
95
+ c = c->next;
96
+ }
97
+ if (c->mapped_string != NO_MAPPED_STRING) {
98
+ held_buffer->mapped_strings[mapped_strings_count] = c->mapped_string;
99
+ mapped_strings_count++;
100
+ }
101
+ held_buffer->size = mapped_strings_count;
102
+ return TypedData_Wrap_Struct(cMessagePack_HeldBuffer, &held_buffer_data_type, held_buffer);
103
+ }
104
+
37
105
 
38
106
  #define CHECK_STRING_TYPE(value) \
39
107
  value = rb_check_string_type(value); \
@@ -520,6 +588,9 @@ void MessagePack_Buffer_module_init(VALUE mMessagePack)
520
588
 
521
589
  msgpack_buffer_static_init();
522
590
 
591
+ cMessagePack_HeldBuffer = rb_define_class_under(mMessagePack, "HeldBuffer", rb_cBasicObject);
592
+ rb_undef_alloc_func(cMessagePack_HeldBuffer);
593
+
523
594
  cMessagePack_Buffer = rb_define_class_under(mMessagePack, "Buffer", rb_cObject);
524
595
 
525
596
  rb_define_alloc_func(cMessagePack_Buffer, Buffer_alloc);
@@ -25,6 +25,7 @@ extern VALUE cMessagePack_Buffer;
25
25
  void MessagePack_Buffer_module_init(VALUE mMessagePack);
26
26
 
27
27
  VALUE MessagePack_Buffer_wrap(msgpack_buffer_t* b, VALUE owner);
28
+ VALUE MessagePack_Buffer_hold(msgpack_buffer_t* b);
28
29
 
29
30
  void MessagePack_Buffer_set_options(msgpack_buffer_t* b, VALUE io, VALUE options);
30
31
 
@@ -1,9 +1,8 @@
1
1
  require 'mkmf'
2
2
 
3
- have_header("ruby/st.h")
4
- have_header("st.h")
5
3
  have_func("rb_enc_interned_str", "ruby.h") # Ruby 3.0+
6
4
  have_func("rb_hash_new_capa", "ruby.h") # Ruby 3.2+
5
+ have_func("rb_proc_call_with_block", "ruby.h") # CRuby (TruffleRuby doesn't have it)
7
6
 
8
7
  append_cflags([
9
8
  "-fvisibility=hidden",
@@ -75,7 +75,7 @@ static const rb_data_type_t factory_data_type = {
75
75
  .dfree = Factory_free,
76
76
  .dsize = Factory_memsize,
77
77
  },
78
- .flags = RUBY_TYPED_FREE_IMMEDIATELY
78
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
79
79
  };
80
80
 
81
81
  static inline msgpack_factory_t *Factory_get(VALUE object)
@@ -98,7 +98,7 @@ static VALUE Factory_initialize(int argc, VALUE* argv, VALUE self)
98
98
  {
99
99
  msgpack_factory_t *fc = Factory_get(self);
100
100
 
101
- msgpack_packer_ext_registry_init(&fc->pkrg);
101
+ msgpack_packer_ext_registry_init(self, &fc->pkrg);
102
102
  // fc->ukrg is lazily initialized
103
103
 
104
104
  fc->has_symbol_ext_type = false;
@@ -124,7 +124,7 @@ static VALUE Factory_dup(VALUE self)
124
124
  cloned_fc->has_symbol_ext_type = fc->has_symbol_ext_type;
125
125
  cloned_fc->pkrg = fc->pkrg;
126
126
  msgpack_unpacker_ext_registry_borrow(fc->ukrg, &cloned_fc->ukrg);
127
- msgpack_packer_ext_registry_dup(&fc->pkrg, &cloned_fc->pkrg);
127
+ msgpack_packer_ext_registry_dup(clone, &fc->pkrg, &cloned_fc->pkrg);
128
128
 
129
129
  return clone;
130
130
  }
@@ -139,7 +139,7 @@ static VALUE Factory_freeze(VALUE self) {
139
139
  // If the factory is frozen, we can safely share the packer cache between
140
140
  // all packers. So we eagerly create it now so it's available when #packer
141
141
  // is called.
142
- fc->pkrg.cache = rb_hash_new();
142
+ RB_OBJ_WRITE(self, &fc->pkrg.cache, rb_hash_new());
143
143
  }
144
144
  }
145
145
 
@@ -158,7 +158,7 @@ VALUE MessagePack_Factory_packer(int argc, VALUE* argv, VALUE self)
158
158
 
159
159
  msgpack_packer_t* pk = MessagePack_Packer_get(packer);
160
160
  msgpack_packer_ext_registry_destroy(&pk->ext_registry);
161
- msgpack_packer_ext_registry_dup(&fc->pkrg, &pk->ext_registry);
161
+ msgpack_packer_ext_registry_borrow(packer, &fc->pkrg, &pk->ext_registry);
162
162
  pk->has_bigint_ext_type = fc->has_bigint_ext_type;
163
163
  pk->has_symbol_ext_type = fc->has_symbol_ext_type;
164
164
 
@@ -187,7 +187,7 @@ static VALUE Factory_registered_types_internal(VALUE self)
187
187
  VALUE uk_mapping = rb_hash_new();
188
188
  if (fc->ukrg) {
189
189
  for(int i=0; i < 256; i++) {
190
- if(fc->ukrg->array[i] != Qnil) {
190
+ if(!NIL_P(fc->ukrg->array[i])) {
191
191
  rb_hash_aset(uk_mapping, INT2FIX(i - 128), fc->ukrg->array[i]);
192
192
  }
193
193
  }
@@ -200,72 +200,35 @@ static VALUE Factory_registered_types_internal(VALUE self)
200
200
  );
201
201
  }
202
202
 
203
- static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
203
+ static VALUE Factory_register_type_internal(VALUE self, VALUE rb_ext_type, VALUE ext_module, VALUE options)
204
204
  {
205
205
  msgpack_factory_t *fc = Factory_get(self);
206
206
 
207
- int ext_type;
208
- int flags = 0;
209
- VALUE ext_module;
210
- VALUE options = Qnil;
211
- VALUE packer_arg, unpacker_arg;
212
- VALUE packer_proc, unpacker_proc;
207
+ Check_Type(rb_ext_type, T_FIXNUM);
213
208
 
214
- if (OBJ_FROZEN(self)) {
215
- rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Factory");
209
+ if(rb_type(ext_module) != T_MODULE && rb_type(ext_module) != T_CLASS) {
210
+ rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
216
211
  }
217
212
 
218
- switch (argc) {
219
- case 2:
220
- /* register_type(0x7f, Time) */
221
- packer_arg = ID2SYM(rb_intern("to_msgpack_ext"));
222
- unpacker_arg = ID2SYM(rb_intern("from_msgpack_ext"));
223
- break;
224
- case 3:
225
- /* register_type(0x7f, Time, packer: proc-like, unpacker: proc-like) */
226
- options = argv[2];
227
- if(rb_type(options) != T_HASH) {
228
- rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
229
- }
213
+ int flags = 0;
230
214
 
231
- packer_arg = rb_hash_aref(options, ID2SYM(rb_intern("packer")));
232
- unpacker_arg = rb_hash_aref(options, ID2SYM(rb_intern("unpacker")));
233
- break;
234
- default:
235
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc);
215
+ VALUE packer_proc = Qnil;
216
+ VALUE unpacker_proc = Qnil;
217
+ if(!NIL_P(options)) {
218
+ Check_Type(options, T_HASH);
219
+ packer_proc = rb_hash_aref(options, ID2SYM(rb_intern("packer")));
220
+ unpacker_proc = rb_hash_aref(options, ID2SYM(rb_intern("unpacker")));
236
221
  }
237
222
 
238
- if (options != Qnil) {
239
- Check_Type(options, T_HASH);
223
+ if (OBJ_FROZEN(self)) {
224
+ rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Factory");
240
225
  }
241
226
 
242
- ext_type = NUM2INT(argv[0]);
227
+ int ext_type = NUM2INT(rb_ext_type);
243
228
  if(ext_type < -128 || ext_type > 127) {
244
229
  rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
245
230
  }
246
231
 
247
- ext_module = argv[1];
248
- if(rb_type(ext_module) != T_MODULE && rb_type(ext_module) != T_CLASS) {
249
- rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
250
- }
251
-
252
- packer_proc = Qnil;
253
- unpacker_proc = Qnil;
254
-
255
- if(packer_arg != Qnil) {
256
- packer_proc = rb_funcall(packer_arg, rb_intern("to_proc"), 0);
257
- }
258
-
259
- if(unpacker_arg != Qnil) {
260
- if(rb_type(unpacker_arg) == T_SYMBOL || rb_type(unpacker_arg) == T_STRING) {
261
- unpacker_proc = rb_obj_method(ext_module, unpacker_arg);
262
- } else if (rb_respond_to(unpacker_arg, rb_intern("call"))) {
263
- unpacker_proc = unpacker_arg;
264
- } else {
265
- unpacker_proc = rb_funcall(unpacker_arg, rb_intern("method"), 1, ID2SYM(rb_intern("call")));
266
- }
267
- }
268
-
269
232
  if(ext_module == rb_cSymbol) {
270
233
  if(NIL_P(options) || RTEST(rb_hash_aref(options, ID2SYM(rb_intern("packer"))))) {
271
234
  fc->has_symbol_ext_type = true;
@@ -289,8 +252,8 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
289
252
  }
290
253
  }
291
254
 
292
- msgpack_packer_ext_registry_put(&fc->pkrg, ext_module, ext_type, flags, packer_proc, packer_arg);
293
- msgpack_unpacker_ext_registry_put(&fc->ukrg, ext_module, ext_type, flags, unpacker_proc, unpacker_arg);
255
+ msgpack_packer_ext_registry_put(self, &fc->pkrg, ext_module, ext_type, flags, packer_proc);
256
+ msgpack_unpacker_ext_registry_put(self, &fc->ukrg, ext_module, ext_type, flags, unpacker_proc);
294
257
 
295
258
  return Qnil;
296
259
  }
@@ -309,5 +272,5 @@ void MessagePack_Factory_module_init(VALUE mMessagePack)
309
272
  rb_define_method(cMessagePack_Factory, "unpacker", MessagePack_Factory_unpacker, -1);
310
273
 
311
274
  rb_define_private_method(cMessagePack_Factory, "registered_types_internal", Factory_registered_types_internal, 0);
312
- rb_define_method(cMessagePack_Factory, "register_type", Factory_register_type, -1);
275
+ rb_define_private_method(cMessagePack_Factory, "register_type_internal", Factory_register_type_internal, 3);
313
276
  }