msgpack 1.4.2 → 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 +4 -4
- data/ChangeLog +89 -0
- data/README.md +73 -13
- data/ext/java/org/msgpack/jruby/Buffer.java +26 -19
- data/ext/java/org/msgpack/jruby/Decoder.java +29 -21
- data/ext/java/org/msgpack/jruby/Encoder.java +68 -30
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +43 -64
- data/ext/java/org/msgpack/jruby/ExtensionValue.java +6 -9
- data/ext/java/org/msgpack/jruby/Factory.java +43 -42
- data/ext/java/org/msgpack/jruby/Packer.java +37 -40
- data/ext/java/org/msgpack/jruby/Unpacker.java +80 -73
- data/ext/msgpack/buffer.c +54 -74
- data/ext/msgpack/buffer.h +21 -18
- data/ext/msgpack/buffer_class.c +161 -52
- data/ext/msgpack/buffer_class.h +1 -0
- data/ext/msgpack/compat.h +0 -99
- data/ext/msgpack/extconf.rb +25 -46
- data/ext/msgpack/factory_class.c +143 -87
- data/ext/msgpack/packer.c +66 -43
- data/ext/msgpack/packer.h +25 -20
- data/ext/msgpack/packer_class.c +102 -130
- data/ext/msgpack/packer_class.h +11 -0
- data/ext/msgpack/packer_ext_registry.c +35 -40
- data/ext/msgpack/packer_ext_registry.h +41 -38
- data/ext/msgpack/rbinit.c +1 -1
- data/ext/msgpack/rmem.c +3 -4
- data/ext/msgpack/sysdep.h +5 -2
- data/ext/msgpack/unpacker.c +136 -111
- data/ext/msgpack/unpacker.h +16 -13
- data/ext/msgpack/unpacker_class.c +86 -126
- data/ext/msgpack/unpacker_class.h +11 -0
- data/ext/msgpack/unpacker_ext_registry.c +40 -28
- data/ext/msgpack/unpacker_ext_registry.h +21 -18
- data/lib/msgpack/bigint.rb +69 -0
- data/lib/msgpack/buffer.rb +9 -0
- data/lib/msgpack/factory.rb +140 -10
- data/lib/msgpack/packer.rb +10 -1
- data/lib/msgpack/symbol.rb +21 -4
- data/lib/msgpack/time.rb +1 -1
- data/lib/msgpack/unpacker.rb +14 -1
- data/lib/msgpack/version.rb +1 -1
- data/lib/msgpack.rb +6 -7
- data/msgpack.gemspec +8 -5
- metadata +37 -82
- data/.gitignore +0 -23
- data/.rubocop.yml +0 -36
- data/.travis.yml +0 -39
- data/Gemfile +0 -9
- data/Rakefile +0 -71
- data/appveyor.yml +0 -18
- data/bench/pack.rb +0 -23
- data/bench/pack_log.rb +0 -33
- data/bench/pack_log_long.rb +0 -65
- data/bench/pack_symbols.rb +0 -28
- data/bench/run.sh +0 -14
- data/bench/run_long.sh +0 -35
- data/bench/run_symbols.sh +0 -26
- data/bench/unpack.rb +0 -21
- data/bench/unpack_log.rb +0 -34
- data/bench/unpack_log_long.rb +0 -67
- data/doclib/msgpack/buffer.rb +0 -193
- data/doclib/msgpack/core_ext.rb +0 -101
- data/doclib/msgpack/error.rb +0 -19
- data/doclib/msgpack/extension_value.rb +0 -9
- data/doclib/msgpack/factory.rb +0 -101
- data/doclib/msgpack/packer.rb +0 -208
- data/doclib/msgpack/time.rb +0 -22
- data/doclib/msgpack/timestamp.rb +0 -44
- data/doclib/msgpack/unpacker.rb +0 -183
- data/doclib/msgpack.rb +0 -87
- data/msgpack.org.md +0 -46
- data/spec/cases.json +0 -1
- data/spec/cases.msg +0 -0
- data/spec/cases_compact.msg +0 -0
- data/spec/cases_spec.rb +0 -39
- data/spec/cruby/buffer_io_spec.rb +0 -255
- data/spec/cruby/buffer_packer.rb +0 -29
- data/spec/cruby/buffer_spec.rb +0 -575
- data/spec/cruby/buffer_unpacker.rb +0 -19
- data/spec/cruby/unpacker_spec.rb +0 -70
- data/spec/ext_value_spec.rb +0 -99
- data/spec/exttypes.rb +0 -51
- data/spec/factory_spec.rb +0 -367
- data/spec/format_spec.rb +0 -301
- data/spec/jruby/benchmarks/shootout_bm.rb +0 -73
- data/spec/jruby/benchmarks/symbolize_keys_bm.rb +0 -25
- data/spec/jruby/unpacker_spec.rb +0 -186
- data/spec/msgpack_spec.rb +0 -214
- data/spec/pack_spec.rb +0 -61
- data/spec/packer_spec.rb +0 -557
- data/spec/random_compat.rb +0 -24
- data/spec/spec_helper.rb +0 -55
- data/spec/timestamp_spec.rb +0 -121
- data/spec/unpack_spec.rb +0 -57
- data/spec/unpacker_spec.rb +0 -819
    
        data/ext/msgpack/unpacker.c
    CHANGED
    
    | @@ -19,43 +19,55 @@ | |
| 19 19 | 
             
            #include "unpacker.h"
         | 
| 20 20 | 
             
            #include "rmem.h"
         | 
| 21 21 | 
             
            #include "extension_value_class.h"
         | 
| 22 | 
            +
            #include <assert.h>
         | 
| 23 | 
            +
            #include <limits.h>
         | 
| 22 24 |  | 
| 23 | 
            -
            #if !defined( | 
| 24 | 
            -
             | 
| 25 | 
            -
            #define UNPACKER_STACK_RMEM
         | 
| 25 | 
            +
            #if !defined(HAVE_RB_PROC_CALL_WITH_BLOCK)
         | 
| 26 | 
            +
            #define rb_proc_call_with_block(recv, argc, argv, block) rb_funcallv(recv, rb_intern("call"), argc, argv)
         | 
| 26 27 | 
             
            #endif
         | 
| 27 28 |  | 
| 28 29 | 
             
            static int RAW_TYPE_STRING = 256;
         | 
| 29 30 | 
             
            static int RAW_TYPE_BINARY = 257;
         | 
| 31 | 
            +
            static int16_t INITIAL_BUFFER_CAPACITY_MAX = SHRT_MAX;
         | 
| 30 32 |  | 
| 31 | 
            -
            static ID s_call;
         | 
| 32 | 
            -
             | 
| 33 | 
            -
            #ifdef UNPACKER_STACK_RMEM
         | 
| 34 33 | 
             
            static msgpack_rmem_t s_stack_rmem;
         | 
| 35 | 
            -
            #endif
         | 
| 36 34 |  | 
| 37 | 
            -
             | 
| 35 | 
            +
            #if !defined(HAVE_RB_HASH_NEW_CAPA)
         | 
| 36 | 
            +
            static inline VALUE rb_hash_new_capa(long capa)
         | 
| 38 37 | 
             
            {
         | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 38 | 
            +
              return rb_hash_new();
         | 
| 39 | 
            +
            }
         | 
| 41 40 | 
             
            #endif
         | 
| 42 41 |  | 
| 43 | 
            -
             | 
| 42 | 
            +
            static inline int16_t initial_buffer_size(long size)
         | 
| 43 | 
            +
            {
         | 
| 44 | 
            +
                return (size > INITIAL_BUFFER_CAPACITY_MAX) ? INITIAL_BUFFER_CAPACITY_MAX : size;
         | 
| 45 | 
            +
            }
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            void msgpack_unpacker_static_init(void)
         | 
| 48 | 
            +
            {
         | 
| 49 | 
            +
                assert(sizeof(msgpack_unpacker_stack_entry_t) * MSGPACK_UNPACKER_STACK_CAPACITY <= MSGPACK_RMEM_PAGE_SIZE);
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                msgpack_rmem_init(&s_stack_rmem);
         | 
| 44 52 | 
             
            }
         | 
| 45 53 |  | 
| 46 | 
            -
            void msgpack_unpacker_static_destroy()
         | 
| 54 | 
            +
            void msgpack_unpacker_static_destroy(void)
         | 
| 47 55 | 
             
            {
         | 
| 48 | 
            -
            #ifdef UNPACKER_STACK_RMEM
         | 
| 49 56 | 
             
                msgpack_rmem_destroy(&s_stack_rmem);
         | 
| 50 | 
            -
            #endif
         | 
| 51 57 | 
             
            }
         | 
| 52 58 |  | 
| 53 59 | 
             
            #define HEAD_BYTE_REQUIRED 0xc1
         | 
| 54 60 |  | 
| 61 | 
            +
            static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
         | 
| 62 | 
            +
                msgpack_unpacker_stack_t *stack = ZALLOC(msgpack_unpacker_stack_t);
         | 
| 63 | 
            +
                stack->capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
         | 
| 64 | 
            +
                stack->data = msgpack_rmem_alloc(&s_stack_rmem);
         | 
| 65 | 
            +
                /*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
         | 
| 66 | 
            +
                return stack;
         | 
| 67 | 
            +
            }
         | 
| 68 | 
            +
             | 
| 55 69 | 
             
            void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
         | 
| 56 70 | 
             
            {
         | 
| 57 | 
            -
                memset(uk, 0, sizeof(msgpack_unpacker_t));
         | 
| 58 | 
            -
             | 
| 59 71 | 
             
                msgpack_buffer_init(UNPACKER_BUFFER_(uk));
         | 
| 60 72 |  | 
| 61 73 | 
             
                uk->head_byte = HEAD_BYTE_REQUIRED;
         | 
| @@ -63,42 +75,44 @@ void _msgpack_unpacker_init(msgpack_unpacker_t* uk) | |
| 63 75 | 
             
                uk->last_object = Qnil;
         | 
| 64 76 | 
             
                uk->reading_raw = Qnil;
         | 
| 65 77 |  | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
                 | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
                 | 
| 78 | 
            +
                uk->stack = _msgpack_unpacker_new_stack();
         | 
| 79 | 
            +
            }
         | 
| 80 | 
            +
             | 
| 81 | 
            +
            static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
         | 
| 82 | 
            +
                if (!msgpack_rmem_free(&s_stack_rmem, stack->data)) {
         | 
| 83 | 
            +
                    rb_bug("Failed to free an rmem pointer, memory leak?");
         | 
| 84 | 
            +
                }
         | 
| 85 | 
            +
                xfree(stack);
         | 
| 74 86 | 
             
            }
         | 
| 75 87 |  | 
| 76 88 | 
             
            void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
         | 
| 77 89 | 
             
            {
         | 
| 78 | 
            -
             | 
| 79 | 
            -
                msgpack_rmem_free(&s_stack_rmem, uk->stack);
         | 
| 80 | 
            -
            #else
         | 
| 81 | 
            -
                xfree(uk->stack);
         | 
| 82 | 
            -
            #endif
         | 
| 83 | 
            -
             | 
| 90 | 
            +
                _msgpack_unpacker_free_stack(uk->stack);
         | 
| 84 91 | 
             
                msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
         | 
| 85 92 | 
             
            }
         | 
| 86 93 |  | 
| 94 | 
            +
            void msgpack_unpacker_mark_stack(msgpack_unpacker_stack_t* stack)
         | 
| 95 | 
            +
            {
         | 
| 96 | 
            +
                while (stack) {
         | 
| 97 | 
            +
                    msgpack_unpacker_stack_entry_t* s = stack->data;
         | 
| 98 | 
            +
                    msgpack_unpacker_stack_entry_t* send = stack->data + stack->depth;
         | 
| 99 | 
            +
                    for(; s < send; s++) {
         | 
| 100 | 
            +
                        rb_gc_mark(s->object);
         | 
| 101 | 
            +
                        rb_gc_mark(s->key);
         | 
| 102 | 
            +
                    }
         | 
| 103 | 
            +
                    stack = stack->parent;
         | 
| 104 | 
            +
                }
         | 
| 105 | 
            +
            }
         | 
| 106 | 
            +
             | 
| 87 107 | 
             
            void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
         | 
| 88 108 | 
             
            {
         | 
| 89 109 | 
             
                rb_gc_mark(uk->last_object);
         | 
| 90 110 | 
             
                rb_gc_mark(uk->reading_raw);
         | 
| 91 | 
            -
             | 
| 92 | 
            -
                msgpack_unpacker_stack_t* s = uk->stack;
         | 
| 93 | 
            -
                msgpack_unpacker_stack_t* send = uk->stack + uk->stack_depth;
         | 
| 94 | 
            -
                for(; s < send; s++) {
         | 
| 95 | 
            -
                    rb_gc_mark(s->object);
         | 
| 96 | 
            -
                    rb_gc_mark(s->key);
         | 
| 97 | 
            -
                }
         | 
| 98 | 
            -
             | 
| 111 | 
            +
                msgpack_unpacker_mark_stack(uk->stack);
         | 
| 99 112 | 
             
                /* See MessagePack_Buffer_wrap */
         | 
| 100 113 | 
             
                /* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
         | 
| 101 114 | 
             
                rb_gc_mark(uk->buffer_ref);
         | 
| 115 | 
            +
                rb_gc_mark(uk->self);
         | 
| 102 116 | 
             
            }
         | 
| 103 117 |  | 
| 104 118 | 
             
            void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
         | 
| @@ -107,9 +121,8 @@ void _msgpack_unpacker_reset(msgpack_unpacker_t* uk) | |
| 107 121 |  | 
| 108 122 | 
             
                uk->head_byte = HEAD_BYTE_REQUIRED;
         | 
| 109 123 |  | 
| 110 | 
            -
                /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk-> | 
| 111 | 
            -
                uk-> | 
| 112 | 
            -
             | 
| 124 | 
            +
                /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack->depth);*/
         | 
| 125 | 
            +
                uk->stack->depth = 0;
         | 
| 113 126 | 
             
                uk->last_object = Qnil;
         | 
| 114 127 | 
             
                uk->reading_raw = Qnil;
         | 
| 115 128 | 
             
                uk->reading_raw_remaining = 0;
         | 
| @@ -151,16 +164,34 @@ static inline int object_complete(msgpack_unpacker_t* uk, VALUE object) | |
| 151 164 | 
             
                return PRIMITIVE_OBJECT_COMPLETE;
         | 
| 152 165 | 
             
            }
         | 
| 153 166 |  | 
| 167 | 
            +
            static inline int object_complete_symbol(msgpack_unpacker_t* uk, VALUE object)
         | 
| 168 | 
            +
            {
         | 
| 169 | 
            +
                uk->last_object = object;
         | 
| 170 | 
            +
                reset_head_byte(uk);
         | 
| 171 | 
            +
                return PRIMITIVE_OBJECT_COMPLETE;
         | 
| 172 | 
            +
            }
         | 
| 173 | 
            +
             | 
| 154 174 | 
             
            static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALUE str)
         | 
| 155 175 | 
             
            {
         | 
| 156 | 
            -
                 | 
| 176 | 
            +
                if (uk->optimized_symbol_ext_type && ext_type == uk->symbol_ext_type) {
         | 
| 177 | 
            +
                    if (RB_UNLIKELY(NIL_P(str))) { // empty extension is returned as Qnil
         | 
| 178 | 
            +
                        return object_complete_symbol(uk, ID2SYM(rb_intern3("", 0, rb_utf8_encoding())));
         | 
| 179 | 
            +
                    }
         | 
| 180 | 
            +
                    return object_complete_symbol(uk, rb_str_intern(str));
         | 
| 181 | 
            +
                }
         | 
| 182 | 
            +
             | 
| 183 | 
            +
                int ext_flags;
         | 
| 184 | 
            +
                VALUE proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, ext_type, &ext_flags);
         | 
| 185 | 
            +
             | 
| 157 186 | 
             
                if(proc != Qnil) {
         | 
| 158 | 
            -
                    VALUE obj | 
| 187 | 
            +
                    VALUE obj;
         | 
| 188 | 
            +
                    VALUE arg = (str == Qnil ? rb_str_buf_new(0) : str);
         | 
| 189 | 
            +
                    obj = rb_proc_call_with_block(proc, 1, &arg, Qnil);
         | 
| 159 190 | 
             
                    return object_complete(uk, obj);
         | 
| 160 191 | 
             
                }
         | 
| 161 192 |  | 
| 162 193 | 
             
                if(uk->allow_unknown_ext) {
         | 
| 163 | 
            -
                    VALUE obj = MessagePack_ExtensionValue_new(ext_type, str);
         | 
| 194 | 
            +
                    VALUE obj = MessagePack_ExtensionValue_new(ext_type, str == Qnil ? rb_str_buf_new(0) : str);
         | 
| 164 195 | 
             
                    return object_complete(uk, obj);
         | 
| 165 196 | 
             
                }
         | 
| 166 197 |  | 
| @@ -168,37 +199,37 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU | |
| 168 199 | 
             
            }
         | 
| 169 200 |  | 
| 170 201 | 
             
            /* stack funcs */
         | 
| 171 | 
            -
            static inline  | 
| 202 | 
            +
            static inline msgpack_unpacker_stack_entry_t* _msgpack_unpacker_stack_entry_top(msgpack_unpacker_t* uk)
         | 
| 172 203 | 
             
            {
         | 
| 173 | 
            -
                return &uk->stack[uk-> | 
| 204 | 
            +
                return &uk->stack->data[uk->stack->depth-1];
         | 
| 174 205 | 
             
            }
         | 
| 175 206 |  | 
| 176 207 | 
             
            static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stack_type_t type, size_t count, VALUE object)
         | 
| 177 208 | 
             
            {
         | 
| 178 209 | 
             
                reset_head_byte(uk);
         | 
| 179 210 |  | 
| 180 | 
            -
                if(uk-> | 
| 211 | 
            +
                if(uk->stack->capacity - uk->stack->depth <= 0) {
         | 
| 181 212 | 
             
                    return PRIMITIVE_STACK_TOO_DEEP;
         | 
| 182 213 | 
             
                }
         | 
| 183 214 |  | 
| 184 | 
            -
                 | 
| 215 | 
            +
                msgpack_unpacker_stack_entry_t* next = &uk->stack->data[uk->stack->depth];
         | 
| 185 216 | 
             
                next->count = count;
         | 
| 186 217 | 
             
                next->type = type;
         | 
| 187 218 | 
             
                next->object = object;
         | 
| 188 219 | 
             
                next->key = Qnil;
         | 
| 189 220 |  | 
| 190 | 
            -
                uk-> | 
| 221 | 
            +
                uk->stack->depth++;
         | 
| 191 222 | 
             
                return PRIMITIVE_CONTAINER_START;
         | 
| 192 223 | 
             
            }
         | 
| 193 224 |  | 
| 194 225 | 
             
            static inline VALUE msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
         | 
| 195 226 | 
             
            {
         | 
| 196 | 
            -
                return --uk-> | 
| 227 | 
            +
                return --uk->stack->depth;
         | 
| 197 228 | 
             
            }
         | 
| 198 229 |  | 
| 199 230 | 
             
            static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
         | 
| 200 231 | 
             
            {
         | 
| 201 | 
            -
                return uk-> | 
| 232 | 
            +
                return uk->stack->depth == 0;
         | 
| 202 233 | 
             
            }
         | 
| 203 234 |  | 
| 204 235 | 
             
            #ifdef USE_CASE_RANGE
         | 
| @@ -226,8 +257,8 @@ static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk) | |
| 226 257 |  | 
| 227 258 | 
             
            static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
         | 
| 228 259 | 
             
            {
         | 
| 229 | 
            -
                if(uk-> | 
| 230 | 
            -
                     | 
| 260 | 
            +
                if(uk->stack->depth > 0) {
         | 
| 261 | 
            +
                    msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
         | 
| 231 262 | 
             
                    if(top->type == STACK_TYPE_MAP_KEY) {
         | 
| 232 263 | 
             
                        return true;
         | 
| 233 264 | 
             
                    }
         | 
| @@ -270,25 +301,50 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type) | |
| 270 301 | 
             
            {
         | 
| 271 302 | 
             
                /* assuming uk->reading_raw == Qnil */
         | 
| 272 303 |  | 
| 304 | 
            +
                int ext_flags;
         | 
| 305 | 
            +
                VALUE proc;
         | 
| 306 | 
            +
             | 
| 307 | 
            +
                if(!(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY)) {
         | 
| 308 | 
            +
                    proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, raw_type, &ext_flags);
         | 
| 309 | 
            +
                    if(proc != Qnil && ext_flags & MSGPACK_EXT_RECURSIVE) {
         | 
| 310 | 
            +
                        VALUE obj;
         | 
| 311 | 
            +
                        uk->last_object = Qnil;
         | 
| 312 | 
            +
                        reset_head_byte(uk);
         | 
| 313 | 
            +
                        uk->reading_raw_remaining = 0;
         | 
| 314 | 
            +
             | 
| 315 | 
            +
                        msgpack_unpacker_stack_t* child_stack = _msgpack_unpacker_new_stack();
         | 
| 316 | 
            +
                        child_stack->parent = uk->stack;
         | 
| 317 | 
            +
                        uk->stack = child_stack;
         | 
| 318 | 
            +
             | 
| 319 | 
            +
                        obj = rb_proc_call_with_block(proc, 1, &uk->self, Qnil);
         | 
| 320 | 
            +
             | 
| 321 | 
            +
                        uk->stack = child_stack->parent;
         | 
| 322 | 
            +
                        _msgpack_unpacker_free_stack(child_stack);
         | 
| 323 | 
            +
             | 
| 324 | 
            +
                        return object_complete(uk, obj);
         | 
| 325 | 
            +
                    }
         | 
| 326 | 
            +
                }
         | 
| 327 | 
            +
             | 
| 273 328 | 
             
                /* try optimized read */
         | 
| 274 329 | 
             
                size_t length = uk->reading_raw_remaining;
         | 
| 275 330 | 
             
                if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
         | 
| 276 | 
            -
                    /* don't use zerocopy for hash keys but get a frozen string directly
         | 
| 277 | 
            -
                     * because rb_hash_aset freezes keys and it causes copying */
         | 
| 278 | 
            -
                    bool will_freeze = uk->freeze || is_reading_map_key(uk);
         | 
| 279 | 
            -
                    VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
         | 
| 280 331 | 
             
                    int ret;
         | 
| 281 | 
            -
                    if( | 
| 282 | 
            -
                         | 
| 332 | 
            +
                    if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type) || (uk->symbolize_keys && is_reading_map_key(uk))) {
         | 
| 333 | 
            +
                        VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, raw_type != RAW_TYPE_BINARY);
         | 
| 334 | 
            +
                        ret = object_complete_symbol(uk, symbol);
         | 
| 283 335 | 
             
                    } else {
         | 
| 284 | 
            -
                         | 
| 285 | 
            -
             | 
| 286 | 
            -
             | 
| 287 | 
            -
             | 
| 288 | 
            -
             | 
| 289 | 
            -
             | 
| 336 | 
            +
                        bool will_freeze = uk->freeze;
         | 
| 337 | 
            +
                        if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
         | 
| 338 | 
            +
                           /* don't use zerocopy for hash keys but get a frozen string directly
         | 
| 339 | 
            +
                            * because rb_hash_aset freezes keys and it causes copying */
         | 
| 340 | 
            +
                            will_freeze = will_freeze || is_reading_map_key(uk);
         | 
| 341 | 
            +
                            VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
         | 
| 342 | 
            +
                            ret = object_complete(uk, string);
         | 
| 343 | 
            +
                        } else {
         | 
| 344 | 
            +
                            VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, false, false);
         | 
| 345 | 
            +
                            ret = object_complete_ext(uk, raw_type, string);
         | 
| 346 | 
            +
                        }
         | 
| 290 347 | 
             
                    }
         | 
| 291 | 
            -
            # endif
         | 
| 292 348 | 
             
                    uk->reading_raw_remaining = 0;
         | 
| 293 349 | 
             
                    return ret;
         | 
| 294 350 | 
             
                }
         | 
| @@ -317,9 +373,6 @@ static int read_primitive(msgpack_unpacker_t* uk) | |
| 317 373 |  | 
| 318 374 | 
             
                SWITCH_RANGE(b, 0xa0, 0xbf)  // FixRaw / fixstr
         | 
| 319 375 | 
             
                    int count = b & 0x1f;
         | 
| 320 | 
            -
                    if(count == 0) {
         | 
| 321 | 
            -
                        return object_complete(uk, rb_utf8_str_new_static("", 0));
         | 
| 322 | 
            -
                    }
         | 
| 323 376 | 
             
                    /* read_raw_body_begin sets uk->reading_raw */
         | 
| 324 377 | 
             
                    uk->reading_raw_remaining = count;
         | 
| 325 378 | 
             
                    return read_raw_body_begin(uk, RAW_TYPE_STRING);
         | 
| @@ -329,14 +382,14 @@ static int read_primitive(msgpack_unpacker_t* uk) | |
| 329 382 | 
             
                    if(count == 0) {
         | 
| 330 383 | 
             
                        return object_complete(uk, rb_ary_new());
         | 
| 331 384 | 
             
                    }
         | 
| 332 | 
            -
                    return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
         | 
| 385 | 
            +
                    return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
         | 
| 333 386 |  | 
| 334 387 | 
             
                SWITCH_RANGE(b, 0x80, 0x8f)  // FixMap
         | 
| 335 388 | 
             
                    int count = b & 0x0f;
         | 
| 336 389 | 
             
                    if(count == 0) {
         | 
| 337 390 | 
             
                        return object_complete(uk, rb_hash_new());
         | 
| 338 391 | 
             
                    }
         | 
| 339 | 
            -
                    return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2,  | 
| 392 | 
            +
                    return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
         | 
| 340 393 |  | 
| 341 394 | 
             
                SWITCH_RANGE(b, 0xc0, 0xdf)  // Variable
         | 
| 342 395 | 
             
                    switch(b) {
         | 
| @@ -357,7 +410,7 @@ static int read_primitive(msgpack_unpacker_t* uk) | |
| 357 410 | 
             
                            uint8_t length = cb->u8;
         | 
| 358 411 | 
             
                            int ext_type = (signed char) cb->buffer[1];
         | 
| 359 412 | 
             
                            if(length == 0) {
         | 
| 360 | 
            -
                                return object_complete_ext(uk, ext_type,  | 
| 413 | 
            +
                                return object_complete_ext(uk, ext_type, Qnil);
         | 
| 361 414 | 
             
                            }
         | 
| 362 415 | 
             
                            uk->reading_raw_remaining = length;
         | 
| 363 416 | 
             
                            return read_raw_body_begin(uk, ext_type);
         | 
| @@ -369,7 +422,7 @@ static int read_primitive(msgpack_unpacker_t* uk) | |
| 369 422 | 
             
                            uint16_t length = _msgpack_be16(cb->u16);
         | 
| 370 423 | 
             
                            int ext_type = (signed char) cb->buffer[2];
         | 
| 371 424 | 
             
                            if(length == 0) {
         | 
| 372 | 
            -
                                return object_complete_ext(uk, ext_type,  | 
| 425 | 
            +
                                return object_complete_ext(uk, ext_type, Qnil);
         | 
| 373 426 | 
             
                            }
         | 
| 374 427 | 
             
                            uk->reading_raw_remaining = length;
         | 
| 375 428 | 
             
                            return read_raw_body_begin(uk, ext_type);
         | 
| @@ -381,7 +434,7 @@ static int read_primitive(msgpack_unpacker_t* uk) | |
| 381 434 | 
             
                            uint32_t length = _msgpack_be32(cb->u32);
         | 
| 382 435 | 
             
                            int ext_type = (signed char) cb->buffer[4];
         | 
| 383 436 | 
             
                            if(length == 0) {
         | 
| 384 | 
            -
                                return object_complete_ext(uk, ext_type,  | 
| 437 | 
            +
                                return object_complete_ext(uk, ext_type, Qnil);
         | 
| 385 438 | 
             
                            }
         | 
| 386 439 | 
             
                            uk->reading_raw_remaining = length;
         | 
| 387 440 | 
             
                            return read_raw_body_begin(uk, ext_type);
         | 
| @@ -419,7 +472,7 @@ static int read_primitive(msgpack_unpacker_t* uk) | |
| 419 472 | 
             
                        {
         | 
| 420 473 | 
             
                            READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
         | 
| 421 474 | 
             
                            uint32_t u32 = _msgpack_be32(cb->u32);
         | 
| 422 | 
            -
                            return object_complete(uk, ULONG2NUM( | 
| 475 | 
            +
                            return object_complete(uk, ULONG2NUM(u32)); // long at least 32 bits
         | 
| 423 476 | 
             
                        }
         | 
| 424 477 |  | 
| 425 478 | 
             
                    case 0xcf:  // unsigned int 64
         | 
| @@ -447,7 +500,7 @@ static int read_primitive(msgpack_unpacker_t* uk) | |
| 447 500 | 
             
                        {
         | 
| 448 501 | 
             
                            READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
         | 
| 449 502 | 
             
                            int32_t i32 = _msgpack_be32(cb->i32);
         | 
| 450 | 
            -
                            return object_complete(uk, LONG2NUM( | 
| 503 | 
            +
                            return object_complete(uk, LONG2NUM(i32)); // long at least 32 bits
         | 
| 451 504 | 
             
                        }
         | 
| 452 505 |  | 
| 453 506 | 
             
                    case 0xd3:  // signed int 64
         | 
| @@ -502,9 +555,6 @@ static int read_primitive(msgpack_unpacker_t* uk) | |
| 502 555 | 
             
                        {
         | 
| 503 556 | 
             
                            READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
         | 
| 504 557 | 
             
                            uint8_t count = cb->u8;
         | 
| 505 | 
            -
                            if(count == 0) {
         | 
| 506 | 
            -
                                return object_complete(uk, rb_utf8_str_new_static("", 0));
         | 
| 507 | 
            -
                            }
         | 
| 508 558 | 
             
                            /* read_raw_body_begin sets uk->reading_raw */
         | 
| 509 559 | 
             
                            uk->reading_raw_remaining = count;
         | 
| 510 560 | 
             
                            return read_raw_body_begin(uk, RAW_TYPE_STRING);
         | 
| @@ -514,9 +564,6 @@ static int read_primitive(msgpack_unpacker_t* uk) | |
| 514 564 | 
             
                        {
         | 
| 515 565 | 
             
                            READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
         | 
| 516 566 | 
             
                            uint16_t count = _msgpack_be16(cb->u16);
         | 
| 517 | 
            -
                            if(count == 0) {
         | 
| 518 | 
            -
                                return object_complete(uk, rb_utf8_str_new_static("", 0));
         | 
| 519 | 
            -
                            }
         | 
| 520 567 | 
             
                            /* read_raw_body_begin sets uk->reading_raw */
         | 
| 521 568 | 
             
                            uk->reading_raw_remaining = count;
         | 
| 522 569 | 
             
                            return read_raw_body_begin(uk, RAW_TYPE_STRING);
         | 
| @@ -526,9 +573,6 @@ static int read_primitive(msgpack_unpacker_t* uk) | |
| 526 573 | 
             
                        {
         | 
| 527 574 | 
             
                            READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
         | 
| 528 575 | 
             
                            uint32_t count = _msgpack_be32(cb->u32);
         | 
| 529 | 
            -
                            if(count == 0) {
         | 
| 530 | 
            -
                                return object_complete(uk, rb_utf8_str_new_static("", 0));
         | 
| 531 | 
            -
                            }
         | 
| 532 576 | 
             
                            /* read_raw_body_begin sets uk->reading_raw */
         | 
| 533 577 | 
             
                            uk->reading_raw_remaining = count;
         | 
| 534 578 | 
             
                            return read_raw_body_begin(uk, RAW_TYPE_STRING);
         | 
| @@ -538,9 +582,6 @@ static int read_primitive(msgpack_unpacker_t* uk) | |
| 538 582 | 
             
                        {
         | 
| 539 583 | 
             
                            READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
         | 
| 540 584 | 
             
                            uint8_t count = cb->u8;
         | 
| 541 | 
            -
                            if(count == 0) {
         | 
| 542 | 
            -
                                return object_complete(uk, rb_str_new_static("", 0));
         | 
| 543 | 
            -
                            }
         | 
| 544 585 | 
             
                            /* read_raw_body_begin sets uk->reading_raw */
         | 
| 545 586 | 
             
                            uk->reading_raw_remaining = count;
         | 
| 546 587 | 
             
                            return read_raw_body_begin(uk, RAW_TYPE_BINARY);
         | 
| @@ -550,9 +591,6 @@ static int read_primitive(msgpack_unpacker_t* uk) | |
| 550 591 | 
             
                        {
         | 
| 551 592 | 
             
                            READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
         | 
| 552 593 | 
             
                            uint16_t count = _msgpack_be16(cb->u16);
         | 
| 553 | 
            -
                            if(count == 0) {
         | 
| 554 | 
            -
                                return object_complete(uk, rb_str_new_static("", 0));
         | 
| 555 | 
            -
                            }
         | 
| 556 594 | 
             
                            /* read_raw_body_begin sets uk->reading_raw */
         | 
| 557 595 | 
             
                            uk->reading_raw_remaining = count;
         | 
| 558 596 | 
             
                            return read_raw_body_begin(uk, RAW_TYPE_BINARY);
         | 
| @@ -562,9 +600,6 @@ static int read_primitive(msgpack_unpacker_t* uk) | |
| 562 600 | 
             
                        {
         | 
| 563 601 | 
             
                            READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
         | 
| 564 602 | 
             
                            uint32_t count = _msgpack_be32(cb->u32);
         | 
| 565 | 
            -
                            if(count == 0) {
         | 
| 566 | 
            -
                                return object_complete(uk, rb_str_new_static("", 0));
         | 
| 567 | 
            -
                            }
         | 
| 568 603 | 
             
                            /* read_raw_body_begin sets uk->reading_raw */
         | 
| 569 604 | 
             
                            uk->reading_raw_remaining = count;
         | 
| 570 605 | 
             
                            return read_raw_body_begin(uk, RAW_TYPE_BINARY);
         | 
| @@ -577,7 +612,7 @@ static int read_primitive(msgpack_unpacker_t* uk) | |
| 577 612 | 
             
                            if(count == 0) {
         | 
| 578 613 | 
             
                                return object_complete(uk, rb_ary_new());
         | 
| 579 614 | 
             
                            }
         | 
| 580 | 
            -
                            return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
         | 
| 615 | 
            +
                            return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
         | 
| 581 616 | 
             
                        }
         | 
| 582 617 |  | 
| 583 618 | 
             
                    case 0xdd:  // array 32
         | 
| @@ -587,7 +622,7 @@ static int read_primitive(msgpack_unpacker_t* uk) | |
| 587 622 | 
             
                            if(count == 0) {
         | 
| 588 623 | 
             
                                return object_complete(uk, rb_ary_new());
         | 
| 589 624 | 
             
                            }
         | 
| 590 | 
            -
                            return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
         | 
| 625 | 
            +
                            return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
         | 
| 591 626 | 
             
                        }
         | 
| 592 627 |  | 
| 593 628 | 
             
                    case 0xde:  // map 16
         | 
| @@ -597,7 +632,7 @@ static int read_primitive(msgpack_unpacker_t* uk) | |
| 597 632 | 
             
                            if(count == 0) {
         | 
| 598 633 | 
             
                                return object_complete(uk, rb_hash_new());
         | 
| 599 634 | 
             
                            }
         | 
| 600 | 
            -
                            return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2,  | 
| 635 | 
            +
                            return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
         | 
| 601 636 | 
             
                        }
         | 
| 602 637 |  | 
| 603 638 | 
             
                    case 0xdf:  // map 32
         | 
| @@ -607,7 +642,7 @@ static int read_primitive(msgpack_unpacker_t* uk) | |
| 607 642 | 
             
                            if(count == 0) {
         | 
| 608 643 | 
             
                                return object_complete(uk, rb_hash_new());
         | 
| 609 644 | 
             
                            }
         | 
| 610 | 
            -
                            return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2,  | 
| 645 | 
            +
                            return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
         | 
| 611 646 | 
             
                        }
         | 
| 612 647 |  | 
| 613 648 | 
             
                    default:
         | 
| @@ -694,7 +729,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth) | |
| 694 729 |  | 
| 695 730 | 
             
                    container_completed:
         | 
| 696 731 | 
             
                    {
         | 
| 697 | 
            -
                         | 
| 732 | 
            +
                        msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
         | 
| 698 733 | 
             
                        switch(top->type) {
         | 
| 699 734 | 
             
                        case STACK_TYPE_ARRAY:
         | 
| 700 735 | 
             
                            rb_ary_push(top->object, uk->last_object);
         | 
| @@ -705,18 +740,8 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth) | |
| 705 740 | 
             
                            break;
         | 
| 706 741 | 
             
                        case STACK_TYPE_MAP_VALUE:
         | 
| 707 742 | 
             
                            if(uk->symbolize_keys && rb_type(top->key) == T_STRING) {
         | 
| 708 | 
            -
                                /* here uses  | 
| 709 | 
            -
            #ifdef HAVE_RB_STR_INTERN
         | 
| 710 | 
            -
                                /* rb_str_intern is added since MRI 2.2.0 */
         | 
| 743 | 
            +
                                /* here uses rb_str_intern instead of rb_intern so that Ruby VM can GC unused symbols */
         | 
| 711 744 | 
             
                                rb_hash_aset(top->object, rb_str_intern(top->key), uk->last_object);
         | 
| 712 | 
            -
            #else
         | 
| 713 | 
            -
            #ifndef HAVE_RB_INTERN_STR
         | 
| 714 | 
            -
                                /* MRI 1.8 doesn't have rb_intern_str or rb_intern2 */
         | 
| 715 | 
            -
                                rb_hash_aset(top->object, ID2SYM(rb_intern(RSTRING_PTR(top->key))), uk->last_object);
         | 
| 716 | 
            -
            #else
         | 
| 717 | 
            -
                                rb_hash_aset(top->object, ID2SYM(rb_intern_str(top->key)), uk->last_object);
         | 
| 718 | 
            -
            #endif
         | 
| 719 | 
            -
            #endif
         | 
| 720 745 | 
             
                            } else {
         | 
| 721 746 | 
             
                                rb_hash_aset(top->object, top->key, uk->last_object);
         | 
| 722 747 | 
             
                            }
         | 
| @@ -754,7 +779,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth) | |
| 754 779 |  | 
| 755 780 | 
             
                    container_completed:
         | 
| 756 781 | 
             
                    {
         | 
| 757 | 
            -
                         | 
| 782 | 
            +
                        msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
         | 
| 758 783 |  | 
| 759 784 | 
             
                        /* this section optimized out */
         | 
| 760 785 | 
             
                        // TODO object_complete still creates objects which should be optimized out
         | 
    
        data/ext/msgpack/unpacker.h
    CHANGED
    
    | @@ -21,12 +21,11 @@ | |
| 21 21 | 
             
            #include "buffer.h"
         | 
| 22 22 | 
             
            #include "unpacker_ext_registry.h"
         | 
| 23 23 |  | 
| 24 | 
            -
            #ifndef MSGPACK_UNPACKER_STACK_CAPACITY
         | 
| 25 24 | 
             
            #define MSGPACK_UNPACKER_STACK_CAPACITY 128
         | 
| 26 | 
            -
            #endif
         | 
| 27 25 |  | 
| 28 26 | 
             
            struct msgpack_unpacker_t;
         | 
| 29 27 | 
             
            typedef struct msgpack_unpacker_t msgpack_unpacker_t;
         | 
| 28 | 
            +
            typedef struct msgpack_unpacker_stack_t msgpack_unpacker_stack_t;
         | 
| 30 29 |  | 
| 31 30 | 
             
            enum stack_type_t {
         | 
| 32 31 | 
             
                STACK_TYPE_ARRAY,
         | 
| @@ -39,19 +38,21 @@ typedef struct { | |
| 39 38 | 
             
                enum stack_type_t type;
         | 
| 40 39 | 
             
                VALUE object;
         | 
| 41 40 | 
             
                VALUE key;
         | 
| 42 | 
            -
            }  | 
| 41 | 
            +
            } msgpack_unpacker_stack_entry_t;
         | 
| 43 42 |  | 
| 44 | 
            -
             | 
| 43 | 
            +
            struct msgpack_unpacker_stack_t {
         | 
| 44 | 
            +
                size_t depth;
         | 
| 45 | 
            +
                size_t capacity;
         | 
| 46 | 
            +
                msgpack_unpacker_stack_entry_t *data;
         | 
| 47 | 
            +
                msgpack_unpacker_stack_t *parent;
         | 
| 48 | 
            +
            };
         | 
| 45 49 |  | 
| 46 50 | 
             
            struct msgpack_unpacker_t {
         | 
| 47 51 | 
             
                msgpack_buffer_t buffer;
         | 
| 48 | 
            -
             | 
| 52 | 
            +
                msgpack_unpacker_stack_t *stack;
         | 
| 49 53 | 
             
                unsigned int head_byte;
         | 
| 50 54 |  | 
| 51 | 
            -
                 | 
| 52 | 
            -
                size_t stack_depth;
         | 
| 53 | 
            -
                size_t stack_capacity;
         | 
| 54 | 
            -
             | 
| 55 | 
            +
                VALUE self;
         | 
| 55 56 | 
             
                VALUE last_object;
         | 
| 56 57 |  | 
| 57 58 | 
             
                VALUE reading_raw;
         | 
| @@ -60,12 +61,14 @@ struct msgpack_unpacker_t { | |
| 60 61 |  | 
| 61 62 | 
             
                VALUE buffer_ref;
         | 
| 62 63 |  | 
| 63 | 
            -
                msgpack_unpacker_ext_registry_t ext_registry;
         | 
| 64 | 
            +
                msgpack_unpacker_ext_registry_t *ext_registry;
         | 
| 64 65 |  | 
| 65 66 | 
             
                /* options */
         | 
| 66 67 | 
             
                bool symbolize_keys;
         | 
| 67 68 | 
             
                bool freeze;
         | 
| 68 69 | 
             
                bool allow_unknown_ext;
         | 
| 70 | 
            +
                bool optimized_symbol_ext_type;
         | 
| 71 | 
            +
                int symbol_ext_type;
         | 
| 69 72 | 
             
            };
         | 
| 70 73 |  | 
| 71 74 | 
             
            #define UNPACKER_BUFFER_(uk) (&(uk)->buffer)
         | 
| @@ -80,11 +83,11 @@ enum msgpack_unpacker_object_type { | |
| 80 83 | 
             
                TYPE_MAP,
         | 
| 81 84 | 
             
            };
         | 
| 82 85 |  | 
| 83 | 
            -
            void msgpack_unpacker_static_init();
         | 
| 86 | 
            +
            void msgpack_unpacker_static_init(void);
         | 
| 84 87 |  | 
| 85 | 
            -
            void msgpack_unpacker_static_destroy();
         | 
| 88 | 
            +
            void msgpack_unpacker_static_destroy(void);
         | 
| 86 89 |  | 
| 87 | 
            -
            void _msgpack_unpacker_init(msgpack_unpacker_t* | 
| 90 | 
            +
            void _msgpack_unpacker_init(msgpack_unpacker_t*);
         | 
| 88 91 |  | 
| 89 92 | 
             
            void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk);
         | 
| 90 93 |  |