msgpack 0.6.0-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +26 -0
  4. data/ChangeLog +129 -0
  5. data/Dockerfile +62 -0
  6. data/LICENSE +177 -0
  7. data/README.rdoc +141 -0
  8. data/Rakefile +68 -0
  9. data/bench/pack.rb +23 -0
  10. data/bench/pack_log.rb +33 -0
  11. data/bench/pack_log_long.rb +65 -0
  12. data/bench/run.sh +14 -0
  13. data/bench/run_long.sh +35 -0
  14. data/bench/unpack.rb +21 -0
  15. data/bench/unpack_log.rb +34 -0
  16. data/bench/unpack_log_long.rb +67 -0
  17. data/doclib/msgpack.rb +77 -0
  18. data/doclib/msgpack/buffer.rb +193 -0
  19. data/doclib/msgpack/core_ext.rb +101 -0
  20. data/doclib/msgpack/error.rb +14 -0
  21. data/doclib/msgpack/packer.rb +134 -0
  22. data/doclib/msgpack/unpacker.rb +146 -0
  23. data/ext/java/org/msgpack/jruby/Buffer.java +221 -0
  24. data/ext/java/org/msgpack/jruby/Decoder.java +201 -0
  25. data/ext/java/org/msgpack/jruby/Encoder.java +308 -0
  26. data/ext/java/org/msgpack/jruby/ExtensionValue.java +136 -0
  27. data/ext/java/org/msgpack/jruby/MessagePackLibrary.java +107 -0
  28. data/ext/java/org/msgpack/jruby/Packer.java +78 -0
  29. data/ext/java/org/msgpack/jruby/Types.java +37 -0
  30. data/ext/java/org/msgpack/jruby/Unpacker.java +170 -0
  31. data/ext/msgpack/buffer.c +695 -0
  32. data/ext/msgpack/buffer.h +447 -0
  33. data/ext/msgpack/buffer_class.c +507 -0
  34. data/ext/msgpack/buffer_class.h +32 -0
  35. data/ext/msgpack/compat.h +114 -0
  36. data/ext/msgpack/core_ext.c +129 -0
  37. data/ext/msgpack/core_ext.h +26 -0
  38. data/ext/msgpack/extconf.rb +30 -0
  39. data/ext/msgpack/packer.c +168 -0
  40. data/ext/msgpack/packer.h +441 -0
  41. data/ext/msgpack/packer_class.c +302 -0
  42. data/ext/msgpack/packer_class.h +30 -0
  43. data/ext/msgpack/rbinit.c +33 -0
  44. data/ext/msgpack/rmem.c +94 -0
  45. data/ext/msgpack/rmem.h +109 -0
  46. data/ext/msgpack/sysdep.h +115 -0
  47. data/ext/msgpack/sysdep_endian.h +50 -0
  48. data/ext/msgpack/sysdep_types.h +46 -0
  49. data/ext/msgpack/unpacker.c +771 -0
  50. data/ext/msgpack/unpacker.h +122 -0
  51. data/ext/msgpack/unpacker_class.c +405 -0
  52. data/ext/msgpack/unpacker_class.h +32 -0
  53. data/lib/msgpack.rb +13 -0
  54. data/lib/msgpack/version.rb +3 -0
  55. data/msgpack.gemspec +31 -0
  56. data/msgpack.org.md +46 -0
  57. data/spec/cases.json +1 -0
  58. data/spec/cases.msg +0 -0
  59. data/spec/cases_compact.msg +0 -0
  60. data/spec/cases_spec.rb +39 -0
  61. data/spec/cruby/buffer_io_spec.rb +256 -0
  62. data/spec/cruby/buffer_packer.rb +29 -0
  63. data/spec/cruby/buffer_spec.rb +572 -0
  64. data/spec/cruby/buffer_unpacker.rb +19 -0
  65. data/spec/cruby/packer_spec.rb +120 -0
  66. data/spec/cruby/unpacker_spec.rb +305 -0
  67. data/spec/format_spec.rb +282 -0
  68. data/spec/jruby/benchmarks/shootout_bm.rb +73 -0
  69. data/spec/jruby/benchmarks/symbolize_keys_bm.rb +25 -0
  70. data/spec/jruby/msgpack/unpacker_spec.rb +290 -0
  71. data/spec/jruby/msgpack_spec.rb +142 -0
  72. data/spec/pack_spec.rb +67 -0
  73. data/spec/random_compat.rb +24 -0
  74. data/spec/spec_helper.rb +27 -0
  75. data/spec/unpack_spec.rb +60 -0
  76. metadata +208 -0
@@ -0,0 +1,771 @@
1
+ /*
2
+ * MessagePack for Ruby
3
+ *
4
+ * Copyright (C) 2008-2013 Sadayuki Furuhashi
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ #include "unpacker.h"
20
+ #include "rmem.h"
21
+
22
+ #if !defined(DISABLE_RMEM) && !defined(DISABLE_UNPACKER_STACK_RMEM) && \
23
+ MSGPACK_UNPACKER_STACK_CAPACITY * MSGPACK_UNPACKER_STACK_SIZE <= MSGPACK_RMEM_PAGE_SIZE
24
+ #define UNPACKER_STACK_RMEM
25
+ #endif
26
+
27
+ #ifdef UNPACKER_STACK_RMEM
28
+ static msgpack_rmem_t s_stack_rmem;
29
+ #endif
30
+
31
+ void msgpack_unpacker_static_init()
32
+ {
33
+ #ifdef UNPACKER_STACK_RMEM
34
+ msgpack_rmem_init(&s_stack_rmem);
35
+ #endif
36
+ }
37
+
38
+ void msgpack_unpacker_static_destroy()
39
+ {
40
+ #ifdef UNPACKER_STACK_RMEM
41
+ msgpack_rmem_destroy(&s_stack_rmem);
42
+ #endif
43
+ }
44
+
45
+ #define HEAD_BYTE_REQUIRED 0xc1
46
+
47
+ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
48
+ {
49
+ memset(uk, 0, sizeof(msgpack_unpacker_t));
50
+
51
+ msgpack_buffer_init(UNPACKER_BUFFER_(uk));
52
+
53
+ uk->head_byte = HEAD_BYTE_REQUIRED;
54
+
55
+ uk->last_object = Qnil;
56
+ uk->reading_raw = Qnil;
57
+
58
+ #ifdef UNPACKER_STACK_RMEM
59
+ uk->stack = msgpack_rmem_alloc(&s_stack_rmem);
60
+ /*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
61
+ #else
62
+ /*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_t));*/
63
+ uk->stack = malloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_t));
64
+ #endif
65
+ uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
66
+ }
67
+
68
+ void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
69
+ {
70
+ #ifdef UNPACKER_STACK_RMEM
71
+ msgpack_rmem_free(&s_stack_rmem, uk->stack);
72
+ #else
73
+ free(uk->stack);
74
+ #endif
75
+
76
+ msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
77
+ }
78
+
79
+ void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
80
+ {
81
+ rb_gc_mark(uk->last_object);
82
+ rb_gc_mark(uk->reading_raw);
83
+
84
+ msgpack_unpacker_stack_t* s = uk->stack;
85
+ msgpack_unpacker_stack_t* send = uk->stack + uk->stack_depth;
86
+ for(; s < send; s++) {
87
+ rb_gc_mark(s->object);
88
+ rb_gc_mark(s->key);
89
+ }
90
+
91
+ /* See MessagePack_Buffer_wrap */
92
+ /* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
93
+ rb_gc_mark(uk->buffer_ref);
94
+ }
95
+
96
+ void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
97
+ {
98
+ msgpack_buffer_clear(UNPACKER_BUFFER_(uk));
99
+
100
+ uk->head_byte = HEAD_BYTE_REQUIRED;
101
+
102
+ /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack_depth);*/
103
+ uk->stack_depth = 0;
104
+
105
+ uk->last_object = Qnil;
106
+ uk->reading_raw = Qnil;
107
+ uk->reading_raw_remaining = 0;
108
+ }
109
+
110
+
111
+ /* head byte functions */
112
+ static int read_head_byte(msgpack_unpacker_t* uk)
113
+ {
114
+ int r = msgpack_buffer_read_1(UNPACKER_BUFFER_(uk));
115
+ if(r == -1) {
116
+ return PRIMITIVE_EOF;
117
+ }
118
+ return uk->head_byte = r;
119
+ }
120
+
121
+ static inline int get_head_byte(msgpack_unpacker_t* uk)
122
+ {
123
+ int b = uk->head_byte;
124
+ if(b == HEAD_BYTE_REQUIRED) {
125
+ b = read_head_byte(uk);
126
+ }
127
+ return b;
128
+ }
129
+
130
+ static inline void reset_head_byte(msgpack_unpacker_t* uk)
131
+ {
132
+ uk->head_byte = HEAD_BYTE_REQUIRED;
133
+ }
134
+
135
+ static inline int object_complete(msgpack_unpacker_t* uk, VALUE object)
136
+ {
137
+ uk->last_object = object;
138
+ reset_head_byte(uk);
139
+ return PRIMITIVE_OBJECT_COMPLETE;
140
+ }
141
+
142
+ static inline int object_complete_string(msgpack_unpacker_t* uk, VALUE str)
143
+ {
144
+ #ifdef COMPAT_HAVE_ENCODING
145
+ ENCODING_SET(str, msgpack_rb_encindex_utf8);
146
+ #endif
147
+ return object_complete(uk, str);
148
+ }
149
+
150
+ static inline int object_complete_binary(msgpack_unpacker_t* uk, VALUE str)
151
+ {
152
+ #ifdef COMPAT_HAVE_ENCODING
153
+ // TODO ruby 2.0 has String#b method
154
+ ENCODING_SET(str, msgpack_rb_encindex_ascii8bit);
155
+ #endif
156
+ return object_complete(uk, str);
157
+ }
158
+
159
+ /* stack funcs */
160
+ static inline msgpack_unpacker_stack_t* _msgpack_unpacker_stack_top(msgpack_unpacker_t* uk)
161
+ {
162
+ return &uk->stack[uk->stack_depth-1];
163
+ }
164
+
165
+ static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stack_type_t type, size_t count, VALUE object)
166
+ {
167
+ reset_head_byte(uk);
168
+
169
+ if(uk->stack_capacity - uk->stack_depth <= 0) {
170
+ return PRIMITIVE_STACK_TOO_DEEP;
171
+ }
172
+
173
+ msgpack_unpacker_stack_t* next = &uk->stack[uk->stack_depth];
174
+ next->count = count;
175
+ next->type = type;
176
+ next->object = object;
177
+ next->key = Qnil;
178
+
179
+ uk->stack_depth++;
180
+ return PRIMITIVE_CONTAINER_START;
181
+ }
182
+
183
+ static inline VALUE msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
184
+ {
185
+ return --uk->stack_depth;
186
+ }
187
+
188
+ static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
189
+ {
190
+ return uk->stack_depth == 0;
191
+ }
192
+
193
+ #ifdef USE_CASE_RANGE
194
+
195
+ #define SWITCH_RANGE_BEGIN(BYTE) { switch(BYTE) {
196
+ #define SWITCH_RANGE(BYTE, FROM, TO) } case FROM ... TO: {
197
+ #define SWITCH_RANGE_DEFAULT } default: {
198
+ #define SWITCH_RANGE_END } }
199
+
200
+ #else
201
+
202
+ #define SWITCH_RANGE_BEGIN(BYTE) { if(0) {
203
+ #define SWITCH_RANGE(BYTE, FROM, TO) } else if(FROM <= (BYTE) && (BYTE) <= TO) {
204
+ #define SWITCH_RANGE_DEFAULT } else {
205
+ #define SWITCH_RANGE_END } }
206
+
207
+ #endif
208
+
209
+
210
+ #define READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, n) \
211
+ union msgpack_buffer_cast_block_t* cb = msgpack_buffer_read_cast_block(UNPACKER_BUFFER_(uk), n); \
212
+ if(cb == NULL) { \
213
+ return PRIMITIVE_EOF; \
214
+ }
215
+
216
+ static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
217
+ {
218
+ if(uk->stack_depth > 0) {
219
+ msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
220
+ if(top->type == STACK_TYPE_MAP_KEY) {
221
+ return true;
222
+ }
223
+ }
224
+ return false;
225
+ }
226
+
227
+ static int read_raw_body_cont(msgpack_unpacker_t* uk)
228
+ {
229
+ size_t length = uk->reading_raw_remaining;
230
+
231
+ if(uk->reading_raw == Qnil) {
232
+ uk->reading_raw = rb_str_buf_new(length);
233
+ }
234
+
235
+ do {
236
+ size_t n = msgpack_buffer_read_to_string(UNPACKER_BUFFER_(uk), uk->reading_raw, length);
237
+ if(n == 0) {
238
+ return PRIMITIVE_EOF;
239
+ }
240
+ /* update reading_raw_remaining everytime because
241
+ * msgpack_buffer_read_to_string raises IOError */
242
+ uk->reading_raw_remaining = length = length - n;
243
+ } while(length > 0);
244
+
245
+ object_complete_string(uk, uk->reading_raw);
246
+ uk->reading_raw = Qnil;
247
+ return PRIMITIVE_OBJECT_COMPLETE;
248
+ }
249
+
250
+ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, bool str)
251
+ {
252
+ /* assuming uk->reading_raw == Qnil */
253
+
254
+ /* try optimized read */
255
+ size_t length = uk->reading_raw_remaining;
256
+ if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
257
+ /* don't use zerocopy for hash keys but get a frozen string directly
258
+ * because rb_hash_aset freezes keys and it causes copying */
259
+ bool will_freeze = is_reading_map_key(uk);
260
+ VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze);
261
+ if(str == true) {
262
+ object_complete_string(uk, string);
263
+ } else {
264
+ object_complete_binary(uk, string);
265
+ }
266
+ if(will_freeze) {
267
+ rb_obj_freeze(string);
268
+ }
269
+ uk->reading_raw_remaining = 0;
270
+ return PRIMITIVE_OBJECT_COMPLETE;
271
+ }
272
+
273
+ return read_raw_body_cont(uk);
274
+ }
275
+
276
+ static int read_primitive(msgpack_unpacker_t* uk)
277
+ {
278
+ if(uk->reading_raw_remaining > 0) {
279
+ return read_raw_body_cont(uk);
280
+ }
281
+
282
+ int b = get_head_byte(uk);
283
+ if(b < 0) {
284
+ return b;
285
+ }
286
+
287
+ SWITCH_RANGE_BEGIN(b)
288
+ SWITCH_RANGE(b, 0x00, 0x7f) // Positive Fixnum
289
+ return object_complete(uk, INT2NUM(b));
290
+
291
+ SWITCH_RANGE(b, 0xe0, 0xff) // Negative Fixnum
292
+ return object_complete(uk, INT2NUM((int8_t)b));
293
+
294
+ SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw / fixstr
295
+ int count = b & 0x1f;
296
+ if(count == 0) {
297
+ return object_complete_string(uk, rb_str_buf_new(0));
298
+ }
299
+ /* read_raw_body_begin sets uk->reading_raw */
300
+ uk->reading_raw_remaining = count;
301
+ return read_raw_body_begin(uk, true);
302
+
303
+ SWITCH_RANGE(b, 0x90, 0x9f) // FixArray
304
+ int count = b & 0x0f;
305
+ if(count == 0) {
306
+ return object_complete(uk, rb_ary_new());
307
+ }
308
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
309
+
310
+ SWITCH_RANGE(b, 0x80, 0x8f) // FixMap
311
+ int count = b & 0x0f;
312
+ if(count == 0) {
313
+ return object_complete(uk, rb_hash_new());
314
+ }
315
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
316
+
317
+ SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
318
+ switch(b) {
319
+ case 0xc0: // nil
320
+ return object_complete(uk, Qnil);
321
+
322
+ //case 0xc1: // string
323
+
324
+ case 0xc2: // false
325
+ return object_complete(uk, Qfalse);
326
+
327
+ case 0xc3: // true
328
+ return object_complete(uk, Qtrue);
329
+
330
+ //case 0xc7: // ext 8
331
+ //case 0xc8: // ext 16
332
+ //case 0xc9: // ext 32
333
+
334
+ case 0xca: // float
335
+ {
336
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
337
+ cb->u32 = _msgpack_be_float(cb->u32);
338
+ return object_complete(uk, rb_float_new(cb->f));
339
+ }
340
+
341
+ case 0xcb: // double
342
+ {
343
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
344
+ cb->u64 = _msgpack_be_double(cb->u64);
345
+ return object_complete(uk, rb_float_new(cb->d));
346
+ }
347
+
348
+ case 0xcc: // unsigned int 8
349
+ {
350
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
351
+ uint8_t u8 = cb->u8;
352
+ return object_complete(uk, INT2NUM((int)u8));
353
+ }
354
+
355
+ case 0xcd: // unsigned int 16
356
+ {
357
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
358
+ uint16_t u16 = _msgpack_be16(cb->u16);
359
+ return object_complete(uk, INT2NUM((int)u16));
360
+ }
361
+
362
+ case 0xce: // unsigned int 32
363
+ {
364
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
365
+ uint32_t u32 = _msgpack_be32(cb->u32);
366
+ return object_complete(uk, ULONG2NUM((unsigned long)u32));
367
+ }
368
+
369
+ case 0xcf: // unsigned int 64
370
+ {
371
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
372
+ uint64_t u64 = _msgpack_be64(cb->u64);
373
+ return object_complete(uk, rb_ull2inum(u64));
374
+ }
375
+
376
+ case 0xd0: // signed int 8
377
+ {
378
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
379
+ int8_t i8 = cb->i8;
380
+ return object_complete(uk, INT2NUM((int)i8));
381
+ }
382
+
383
+ case 0xd1: // signed int 16
384
+ {
385
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
386
+ int16_t i16 = _msgpack_be16(cb->i16);
387
+ return object_complete(uk, INT2NUM((int)i16));
388
+ }
389
+
390
+ case 0xd2: // signed int 32
391
+ {
392
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
393
+ int32_t i32 = _msgpack_be32(cb->i32);
394
+ return object_complete(uk, LONG2NUM((long)i32));
395
+ }
396
+
397
+ case 0xd3: // signed int 64
398
+ {
399
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
400
+ int64_t i64 = _msgpack_be64(cb->i64);
401
+ return object_complete(uk, rb_ll2inum(i64));
402
+ }
403
+
404
+ //case 0xd4: // fixext 1
405
+ //case 0xd5: // fixext 2
406
+ //case 0xd6: // fixext 4
407
+ //case 0xd7: // fixext 8
408
+ //case 0xd8: // fixext 16
409
+
410
+ case 0xd9: // raw 8 / str 8
411
+ {
412
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
413
+ uint8_t count = cb->u8;
414
+ if(count == 0) {
415
+ return object_complete_string(uk, rb_str_buf_new(0));
416
+ }
417
+ /* read_raw_body_begin sets uk->reading_raw */
418
+ uk->reading_raw_remaining = count;
419
+ return read_raw_body_begin(uk, true);
420
+ }
421
+
422
+ case 0xda: // raw 16 / str 16
423
+ {
424
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
425
+ uint16_t count = _msgpack_be16(cb->u16);
426
+ if(count == 0) {
427
+ return object_complete_string(uk, rb_str_buf_new(0));
428
+ }
429
+ /* read_raw_body_begin sets uk->reading_raw */
430
+ uk->reading_raw_remaining = count;
431
+ return read_raw_body_begin(uk, true);
432
+ }
433
+
434
+ case 0xdb: // raw 32 / str 32
435
+ {
436
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
437
+ uint32_t count = _msgpack_be32(cb->u32);
438
+ if(count == 0) {
439
+ return object_complete_string(uk, rb_str_buf_new(0));
440
+ }
441
+ /* read_raw_body_begin sets uk->reading_raw */
442
+ uk->reading_raw_remaining = count;
443
+ return read_raw_body_begin(uk, true);
444
+ }
445
+
446
+ case 0xc4: // bin 8
447
+ {
448
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
449
+ uint8_t count = cb->u8;
450
+ if(count == 0) {
451
+ return object_complete_binary(uk, rb_str_buf_new(0));
452
+ }
453
+ /* read_raw_body_begin sets uk->reading_raw */
454
+ uk->reading_raw_remaining = count;
455
+ return read_raw_body_begin(uk, false);
456
+ }
457
+
458
+ case 0xc5: // bin 16
459
+ {
460
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
461
+ uint16_t count = _msgpack_be16(cb->u16);
462
+ if(count == 0) {
463
+ return object_complete_binary(uk, rb_str_buf_new(0));
464
+ }
465
+ /* read_raw_body_begin sets uk->reading_raw */
466
+ uk->reading_raw_remaining = count;
467
+ return read_raw_body_begin(uk, false);
468
+ }
469
+
470
+ case 0xc6: // bin 32
471
+ {
472
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
473
+ uint32_t count = _msgpack_be32(cb->u32);
474
+ if(count == 0) {
475
+ return object_complete_binary(uk, rb_str_buf_new(0));
476
+ }
477
+ /* read_raw_body_begin sets uk->reading_raw */
478
+ uk->reading_raw_remaining = count;
479
+ return read_raw_body_begin(uk, false);
480
+ }
481
+
482
+ case 0xdc: // array 16
483
+ {
484
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
485
+ uint16_t count = _msgpack_be16(cb->u16);
486
+ if(count == 0) {
487
+ return object_complete(uk, rb_ary_new());
488
+ }
489
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
490
+ }
491
+
492
+ case 0xdd: // array 32
493
+ {
494
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
495
+ uint32_t count = _msgpack_be32(cb->u32);
496
+ if(count == 0) {
497
+ return object_complete(uk, rb_ary_new());
498
+ }
499
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
500
+ }
501
+
502
+ case 0xde: // map 16
503
+ {
504
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
505
+ uint16_t count = _msgpack_be16(cb->u16);
506
+ if(count == 0) {
507
+ return object_complete(uk, rb_hash_new());
508
+ }
509
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
510
+ }
511
+
512
+ case 0xdf: // map 32
513
+ {
514
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
515
+ uint32_t count = _msgpack_be32(cb->u32);
516
+ if(count == 0) {
517
+ return object_complete(uk, rb_hash_new());
518
+ }
519
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
520
+ }
521
+
522
+ default:
523
+ return PRIMITIVE_INVALID_BYTE;
524
+ }
525
+
526
+ SWITCH_RANGE_DEFAULT
527
+ return PRIMITIVE_INVALID_BYTE;
528
+
529
+ SWITCH_RANGE_END
530
+ }
531
+
532
+ int msgpack_unpacker_read_array_header(msgpack_unpacker_t* uk, uint32_t* result_size)
533
+ {
534
+ int b = get_head_byte(uk);
535
+ if(b < 0) {
536
+ return b;
537
+ }
538
+
539
+ if(0x90 <= b && b <= 0x9f) {
540
+ *result_size = b & 0x0f;
541
+
542
+ } else if(b == 0xdc) {
543
+ /* array 16 */
544
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
545
+ *result_size = _msgpack_be16(cb->u16);
546
+
547
+ } else if(b == 0xdd) {
548
+ /* array 32 */
549
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
550
+ *result_size = _msgpack_be32(cb->u32);
551
+
552
+ } else {
553
+ return PRIMITIVE_UNEXPECTED_TYPE;
554
+ }
555
+
556
+ reset_head_byte(uk);
557
+ return 0;
558
+ }
559
+
560
+ int msgpack_unpacker_read_map_header(msgpack_unpacker_t* uk, uint32_t* result_size)
561
+ {
562
+ int b = get_head_byte(uk);
563
+ if(b < 0) {
564
+ return b;
565
+ }
566
+
567
+ if(0x80 <= b && b <= 0x8f) {
568
+ *result_size = b & 0x0f;
569
+
570
+ } else if(b == 0xde) {
571
+ /* map 16 */
572
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
573
+ *result_size = _msgpack_be16(cb->u16);
574
+
575
+ } else if(b == 0xdf) {
576
+ /* map 32 */
577
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
578
+ *result_size = _msgpack_be32(cb->u32);
579
+
580
+ } else {
581
+ return PRIMITIVE_UNEXPECTED_TYPE;
582
+ }
583
+
584
+ reset_head_byte(uk);
585
+ return 0;
586
+ }
587
+
588
+ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
589
+ {
590
+ while(true) {
591
+ int r = read_primitive(uk);
592
+ if(r < 0) {
593
+ return r;
594
+ }
595
+ if(r == PRIMITIVE_CONTAINER_START) {
596
+ continue;
597
+ }
598
+ /* PRIMITIVE_OBJECT_COMPLETE */
599
+
600
+ if(msgpack_unpacker_stack_is_empty(uk)) {
601
+ return PRIMITIVE_OBJECT_COMPLETE;
602
+ }
603
+
604
+ container_completed:
605
+ {
606
+ msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
607
+ switch(top->type) {
608
+ case STACK_TYPE_ARRAY:
609
+ rb_ary_push(top->object, uk->last_object);
610
+ break;
611
+ case STACK_TYPE_MAP_KEY:
612
+ top->key = uk->last_object;
613
+ top->type = STACK_TYPE_MAP_VALUE;
614
+ break;
615
+ case STACK_TYPE_MAP_VALUE:
616
+ if(uk->symbolize_keys && rb_type(top->key) == T_STRING) {
617
+ /* here uses rb_intern_str instead of rb_intern so that Ruby VM can GC unused symbols */
618
+ #ifdef HAVE_RB_STR_INTERN
619
+ /* rb_str_intern is added since MRI 2.2.0 */
620
+ rb_hash_aset(top->object, rb_str_intern(top->key), uk->last_object);
621
+ #else
622
+ #ifndef HAVE_RB_INTERN_STR
623
+ /* MRI 1.8 doesn't have rb_intern_str or rb_intern2 */
624
+ rb_hash_aset(top->object, ID2SYM(rb_intern(RSTRING_PTR(top->key))), uk->last_object);
625
+ #else
626
+ rb_hash_aset(top->object, ID2SYM(rb_intern_str(top->key)), uk->last_object);
627
+ #endif
628
+ #endif
629
+ } else {
630
+ rb_hash_aset(top->object, top->key, uk->last_object);
631
+ }
632
+ top->type = STACK_TYPE_MAP_KEY;
633
+ break;
634
+ }
635
+ size_t count = --top->count;
636
+
637
+ if(count == 0) {
638
+ object_complete(uk, top->object);
639
+ if(msgpack_unpacker_stack_pop(uk) <= target_stack_depth) {
640
+ return PRIMITIVE_OBJECT_COMPLETE;
641
+ }
642
+ goto container_completed;
643
+ }
644
+ }
645
+ }
646
+ }
647
+
648
+ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
649
+ {
650
+ while(true) {
651
+ int r = read_primitive(uk);
652
+ if(r < 0) {
653
+ return r;
654
+ }
655
+ if(r == PRIMITIVE_CONTAINER_START) {
656
+ continue;
657
+ }
658
+ /* PRIMITIVE_OBJECT_COMPLETE */
659
+
660
+ if(msgpack_unpacker_stack_is_empty(uk)) {
661
+ return PRIMITIVE_OBJECT_COMPLETE;
662
+ }
663
+
664
+ container_completed:
665
+ {
666
+ msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
667
+
668
+ /* this section optimized out */
669
+ // TODO object_complete still creates objects which should be optimized out
670
+
671
+ size_t count = --top->count;
672
+
673
+ if(count == 0) {
674
+ object_complete(uk, Qnil);
675
+ if(msgpack_unpacker_stack_pop(uk) <= target_stack_depth) {
676
+ return PRIMITIVE_OBJECT_COMPLETE;
677
+ }
678
+ goto container_completed;
679
+ }
680
+ }
681
+ }
682
+ }
683
+
684
+ int msgpack_unpacker_peek_next_object_type(msgpack_unpacker_t* uk)
685
+ {
686
+ int b = get_head_byte(uk);
687
+ if(b < 0) {
688
+ return b;
689
+ }
690
+
691
+ SWITCH_RANGE_BEGIN(b)
692
+ SWITCH_RANGE(b, 0x00, 0x7f) // Positive Fixnum
693
+ return TYPE_INTEGER;
694
+
695
+ SWITCH_RANGE(b, 0xe0, 0xff) // Negative Fixnum
696
+ return TYPE_INTEGER;
697
+
698
+ SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw
699
+ return TYPE_RAW;
700
+
701
+ SWITCH_RANGE(b, 0x90, 0x9f) // FixArray
702
+ return TYPE_ARRAY;
703
+
704
+ SWITCH_RANGE(b, 0x80, 0x8f) // FixMap
705
+ return TYPE_MAP;
706
+
707
+ SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
708
+ switch(b) {
709
+ case 0xc0: // nil
710
+ return TYPE_NIL;
711
+
712
+ case 0xc2: // false
713
+ case 0xc3: // true
714
+ return TYPE_BOOLEAN;
715
+
716
+ case 0xca: // float
717
+ case 0xcb: // double
718
+ return TYPE_FLOAT;
719
+
720
+ case 0xcc: // unsigned int 8
721
+ case 0xcd: // unsigned int 16
722
+ case 0xce: // unsigned int 32
723
+ case 0xcf: // unsigned int 64
724
+ return TYPE_INTEGER;
725
+
726
+ case 0xd0: // signed int 8
727
+ case 0xd1: // signed int 16
728
+ case 0xd2: // signed int 32
729
+ case 0xd3: // signed int 64
730
+ return TYPE_INTEGER;
731
+
732
+ case 0xd9: // raw 8 / str 8
733
+ case 0xda: // raw 16 / str 16
734
+ case 0xdb: // raw 32 / str 32
735
+ return TYPE_RAW;
736
+
737
+ case 0xc4: // bin 8
738
+ case 0xc5: // bin 16
739
+ case 0xc6: // bin 32
740
+ return TYPE_RAW;
741
+
742
+ case 0xdc: // array 16
743
+ case 0xdd: // array 32
744
+ return TYPE_ARRAY;
745
+
746
+ case 0xde: // map 16
747
+ case 0xdf: // map 32
748
+ return TYPE_MAP;
749
+
750
+ default:
751
+ return PRIMITIVE_INVALID_BYTE;
752
+ }
753
+
754
+ SWITCH_RANGE_DEFAULT
755
+ return PRIMITIVE_INVALID_BYTE;
756
+
757
+ SWITCH_RANGE_END
758
+ }
759
+
760
+ int msgpack_unpacker_skip_nil(msgpack_unpacker_t* uk)
761
+ {
762
+ int b = get_head_byte(uk);
763
+ if(b < 0) {
764
+ return b;
765
+ }
766
+ if(b == 0xc0) {
767
+ return 1;
768
+ }
769
+ return 0;
770
+ }
771
+