oj 3.11.7 → 3.12.2
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/ext/oj/compat.c +32 -27
- data/ext/oj/custom.c +3 -15
- data/ext/oj/dump.c +39 -42
- data/ext/oj/dump_strict.c +1 -1
- data/ext/oj/hash.c +41 -4
- data/ext/oj/hash.h +2 -0
- data/ext/oj/mimic_json.c +6 -4
- data/ext/oj/object.c +33 -5
- data/ext/oj/oj.c +51 -3
- data/ext/oj/oj.h +2 -0
- data/ext/oj/parse.h +3 -0
- data/ext/oj/rails.c +2 -1
- data/ext/oj/scp.c +4 -16
- data/ext/oj/strict.c +67 -22
- data/ext/oj/wab.c +35 -18
- data/lib/oj/mimic.rb +2 -0
- data/lib/oj/version.rb +1 -1
- data/pages/Options.md +7 -1
- data/test/foo.rb +2 -9
- data/test/perf.rb +1 -1
- data/test/perf_scp.rb +11 -10
- data/test/perf_strict.rb +17 -23
- data/test/test_various.rb +2 -0
- metadata +3 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 89a87064f6668864cec4ab0c43892b4950c8ef7a9f7ea3da22f459af5bcd0083
         | 
| 4 | 
            +
              data.tar.gz: bc078e8b28d710a2194e2943343db687ec15d35d2556efff2f9e46936f3bb0b0
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 95cb66c13e871bf85a351348b0c458c53fe2cd4057886396a62b763386fafe5d99c97143151808eb70dd526b8f13740cd43e266805c6b3454eac1be6940897db
         | 
| 7 | 
            +
              data.tar.gz: '09e24c7ec1daf2c10850b071eb4060aed265db662a92a78439eee1746b22437396f3358f82d982e040874c0916af3c38def244e03416e4971c2c5649823ff7c2'
         | 
    
        data/ext/oj/compat.c
    CHANGED
    
    | @@ -23,14 +23,34 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c | |
| 23 23 | 
             
                    parent->classname = oj_strndup(str, len);
         | 
| 24 24 | 
             
                    parent->clen      = len;
         | 
| 25 25 | 
             
                } else {
         | 
| 26 | 
            -
                    volatile VALUE rstr =  | 
| 26 | 
            +
                    volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
         | 
| 27 27 |  | 
| 28 28 | 
             
                    if (Qundef == rkey) {
         | 
| 29 | 
            -
                         | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 29 | 
            +
                        if (Yes != pi->options.cache_keys) {
         | 
| 30 | 
            +
                            rkey = rb_str_new(key, klen);
         | 
| 31 | 
            +
                            rkey = oj_encode(rkey);
         | 
| 32 | 
            +
                            if (Yes == pi->options.sym_key) {
         | 
| 33 | 
            +
                                rkey = rb_str_intern(rkey);
         | 
| 34 | 
            +
                            }
         | 
| 35 | 
            +
                        } else {
         | 
| 36 | 
            +
                            VALUE *slot;
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                            if (Yes == pi->options.sym_key) {
         | 
| 39 | 
            +
                                if (Qnil == (rkey = oj_sym_hash_get(key, klen, &slot))) {
         | 
| 40 | 
            +
                                    rkey  = rb_str_new(key, klen);
         | 
| 41 | 
            +
                                    rkey  = oj_encode(rkey);
         | 
| 42 | 
            +
                                    rkey  = rb_str_intern(rkey);
         | 
| 43 | 
            +
                                    *slot = rkey;
         | 
| 44 | 
            +
                                    rb_gc_register_address(slot);
         | 
| 45 | 
            +
                                }
         | 
| 46 | 
            +
                            } else {
         | 
| 47 | 
            +
                                if (Qnil == (rkey = oj_str_hash_get(key, klen, &slot))) {
         | 
| 48 | 
            +
                                    rkey  = rb_str_new(key, klen);
         | 
| 49 | 
            +
                                    rkey  = oj_encode(rkey);
         | 
| 50 | 
            +
                                    *slot = rkey;
         | 
| 51 | 
            +
                                    rb_gc_register_address(slot);
         | 
| 52 | 
            +
                                }
         | 
| 53 | 
            +
                            }
         | 
| 34 54 | 
             
                        }
         | 
| 35 55 | 
             
                    }
         | 
| 36 56 | 
             
                    if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
         | 
| @@ -93,23 +113,9 @@ static void end_hash(struct _parseInfo *pi) { | |
| 93 113 | 
             
                }
         | 
| 94 114 | 
             
            }
         | 
| 95 115 |  | 
| 96 | 
            -
            static VALUE calc_hash_key(ParseInfo pi, Val parent) {
         | 
| 97 | 
            -
                volatile VALUE rkey = parent->key_val;
         | 
| 98 | 
            -
             | 
| 99 | 
            -
                if (Qundef == rkey) {
         | 
| 100 | 
            -
                    rkey = rb_str_new(parent->key, parent->klen);
         | 
| 101 | 
            -
                }
         | 
| 102 | 
            -
                rkey = oj_encode(rkey);
         | 
| 103 | 
            -
                if (Yes == pi->options.sym_key) {
         | 
| 104 | 
            -
                    rkey = rb_str_intern(rkey);
         | 
| 105 | 
            -
                }
         | 
| 106 | 
            -
                return rkey;
         | 
| 107 | 
            -
            }
         | 
| 108 | 
            -
             | 
| 109 116 | 
             
            static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
         | 
| 110 | 
            -
                volatile VALUE rstr =  | 
| 117 | 
            +
                volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
         | 
| 111 118 |  | 
| 112 | 
            -
                rstr = oj_encode(rstr);
         | 
| 113 119 | 
             
                if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
         | 
| 114 120 | 
             
                    VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
         | 
| 115 121 |  | 
| @@ -142,10 +148,10 @@ static void hash_set_num(struct _parseInfo *pi, Val parent, NumInfo ni) { | |
| 142 148 | 
             
                    rb_funcall(stack_peek(&pi->stack)->val,
         | 
| 143 149 | 
             
                               rb_intern("[]="),
         | 
| 144 150 | 
             
                               2,
         | 
| 145 | 
            -
                                | 
| 151 | 
            +
                               oj_calc_hash_key(pi, parent),
         | 
| 146 152 | 
             
                               rval);
         | 
| 147 153 | 
             
                } else {
         | 
| 148 | 
            -
                    rb_hash_aset(stack_peek(&pi->stack)->val,  | 
| 154 | 
            +
                    rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), rval);
         | 
| 149 155 | 
             
                }
         | 
| 150 156 | 
             
                if (Yes == pi->options.trace) {
         | 
| 151 157 | 
             
                    oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, rval);
         | 
| @@ -161,10 +167,10 @@ static void hash_set_value(ParseInfo pi, Val parent, VALUE value) { | |
| 161 167 | 
             
                    rb_funcall(stack_peek(&pi->stack)->val,
         | 
| 162 168 | 
             
                               rb_intern("[]="),
         | 
| 163 169 | 
             
                               2,
         | 
| 164 | 
            -
                                | 
| 170 | 
            +
                               oj_calc_hash_key(pi, parent),
         | 
| 165 171 | 
             
                               value);
         | 
| 166 172 | 
             
                } else {
         | 
| 167 | 
            -
                    rb_hash_aset(stack_peek(&pi->stack)->val,  | 
| 173 | 
            +
                    rb_hash_aset(stack_peek(&pi->stack)->val, oj_calc_hash_key(pi, parent), value);
         | 
| 168 174 | 
             
                }
         | 
| 169 175 | 
             
                if (Yes == pi->options.trace) {
         | 
| 170 176 | 
             
                    oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
         | 
| @@ -199,9 +205,8 @@ static void array_append_num(ParseInfo pi, NumInfo ni) { | |
| 199 205 | 
             
            }
         | 
| 200 206 |  | 
| 201 207 | 
             
            static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
         | 
| 202 | 
            -
                volatile VALUE rstr =  | 
| 208 | 
            +
                volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
         | 
| 203 209 |  | 
| 204 | 
            -
                rstr = oj_encode(rstr);
         | 
| 205 210 | 
             
                if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
         | 
| 206 211 | 
             
                    VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
         | 
| 207 212 |  | 
    
        data/ext/oj/custom.c
    CHANGED
    
    | @@ -955,6 +955,7 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c | |
| 955 955 | 
             
                        }
         | 
| 956 956 | 
             
                    }
         | 
| 957 957 | 
             
                } else {
         | 
| 958 | 
            +
            	//volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
         | 
| 958 959 | 
             
                    volatile VALUE rstr = rb_str_new(str, len);
         | 
| 959 960 |  | 
| 960 961 | 
             
                    if (Qundef == rkey) {
         | 
| @@ -1010,19 +1011,6 @@ static void end_hash(struct _parseInfo *pi) { | |
| 1010 1011 | 
             
                }
         | 
| 1011 1012 | 
             
            }
         | 
| 1012 1013 |  | 
| 1013 | 
            -
            static VALUE calc_hash_key(ParseInfo pi, Val parent) {
         | 
| 1014 | 
            -
                volatile VALUE rkey = parent->key_val;
         | 
| 1015 | 
            -
             | 
| 1016 | 
            -
                if (Qundef == rkey) {
         | 
| 1017 | 
            -
                    rkey = rb_str_new(parent->key, parent->klen);
         | 
| 1018 | 
            -
                }
         | 
| 1019 | 
            -
                rkey = oj_encode(rkey);
         | 
| 1020 | 
            -
                if (Yes == pi->options.sym_key) {
         | 
| 1021 | 
            -
                    rkey = rb_str_intern(rkey);
         | 
| 1022 | 
            -
                }
         | 
| 1023 | 
            -
                return rkey;
         | 
| 1024 | 
            -
            }
         | 
| 1025 | 
            -
             | 
| 1026 1014 | 
             
            static void hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) {
         | 
| 1027 1015 | 
             
                Val            parent = stack_peek(&pi->stack);
         | 
| 1028 1016 | 
             
                volatile VALUE rval   = oj_num_as_value(ni);
         | 
| @@ -1067,7 +1055,7 @@ static void hash_set_num(struct _parseInfo *pi, Val kval, NumInfo ni) { | |
| 1067 1055 | 
             
                        }
         | 
| 1068 1056 | 
             
                        rval = parent->val;
         | 
| 1069 1057 | 
             
                    } else {
         | 
| 1070 | 
            -
                        rb_hash_aset(parent->val,  | 
| 1058 | 
            +
                        rb_hash_aset(parent->val, oj_calc_hash_key(pi, kval), rval);
         | 
| 1071 1059 | 
             
                    }
         | 
| 1072 1060 | 
             
                    break;
         | 
| 1073 1061 | 
             
                default: break;
         | 
| @@ -1082,7 +1070,7 @@ static void hash_set_value(ParseInfo pi, Val kval, VALUE value) { | |
| 1082 1070 |  | 
| 1083 1071 | 
             
                switch (rb_type(parent->val)) {
         | 
| 1084 1072 | 
             
                case T_OBJECT: oj_set_obj_ivar(parent, kval, value); break;
         | 
| 1085 | 
            -
                case T_HASH: rb_hash_aset(parent->val,  | 
| 1073 | 
            +
                case T_HASH: rb_hash_aset(parent->val, oj_calc_hash_key(pi, kval), value); break;
         | 
| 1086 1074 | 
             
                default: break;
         | 
| 1087 1075 | 
             
                }
         | 
| 1088 1076 | 
             
                if (Yes == pi->options.trace) {
         | 
    
        data/ext/oj/dump.c
    CHANGED
    
    | @@ -535,59 +535,57 @@ void oj_dump_xml_time(VALUE obj, Out out) { | |
| 535 535 | 
             
                }
         | 
| 536 536 | 
             
                if ((0 == nsec && !out->opts->sec_prec_set) || 0 == out->opts->sec_prec) {
         | 
| 537 537 | 
             
                    if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
         | 
| 538 | 
            -
                        sprintf(buf,
         | 
| 539 | 
            -
             | 
| 540 | 
            -
             | 
| 541 | 
            -
             | 
| 542 | 
            -
             | 
| 543 | 
            -
             | 
| 544 | 
            -
             | 
| 545 | 
            -
             | 
| 546 | 
            -
                        oj_dump_cstr(buf,  | 
| 538 | 
            +
                        int len = sprintf(buf,
         | 
| 539 | 
            +
                                          "%04d-%02d-%02dT%02d:%02d:%02dZ",
         | 
| 540 | 
            +
                                          ti.year,
         | 
| 541 | 
            +
                                          ti.mon,
         | 
| 542 | 
            +
                                          ti.day,
         | 
| 543 | 
            +
                                          ti.hour,
         | 
| 544 | 
            +
                                          ti.min,
         | 
| 545 | 
            +
                                          ti.sec);
         | 
| 546 | 
            +
                        oj_dump_cstr(buf, len, 0, 0, out);
         | 
| 547 547 | 
             
                    } else {
         | 
| 548 | 
            -
                        sprintf(buf,
         | 
| 549 | 
            -
             | 
| 550 | 
            -
             | 
| 551 | 
            -
             | 
| 552 | 
            -
             | 
| 553 | 
            -
             | 
| 554 | 
            -
             | 
| 555 | 
            -
             | 
| 556 | 
            -
             | 
| 557 | 
            -
             | 
| 558 | 
            -
             | 
| 559 | 
            -
                        oj_dump_cstr(buf,  | 
| 548 | 
            +
                        int len = sprintf(buf,
         | 
| 549 | 
            +
                                          "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
         | 
| 550 | 
            +
                                          ti.year,
         | 
| 551 | 
            +
                                          ti.mon,
         | 
| 552 | 
            +
                                          ti.day,
         | 
| 553 | 
            +
                                          ti.hour,
         | 
| 554 | 
            +
                                          ti.min,
         | 
| 555 | 
            +
                                          ti.sec,
         | 
| 556 | 
            +
                                          tzsign,
         | 
| 557 | 
            +
                                          tzhour,
         | 
| 558 | 
            +
                                          tzmin);
         | 
| 559 | 
            +
                        oj_dump_cstr(buf, len, 0, 0, out);
         | 
| 560 560 | 
             
                    }
         | 
| 561 561 | 
             
                } else if (0 == tzsecs && rb_funcall2(obj, oj_utcq_id, 0, 0)) {
         | 
| 562 562 | 
             
                    char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ldZ";
         | 
| 563 | 
            -
                    int  len | 
| 563 | 
            +
                    int  len;
         | 
| 564 564 |  | 
| 565 565 | 
             
                    if (9 > out->opts->sec_prec) {
         | 
| 566 566 | 
             
                        format[32] = '0' + out->opts->sec_prec;
         | 
| 567 | 
            -
                        len -= 9 - out->opts->sec_prec;
         | 
| 568 567 | 
             
                    }
         | 
| 569 | 
            -
                    sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, (long)nsec);
         | 
| 568 | 
            +
                    len = sprintf(buf, format, ti.year, ti.mon, ti.day, ti.hour, ti.min, ti.sec, (long)nsec);
         | 
| 570 569 | 
             
                    oj_dump_cstr(buf, len, 0, 0, out);
         | 
| 571 570 | 
             
                } else {
         | 
| 572 571 | 
             
                    char format[64] = "%04d-%02d-%02dT%02d:%02d:%02d.%09ld%c%02d:%02d";
         | 
| 573 | 
            -
                    int  len | 
| 572 | 
            +
                    int  len;
         | 
| 574 573 |  | 
| 575 574 | 
             
                    if (9 > out->opts->sec_prec) {
         | 
| 576 575 | 
             
                        format[32] = '0' + out->opts->sec_prec;
         | 
| 577 | 
            -
                        len -= 9 - out->opts->sec_prec;
         | 
| 578 576 | 
             
                    }
         | 
| 579 | 
            -
                    sprintf(buf,
         | 
| 580 | 
            -
             | 
| 581 | 
            -
             | 
| 582 | 
            -
             | 
| 583 | 
            -
             | 
| 584 | 
            -
             | 
| 585 | 
            -
             | 
| 586 | 
            -
             | 
| 587 | 
            -
             | 
| 588 | 
            -
             | 
| 589 | 
            -
             | 
| 590 | 
            -
             | 
| 577 | 
            +
                    len = sprintf(buf,
         | 
| 578 | 
            +
                                  format,
         | 
| 579 | 
            +
                                  ti.year,
         | 
| 580 | 
            +
                                  ti.mon,
         | 
| 581 | 
            +
                                  ti.day,
         | 
| 582 | 
            +
                                  ti.hour,
         | 
| 583 | 
            +
                                  ti.min,
         | 
| 584 | 
            +
                                  ti.sec,
         | 
| 585 | 
            +
                                  (long)nsec,
         | 
| 586 | 
            +
                                  tzsign,
         | 
| 587 | 
            +
                                  tzhour,
         | 
| 588 | 
            +
                                  tzmin);
         | 
| 591 589 | 
             
                    oj_dump_cstr(buf, len, 0, 0, out);
         | 
| 592 590 | 
             
                }
         | 
| 593 591 | 
             
            }
         | 
| @@ -827,9 +825,8 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou | |
| 827 825 | 
             
                    if (is_sym) {
         | 
| 828 826 | 
             
                        *out->cur++ = ':';
         | 
| 829 827 | 
             
                    }
         | 
| 830 | 
            -
                     | 
| 831 | 
            -
             | 
| 832 | 
            -
                    }
         | 
| 828 | 
            +
                    memcpy(out->cur, str, cnt);
         | 
| 829 | 
            +
                    out->cur += cnt;
         | 
| 833 830 | 
             
                    *out->cur++ = '"';
         | 
| 834 831 | 
             
                } else {
         | 
| 835 832 | 
             
                    const char *end         = str + cnt;
         | 
| @@ -1206,7 +1203,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) { | |
| 1206 1203 | 
             
                    if ((int)sizeof(buf) <= cnt) {
         | 
| 1207 1204 | 
             
                        cnt = sizeof(buf) - 1;
         | 
| 1208 1205 | 
             
                    }
         | 
| 1209 | 
            -
                     | 
| 1206 | 
            +
                    memcpy(buf, rb_string_value_ptr((VALUE *)&rstr), cnt);
         | 
| 1210 1207 | 
             
                    buf[cnt] = '\0';
         | 
| 1211 1208 | 
             
                } else {
         | 
| 1212 1209 | 
             
                    cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, out->opts->float_fmt);
         | 
    
        data/ext/oj/dump_strict.c
    CHANGED
    
    | @@ -98,7 +98,7 @@ static void dump_float(VALUE obj, int depth, Out out, bool as_ok) { | |
| 98 98 | 
             
                        if ((int)sizeof(buf) <= cnt) {
         | 
| 99 99 | 
             
                            cnt = sizeof(buf) - 1;
         | 
| 100 100 | 
             
                        }
         | 
| 101 | 
            -
                         | 
| 101 | 
            +
                        memcpy(buf, rb_string_value_ptr((VALUE *)&rstr), cnt);
         | 
| 102 102 | 
             
                        buf[cnt] = '\0';
         | 
| 103 103 | 
             
                    } else {
         | 
| 104 104 | 
             
                        cnt = oj_dump_float_printf(buf, sizeof(buf), obj, d, out->opts->float_fmt);
         | 
    
        data/ext/oj/hash.c
    CHANGED
    
    | @@ -5,8 +5,8 @@ | |
| 5 5 |  | 
| 6 6 | 
             
            #include <stdint.h>
         | 
| 7 7 |  | 
| 8 | 
            -
            #define  | 
| 9 | 
            -
            #define HASH_SLOT_CNT  | 
| 8 | 
            +
            #define HASH_SLOT_CNT ((uint32_t)8192)
         | 
| 9 | 
            +
            #define HASH_MASK (HASH_SLOT_CNT - 1)
         | 
| 10 10 |  | 
| 11 11 | 
             
            typedef struct _keyVal {
         | 
| 12 12 | 
             
                struct _keyVal *next;
         | 
| @@ -20,6 +20,8 @@ struct _hash { | |
| 20 20 | 
             
            };
         | 
| 21 21 |  | 
| 22 22 | 
             
            struct _hash class_hash;
         | 
| 23 | 
            +
            struct _hash str_hash;
         | 
| 24 | 
            +
            struct _hash sym_hash;
         | 
| 23 25 | 
             
            struct _hash intern_hash;
         | 
| 24 26 |  | 
| 25 27 | 
             
            // almost the Murmur hash algorithm
         | 
| @@ -64,6 +66,8 @@ static uint32_t hash_calc(const uint8_t *key, size_t len) { | |
| 64 66 |  | 
| 65 67 | 
             
            void oj_hash_init() {
         | 
| 66 68 | 
             
                memset(class_hash.slots, 0, sizeof(class_hash.slots));
         | 
| 69 | 
            +
                memset(str_hash.slots, 0, sizeof(str_hash.slots));
         | 
| 70 | 
            +
                memset(sym_hash.slots, 0, sizeof(sym_hash.slots));
         | 
| 67 71 | 
             
                memset(intern_hash.slots, 0, sizeof(intern_hash.slots));
         | 
| 68 72 | 
             
            }
         | 
| 69 73 |  | 
| @@ -100,8 +104,8 @@ static VALUE hash_get(Hash hash, const char *key, size_t len, VALUE **slotp, VAL | |
| 100 104 | 
             
            }
         | 
| 101 105 |  | 
| 102 106 | 
             
            void oj_hash_print() {
         | 
| 103 | 
            -
                 | 
| 104 | 
            -
                KeyVal | 
| 107 | 
            +
                uint32_t i;
         | 
| 108 | 
            +
                KeyVal   b;
         | 
| 105 109 |  | 
| 106 110 | 
             
                for (i = 0; i < HASH_SLOT_CNT; i++) {
         | 
| 107 111 | 
             
                    printf("%4d:", i);
         | 
| @@ -112,11 +116,44 @@ void oj_hash_print() { | |
| 112 116 | 
             
                }
         | 
| 113 117 | 
             
            }
         | 
| 114 118 |  | 
| 119 | 
            +
            void oj_hash_sizes() {
         | 
| 120 | 
            +
                uint32_t i;
         | 
| 121 | 
            +
                KeyVal   b;
         | 
| 122 | 
            +
                int      max = 0;
         | 
| 123 | 
            +
                int      min = 1000000;
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                for (i = 0; i < HASH_SLOT_CNT; i++) {
         | 
| 126 | 
            +
                    int cnt = 0;
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                    for (b = str_hash.slots + i; 0 != b && 0 != b->key; b = b->next) {
         | 
| 129 | 
            +
                        cnt++;
         | 
| 130 | 
            +
                    }
         | 
| 131 | 
            +
                    // printf(" %4d\n", cnt);
         | 
| 132 | 
            +
                    if (max < cnt) {
         | 
| 133 | 
            +
                        max = cnt;
         | 
| 134 | 
            +
                    }
         | 
| 135 | 
            +
                    if (cnt < min) {
         | 
| 136 | 
            +
                        min = cnt;
         | 
| 137 | 
            +
                    }
         | 
| 138 | 
            +
                }
         | 
| 139 | 
            +
                printf("min: %d  max: %d\n", min, max);
         | 
| 140 | 
            +
            }
         | 
| 141 | 
            +
             | 
| 115 142 | 
             
            VALUE
         | 
| 116 143 | 
             
            oj_class_hash_get(const char *key, size_t len, VALUE **slotp) {
         | 
| 117 144 | 
             
                return hash_get(&class_hash, key, len, slotp, Qnil);
         | 
| 118 145 | 
             
            }
         | 
| 119 146 |  | 
| 147 | 
            +
            VALUE
         | 
| 148 | 
            +
            oj_str_hash_get(const char *key, size_t len, VALUE **slotp) {
         | 
| 149 | 
            +
                return hash_get(&str_hash, key, len, slotp, Qnil);
         | 
| 150 | 
            +
            }
         | 
| 151 | 
            +
             | 
| 152 | 
            +
            VALUE
         | 
| 153 | 
            +
            oj_sym_hash_get(const char *key, size_t len, VALUE **slotp) {
         | 
| 154 | 
            +
                return hash_get(&sym_hash, key, len, slotp, Qnil);
         | 
| 155 | 
            +
            }
         | 
| 156 | 
            +
             | 
| 120 157 | 
             
            ID oj_attr_hash_get(const char *key, size_t len, ID **slotp) {
         | 
| 121 158 | 
             
                return (ID)hash_get(&intern_hash, key, len, (VALUE **)slotp, 0);
         | 
| 122 159 | 
             
            }
         | 
    
        data/ext/oj/hash.h
    CHANGED
    
    | @@ -11,6 +11,8 @@ typedef struct _hash *Hash; | |
| 11 11 | 
             
            extern void oj_hash_init();
         | 
| 12 12 |  | 
| 13 13 | 
             
            extern VALUE oj_class_hash_get(const char *key, size_t len, VALUE **slotp);
         | 
| 14 | 
            +
            extern VALUE oj_str_hash_get(const char *key, size_t len, VALUE **slotp);
         | 
| 15 | 
            +
            extern VALUE oj_sym_hash_get(const char *key, size_t len, VALUE **slotp);
         | 
| 14 16 | 
             
            extern ID    oj_attr_hash_get(const char *key, size_t len, ID **slotp);
         | 
| 15 17 |  | 
| 16 18 | 
             
            extern void  oj_hash_print();
         | 
    
        data/ext/oj/mimic_json.c
    CHANGED
    
    | @@ -389,9 +389,9 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) { | |
| 389 389 | 
             
                } else {
         | 
| 390 390 | 
             
                    VALUE active_hack[1];
         | 
| 391 391 |  | 
| 392 | 
            -
             | 
| 393 | 
            -
             | 
| 394 | 
            -
             | 
| 392 | 
            +
                    if (Qundef == state_class) {
         | 
| 393 | 
            +
                        oj_define_mimic_json(0, NULL, Qnil);
         | 
| 394 | 
            +
                    }
         | 
| 395 395 | 
             
                    active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
         | 
| 396 396 | 
             
                    oj_dump_obj_to_json_using_params(*argv, copts, &out, 1, active_hack);
         | 
| 397 397 | 
             
                }
         | 
| @@ -480,7 +480,7 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) { | |
| 480 480 | 
             
                    rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
         | 
| 481 481 | 
             
                }
         | 
| 482 482 | 
             
                if (Qundef == state_class) {
         | 
| 483 | 
            -
             | 
| 483 | 
            +
                    oj_define_mimic_json(0, NULL, Qnil);
         | 
| 484 484 | 
             
                }
         | 
| 485 485 | 
             
                rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
         | 
| 486 486 |  | 
| @@ -713,6 +713,8 @@ static struct _options mimic_object_to_json_options = {0,              // indent | |
| 713 713 | 
             
                                                                   No,             // safe
         | 
| 714 714 | 
             
                                                                   false,          // sec_prec_set
         | 
| 715 715 | 
             
                                                                   No,             // ignore_under
         | 
| 716 | 
            +
                                                                   Yes,            // cache_keys
         | 
| 717 | 
            +
                                                                   3,              // cache_str
         | 
| 716 718 | 
             
                                                                   0,              // int_range_min
         | 
| 717 719 | 
             
                                                                   0,              // int_range_max
         | 
| 718 720 | 
             
                                                                   oj_json_class,  // create_id
         | 
    
        data/ext/oj/object.c
    CHANGED
    
    | @@ -30,11 +30,38 @@ inline static long read_long(const char *str, size_t len) { | |
| 30 30 |  | 
| 31 31 | 
             
            static VALUE calc_hash_key(ParseInfo pi, Val kval, char k1) {
         | 
| 32 32 | 
             
                volatile VALUE rkey;
         | 
| 33 | 
            +
            #if 0
         | 
| 34 | 
            +
                VALUE *slot;
         | 
| 33 35 |  | 
| 36 | 
            +
                if (':' == k1) {
         | 
| 37 | 
            +
                    if (Qnil == (rkey = oj_sym_hash_get(kval->key + 1, kval->klen - 1, &slot))) {
         | 
| 38 | 
            +
                        rkey  = rb_str_new(kval->key + 1, kval->klen - 1);
         | 
| 39 | 
            +
                        rkey  = oj_encode(rkey);
         | 
| 40 | 
            +
                        rkey  = rb_str_intern(rkey);
         | 
| 41 | 
            +
                        *slot = rkey;
         | 
| 42 | 
            +
                        rb_gc_register_address(slot);
         | 
| 43 | 
            +
                    }
         | 
| 44 | 
            +
                } else if (Yes == pi->options.sym_key) {
         | 
| 45 | 
            +
                    if (Qnil == (rkey = oj_sym_hash_get(kval->key, kval->klen, &slot))) {
         | 
| 46 | 
            +
                        rkey  = rb_str_new(kval->key, kval->klen);
         | 
| 47 | 
            +
                        rkey  = oj_encode(rkey);
         | 
| 48 | 
            +
                        rkey  = rb_str_intern(rkey);
         | 
| 49 | 
            +
                        *slot = rkey;
         | 
| 50 | 
            +
                        rb_gc_register_address(slot);
         | 
| 51 | 
            +
                    }
         | 
| 52 | 
            +
                } else {
         | 
| 53 | 
            +
                    if (Qnil == (rkey = oj_str_hash_get(kval->key, kval->klen, &slot))) {
         | 
| 54 | 
            +
                        rkey  = rb_str_new(kval->key, kval->klen);
         | 
| 55 | 
            +
                        rkey  = oj_encode(rkey);
         | 
| 56 | 
            +
                        *slot = rkey;
         | 
| 57 | 
            +
                        rb_gc_register_address(slot);
         | 
| 58 | 
            +
                    }
         | 
| 59 | 
            +
                }
         | 
| 60 | 
            +
            #else
         | 
| 34 61 | 
             
                if (':' == k1) {
         | 
| 35 62 | 
             
                    rkey = rb_str_new(kval->key + 1, kval->klen - 1);
         | 
| 36 63 | 
             
                    rkey = oj_encode(rkey);
         | 
| 37 | 
            -
             | 
| 64 | 
            +
            	rkey  = rb_str_intern(rkey);
         | 
| 38 65 | 
             
                } else {
         | 
| 39 66 | 
             
                    rkey = rb_str_new(kval->key, kval->klen);
         | 
| 40 67 | 
             
                    rkey = oj_encode(rkey);
         | 
| @@ -42,6 +69,7 @@ static VALUE calc_hash_key(ParseInfo pi, Val kval, char k1) { | |
| 42 69 | 
             
                        rkey = rb_str_intern(rkey);
         | 
| 43 70 | 
             
                    }
         | 
| 44 71 | 
             
                }
         | 
| 72 | 
            +
            #endif
         | 
| 45 73 | 
             
                return rkey;
         | 
| 46 74 | 
             
            }
         | 
| 47 75 |  | 
| @@ -405,22 +433,22 @@ void oj_set_obj_ivar(Val parent, Val kval, VALUE value) { | |
| 405 433 | 
             
                        char *buf = ALLOC_N(char, klen + 2);
         | 
| 406 434 |  | 
| 407 435 | 
             
                        if ('~' == *key) {
         | 
| 408 | 
            -
                             | 
| 436 | 
            +
                            memcpy(buf, key + 1, klen - 1);
         | 
| 409 437 | 
             
                            buf[klen - 1] = '\0';
         | 
| 410 438 | 
             
                        } else {
         | 
| 411 439 | 
             
                            *buf = '@';
         | 
| 412 | 
            -
                             | 
| 440 | 
            +
                            memcpy(buf + 1, key, klen);
         | 
| 413 441 | 
             
                            buf[klen + 1] = '\0';
         | 
| 414 442 | 
             
                        }
         | 
| 415 443 | 
             
                        var_id = rb_intern(buf);
         | 
| 416 444 | 
             
                        xfree(buf);
         | 
| 417 445 | 
             
                    } else {
         | 
| 418 446 | 
             
                        if ('~' == *key) {
         | 
| 419 | 
            -
                             | 
| 447 | 
            +
                            memcpy(attr, key + 1, klen - 1);
         | 
| 420 448 | 
             
                            attr[klen - 1] = '\0';
         | 
| 421 449 | 
             
                        } else {
         | 
| 422 450 | 
             
                            *attr = '@';
         | 
| 423 | 
            -
                             | 
| 451 | 
            +
                            memcpy(attr + 1, key, klen);
         | 
| 424 452 | 
             
                            attr[klen + 1] = '\0';
         | 
| 425 453 | 
             
                        }
         | 
| 426 454 | 
             
                        var_id = rb_intern(attr);
         | 
    
        data/ext/oj/oj.c
    CHANGED
    
    | @@ -106,6 +106,8 @@ static VALUE auto_sym; | |
| 106 106 | 
             
            static VALUE bigdecimal_as_decimal_sym;
         | 
| 107 107 | 
             
            static VALUE bigdecimal_load_sym;
         | 
| 108 108 | 
             
            static VALUE bigdecimal_sym;
         | 
| 109 | 
            +
            static VALUE cache_keys_sym;
         | 
| 110 | 
            +
            static VALUE cache_str_sym;
         | 
| 109 111 | 
             
            static VALUE circular_sym;
         | 
| 110 112 | 
             
            static VALUE class_cache_sym;
         | 
| 111 113 | 
             
            static VALUE compat_bigdecimal_sym;
         | 
| @@ -186,6 +188,8 @@ struct _options oj_default_options = { | |
| 186 188 | 
             
                No,             // safe
         | 
| 187 189 | 
             
                false,          // sec_prec_set
         | 
| 188 190 | 
             
                No,             // ignore_under
         | 
| 191 | 
            +
                Yes,            // cache_keys
         | 
| 192 | 
            +
                3,              // cache_str
         | 
| 189 193 | 
             
                0,              // int_range_min
         | 
| 190 194 | 
             
                0,              // int_range_max
         | 
| 191 195 | 
             
                oj_json_class,  // create_id
         | 
| @@ -279,9 +283,11 @@ struct _options oj_default_options = { | |
| 279 283 | 
             
             *used
         | 
| 280 284 | 
             
             * - *:array_class* [_Class_|_nil_] Class to use instead of Array on load
         | 
| 281 285 | 
             
             * - *:omit_nil* [_true_|_false_] if true Hash and Object attributes with nil values are omitted
         | 
| 282 | 
            -
             * - *:ignore* [_nil_| | 
| 283 | 
            -
             * - *:ignore_under* [ | 
| 286 | 
            +
             * - *:ignore* [_nil_|_Array_] either nil or an Array of classes to ignore when dumping
         | 
| 287 | 
            +
             * - *:ignore_under* [_Boolean_] if true then attributes that start with _ are ignored when dumping in
         | 
| 284 288 | 
             
             *object or custom mode.
         | 
| 289 | 
            +
             * - *:cache_keys* [_Boolean_] if true then hash keys are cached
         | 
| 290 | 
            +
             * - *:cache_str* [_Fixnum_] maximum string value length to cache
         | 
| 285 291 | 
             
             * - *:integer_range* [_Range_] Dump integers outside range as strings.
         | 
| 286 292 | 
             
             * - *:trace* [_true,_|_false_] Trace all load and dump calls, default is false (trace is off)
         | 
| 287 293 | 
             
             * - *:safe* [_true,_|_false_] Safe mimic breaks JSON mimic to be safer, default is false (safe is
         | 
| @@ -389,11 +395,17 @@ static VALUE get_def_opts(VALUE self) { | |
| 389 395 | 
             
                                 ? Qtrue
         | 
| 390 396 | 
             
                                 : ((No == oj_default_options.safe) ? Qfalse : Qnil));
         | 
| 391 397 | 
             
                rb_hash_aset(opts, float_prec_sym, INT2FIX(oj_default_options.float_prec));
         | 
| 398 | 
            +
                rb_hash_aset(opts, cache_str_sym, INT2FIX(oj_default_options.cache_str));
         | 
| 392 399 | 
             
                rb_hash_aset(opts,
         | 
| 393 400 | 
             
                             ignore_under_sym,
         | 
| 394 401 | 
             
                             (Yes == oj_default_options.ignore_under)
         | 
| 395 402 | 
             
                                 ? Qtrue
         | 
| 396 403 | 
             
                                 : ((No == oj_default_options.ignore_under) ? Qfalse : Qnil));
         | 
| 404 | 
            +
                rb_hash_aset(opts,
         | 
| 405 | 
            +
                             cache_keys_sym,
         | 
| 406 | 
            +
                             (Yes == oj_default_options.cache_keys)
         | 
| 407 | 
            +
                                 ? Qtrue
         | 
| 408 | 
            +
                                 : ((No == oj_default_options.cache_keys) ? Qfalse : Qnil));
         | 
| 397 409 | 
             
                switch (oj_default_options.mode) {
         | 
| 398 410 | 
             
                case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
         | 
| 399 411 | 
             
                case CompatMode: rb_hash_aset(opts, mode_sym, compat_sym); break;
         | 
| @@ -557,6 +569,8 @@ static VALUE get_def_opts(VALUE self) { | |
| 557 569 | 
             
             *   - *:ignore* [_nil_|Array] either nil or an Array of classes to ignore when dumping
         | 
| 558 570 | 
             
             *   - *:ignore_under* [_Boolean_] if true then attributes that start with _ are ignored when
         | 
| 559 571 | 
             
             *dumping in object or custom mode.
         | 
| 572 | 
            +
             *   - *:cache_keys* [_Boolean_] if true then hash keys are cached
         | 
| 573 | 
            +
             *   - *:cache_str* [_Fixnum_] maximum string vsalue length to cache
         | 
| 560 574 | 
             
             *   - *:integer_range* [_Range_] Dump integers outside range as strings.
         | 
| 561 575 | 
             
             *   - *:trace* [_Boolean_] turn trace on or off.
         | 
| 562 576 | 
             
             *   - *:safe* [_Boolean_] turn safe mimic on or off.
         | 
| @@ -589,6 +603,7 @@ void oj_parse_options(VALUE ropts, Options copts) { | |
| 589 603 | 
             
                                           {oj_safe_sym, &copts->safe},
         | 
| 590 604 | 
             
                                           {ignore_under_sym, &copts->ignore_under},
         | 
| 591 605 | 
             
                                           {oj_create_additions_sym, &copts->create_ok},
         | 
| 606 | 
            +
                                           {cache_keys_sym, &copts->cache_keys},
         | 
| 592 607 | 
             
                                           {Qnil, 0}};
         | 
| 593 608 | 
             
                YesNoOpt         o;
         | 
| 594 609 | 
             
                volatile VALUE   v;
         | 
| @@ -647,6 +662,28 @@ void oj_parse_options(VALUE ropts, Options copts) { | |
| 647 662 | 
             
                        copts->float_prec = n;
         | 
| 648 663 | 
             
                    }
         | 
| 649 664 | 
             
                }
         | 
| 665 | 
            +
                if (Qnil != (v = rb_hash_lookup(ropts, cache_str_sym))) {
         | 
| 666 | 
            +
                    int n;
         | 
| 667 | 
            +
             | 
| 668 | 
            +
            #ifdef RUBY_INTEGER_UNIFICATION
         | 
| 669 | 
            +
                    if (rb_cInteger != rb_obj_class(v)) {
         | 
| 670 | 
            +
                        rb_raise(rb_eArgError, ":cache_str must be a Integer.");
         | 
| 671 | 
            +
                    }
         | 
| 672 | 
            +
            #else
         | 
| 673 | 
            +
                    if (T_FIXNUM != rb_type(v)) {
         | 
| 674 | 
            +
                        rb_raise(rb_eArgError, ":cache_str must be a Fixnum.");
         | 
| 675 | 
            +
                    }
         | 
| 676 | 
            +
            #endif
         | 
| 677 | 
            +
                    n = FIX2INT(v);
         | 
| 678 | 
            +
                    if (0 >= n) {
         | 
| 679 | 
            +
                        copts->cache_str = 0;
         | 
| 680 | 
            +
                    } else {
         | 
| 681 | 
            +
                        if (32 < n) {
         | 
| 682 | 
            +
                            n = 32;
         | 
| 683 | 
            +
                        }
         | 
| 684 | 
            +
                        copts->cache_str = (char)n;
         | 
| 685 | 
            +
                    }
         | 
| 686 | 
            +
                }
         | 
| 650 687 | 
             
                if (Qnil != (v = rb_hash_lookup(ropts, sec_prec_sym))) {
         | 
| 651 688 | 
             
                    int n;
         | 
| 652 689 |  | 
| @@ -1636,13 +1673,20 @@ extern VALUE oj_optimize_rails(VALUE self); | |
| 1636 1673 |  | 
| 1637 1674 | 
             
            /*
         | 
| 1638 1675 | 
             
            extern void	oj_hash_test();
         | 
| 1639 | 
            -
             | 
| 1640 1676 | 
             
            static VALUE
         | 
| 1641 1677 | 
             
            hash_test(VALUE self) {
         | 
| 1642 1678 | 
             
                oj_hash_test();
         | 
| 1643 1679 | 
             
                return Qnil;
         | 
| 1644 1680 | 
             
            }
         | 
| 1645 1681 | 
             
            */
         | 
| 1682 | 
            +
            /*
         | 
| 1683 | 
            +
            extern void oj_hash_sizes();
         | 
| 1684 | 
            +
            static VALUE
         | 
| 1685 | 
            +
            hash_test(VALUE self) {
         | 
| 1686 | 
            +
                oj_hash_sizes();
         | 
| 1687 | 
            +
                return Qnil;
         | 
| 1688 | 
            +
            }
         | 
| 1689 | 
            +
            */
         | 
| 1646 1690 |  | 
| 1647 1691 | 
             
            static VALUE protect_require(VALUE x) {
         | 
| 1648 1692 | 
             
                rb_require("time");
         | 
| @@ -1816,6 +1860,10 @@ void Init_oj() { | |
| 1816 1860 | 
             
                rb_gc_register_address(&bigdecimal_load_sym);
         | 
| 1817 1861 | 
             
                bigdecimal_sym = ID2SYM(rb_intern("bigdecimal"));
         | 
| 1818 1862 | 
             
                rb_gc_register_address(&bigdecimal_sym);
         | 
| 1863 | 
            +
                cache_keys_sym = ID2SYM(rb_intern("cache_keys"));
         | 
| 1864 | 
            +
                rb_gc_register_address(&cache_keys_sym);
         | 
| 1865 | 
            +
                cache_str_sym = ID2SYM(rb_intern("cache_str"));
         | 
| 1866 | 
            +
                rb_gc_register_address(&cache_str_sym);
         | 
| 1819 1867 | 
             
                circular_sym = ID2SYM(rb_intern("circular"));
         | 
| 1820 1868 | 
             
                rb_gc_register_address(&circular_sym);
         | 
| 1821 1869 | 
             
                class_cache_sym = ID2SYM(rb_intern("class_cache"));
         | 
    
        data/ext/oj/oj.h
    CHANGED
    
    | @@ -143,6 +143,8 @@ typedef struct _options { | |
| 143 143 | 
             
                char safe;           // YesNo
         | 
| 144 144 | 
             
                char sec_prec_set;   // boolean (0 or 1)
         | 
| 145 145 | 
             
                char ignore_under;   // YesNo - ignore attrs starting with _ if true in object and custom modes
         | 
| 146 | 
            +
                char cache_keys;     // YexNo
         | 
| 147 | 
            +
                char cache_str;      // string short than or equal to this are cache
         | 
| 146 148 | 
             
                int64_t          int_range_min;  // dump numbers below as string
         | 
| 147 149 | 
             
                int64_t          int_range_max;  // dump numbers above as string
         | 
| 148 150 | 
             
                const char *     create_id;      // 0 or string
         | 
    
        data/ext/oj/parse.h
    CHANGED
    
    | @@ -90,6 +90,9 @@ extern void oj_set_wab_callbacks(ParseInfo pi); | |
| 90 90 | 
             
            extern void  oj_sparse2(ParseInfo pi);
         | 
| 91 91 | 
             
            extern VALUE oj_pi_sparse(int argc, VALUE *argv, ParseInfo pi, int fd);
         | 
| 92 92 |  | 
| 93 | 
            +
            extern VALUE oj_cstr_to_value(const char *str, size_t len, size_t cache_str);
         | 
| 94 | 
            +
            extern VALUE oj_calc_hash_key(ParseInfo pi, Val parent);
         | 
| 95 | 
            +
             | 
| 93 96 | 
             
            static inline void parse_info_init(ParseInfo pi) {
         | 
| 94 97 | 
             
                memset(pi, 0, sizeof(struct _parseInfo));
         | 
| 95 98 | 
             
            }
         | 
    
        data/ext/oj/rails.c
    CHANGED
    
    | @@ -828,7 +828,8 @@ rails_mimic_json(VALUE self) { | |
| 828 828 | 
             
                    json = rb_define_module("JSON");
         | 
| 829 829 | 
             
                }
         | 
| 830 830 | 
             
                oj_mimic_json_methods(json);
         | 
| 831 | 
            -
                 | 
| 831 | 
            +
                // Setting the default mode breaks the prmoise in the docs not to.
         | 
| 832 | 
            +
                //oj_default_options.mode = RailsMode;
         | 
| 832 833 |  | 
| 833 834 | 
             
                return Qnil;
         | 
| 834 835 | 
             
            }
         | 
    
        data/ext/oj/scp.c
    CHANGED
    
    | @@ -9,6 +9,7 @@ | |
| 9 9 | 
             
            #include <unistd.h>
         | 
| 10 10 |  | 
| 11 11 | 
             
            #include "encode.h"
         | 
| 12 | 
            +
            #include "hash.h"
         | 
| 12 13 | 
             
            #include "oj.h"
         | 
| 13 14 | 
             
            #include "parse.h"
         | 
| 14 15 |  | 
| @@ -82,19 +83,6 @@ static void end_array(ParseInfo pi) { | |
| 82 83 | 
             
                rb_funcall(pi->handler, oj_array_end_id, 0);
         | 
| 83 84 | 
             
            }
         | 
| 84 85 |  | 
| 85 | 
            -
            static VALUE calc_hash_key(ParseInfo pi, Val kval) {
         | 
| 86 | 
            -
                volatile VALUE rkey = kval->key_val;
         | 
| 87 | 
            -
             | 
| 88 | 
            -
                if (Qundef == rkey) {
         | 
| 89 | 
            -
                    rkey = rb_str_new(kval->key, kval->klen);
         | 
| 90 | 
            -
                    rkey = oj_encode(rkey);
         | 
| 91 | 
            -
                    if (Yes == pi->options.sym_key) {
         | 
| 92 | 
            -
                        rkey = rb_str_intern(rkey);
         | 
| 93 | 
            -
                    }
         | 
| 94 | 
            -
                }
         | 
| 95 | 
            -
                return rkey;
         | 
| 96 | 
            -
            }
         | 
| 97 | 
            -
             | 
| 98 86 | 
             
            static VALUE hash_key(ParseInfo pi, const char *key, size_t klen) {
         | 
| 99 87 | 
             
                return rb_funcall(pi->handler, oj_hash_key_id, 1, rb_str_new(key, klen));
         | 
| 100 88 | 
             
            }
         | 
| @@ -107,7 +95,7 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c | |
| 107 95 | 
             
                           oj_hash_set_id,
         | 
| 108 96 | 
             
                           3,
         | 
| 109 97 | 
             
                           stack_peek(&pi->stack)->val,
         | 
| 110 | 
            -
                            | 
| 98 | 
            +
                           oj_calc_hash_key(pi, kval),
         | 
| 111 99 | 
             
                           rstr);
         | 
| 112 100 | 
             
            }
         | 
| 113 101 |  | 
| @@ -116,7 +104,7 @@ static void hash_set_num(ParseInfo pi, Val kval, NumInfo ni) { | |
| 116 104 | 
             
                           oj_hash_set_id,
         | 
| 117 105 | 
             
                           3,
         | 
| 118 106 | 
             
                           stack_peek(&pi->stack)->val,
         | 
| 119 | 
            -
                            | 
| 107 | 
            +
                           oj_calc_hash_key(pi, kval),
         | 
| 120 108 | 
             
                           oj_num_as_value(ni));
         | 
| 121 109 | 
             
            }
         | 
| 122 110 |  | 
| @@ -125,7 +113,7 @@ static void hash_set_value(ParseInfo pi, Val kval, VALUE value) { | |
| 125 113 | 
             
                           oj_hash_set_id,
         | 
| 126 114 | 
             
                           3,
         | 
| 127 115 | 
             
                           stack_peek(&pi->stack)->val,
         | 
| 128 | 
            -
                            | 
| 116 | 
            +
                           oj_calc_hash_key(pi, kval),
         | 
| 129 117 | 
             
                           value);
         | 
| 130 118 | 
             
            }
         | 
| 131 119 |  | 
    
        data/ext/oj/strict.c
    CHANGED
    
    | @@ -8,10 +8,65 @@ | |
| 8 8 |  | 
| 9 9 | 
             
            #include "encode.h"
         | 
| 10 10 | 
             
            #include "err.h"
         | 
| 11 | 
            +
            #include "hash.h"
         | 
| 11 12 | 
             
            #include "oj.h"
         | 
| 12 13 | 
             
            #include "parse.h"
         | 
| 13 14 | 
             
            #include "trace.h"
         | 
| 14 15 |  | 
| 16 | 
            +
            VALUE oj_cstr_to_value(const char *str, size_t len, size_t cache_str) {
         | 
| 17 | 
            +
                volatile VALUE rstr = Qnil;
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                if (len <= cache_str) {
         | 
| 20 | 
            +
                    VALUE *slot;
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    if (Qnil == (rstr = oj_str_hash_get(str, len, &slot))) {
         | 
| 23 | 
            +
                        rstr  = rb_str_new(str, len);
         | 
| 24 | 
            +
                        rstr  = oj_encode(rstr);
         | 
| 25 | 
            +
                        *slot = rstr;
         | 
| 26 | 
            +
                        rb_gc_register_address(slot);
         | 
| 27 | 
            +
                    }
         | 
| 28 | 
            +
                } else {
         | 
| 29 | 
            +
                    rstr = rb_str_new(str, len);
         | 
| 30 | 
            +
                    rstr = oj_encode(rstr);
         | 
| 31 | 
            +
                }
         | 
| 32 | 
            +
                return rstr;
         | 
| 33 | 
            +
            }
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            VALUE oj_calc_hash_key(ParseInfo pi, Val parent) {
         | 
| 36 | 
            +
                volatile VALUE rkey = parent->key_val;
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                if (Qundef != rkey) {
         | 
| 39 | 
            +
                    return rkey;
         | 
| 40 | 
            +
                }
         | 
| 41 | 
            +
                if (Yes != pi->options.cache_keys) {
         | 
| 42 | 
            +
                    rkey = rb_str_new(parent->key, parent->klen);
         | 
| 43 | 
            +
                    rkey = oj_encode(rkey);
         | 
| 44 | 
            +
                    if (Yes == pi->options.sym_key) {
         | 
| 45 | 
            +
                        rkey = rb_str_intern(rkey);
         | 
| 46 | 
            +
                    }
         | 
| 47 | 
            +
                    return rkey;
         | 
| 48 | 
            +
                }
         | 
| 49 | 
            +
                VALUE *slot;
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                if (Yes == pi->options.sym_key) {
         | 
| 52 | 
            +
                    if (Qnil == (rkey = oj_sym_hash_get(parent->key, parent->klen, &slot))) {
         | 
| 53 | 
            +
                        rkey  = rb_str_new(parent->key, parent->klen);
         | 
| 54 | 
            +
                        rkey  = oj_encode(rkey);
         | 
| 55 | 
            +
                        rkey  = rb_str_intern(rkey);
         | 
| 56 | 
            +
                        *slot = rkey;
         | 
| 57 | 
            +
                        rb_gc_register_address(slot);
         | 
| 58 | 
            +
                    }
         | 
| 59 | 
            +
                } else {
         | 
| 60 | 
            +
                    if (Qnil == (rkey = oj_str_hash_get(parent->key, parent->klen, &slot))) {
         | 
| 61 | 
            +
                        rkey  = rb_str_new(parent->key, parent->klen);
         | 
| 62 | 
            +
                        rkey  = oj_encode(rkey);
         | 
| 63 | 
            +
                        *slot = rkey;
         | 
| 64 | 
            +
                        rb_gc_register_address(slot);
         | 
| 65 | 
            +
                    }
         | 
| 66 | 
            +
                }
         | 
| 67 | 
            +
                return rkey;
         | 
| 68 | 
            +
            }
         | 
| 69 | 
            +
             | 
| 15 70 | 
             
            static void hash_end(ParseInfo pi) {
         | 
| 16 71 | 
             
                if (Yes == pi->options.trace) {
         | 
| 17 72 | 
             
                    oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
         | 
| @@ -36,9 +91,8 @@ static void add_value(ParseInfo pi, VALUE val) { | |
| 36 91 | 
             
            }
         | 
| 37 92 |  | 
| 38 93 | 
             
            static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
         | 
| 39 | 
            -
                volatile VALUE rstr =  | 
| 94 | 
            +
                volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
         | 
| 40 95 |  | 
| 41 | 
            -
                rstr                = oj_encode(rstr);
         | 
| 42 96 | 
             
                pi->stack.head->val = rstr;
         | 
| 43 97 | 
             
                if (Yes == pi->options.trace) {
         | 
| 44 98 | 
             
                    oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, rstr);
         | 
| @@ -65,24 +119,12 @@ static VALUE start_hash(ParseInfo pi) { | |
| 65 119 | 
             
                return rb_hash_new();
         | 
| 66 120 | 
             
            }
         | 
| 67 121 |  | 
| 68 | 
            -
            static VALUE calc_hash_key(ParseInfo pi, Val parent) {
         | 
| 69 | 
            -
                volatile VALUE rkey = parent->key_val;
         | 
| 70 | 
            -
             | 
| 71 | 
            -
                if (Qundef == rkey) {
         | 
| 72 | 
            -
                    rkey = rb_str_new(parent->key, parent->klen);
         | 
| 73 | 
            -
                }
         | 
| 74 | 
            -
                rkey = oj_encode(rkey);
         | 
| 75 | 
            -
                if (Yes == pi->options.sym_key) {
         | 
| 76 | 
            -
                    rkey = rb_str_intern(rkey);
         | 
| 77 | 
            -
                }
         | 
| 78 | 
            -
                return rkey;
         | 
| 79 | 
            -
            }
         | 
| 80 | 
            -
             | 
| 81 122 | 
             
            static void hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
         | 
| 82 | 
            -
                volatile VALUE rstr =  | 
| 123 | 
            +
                volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
         | 
| 83 124 |  | 
| 84 | 
            -
                 | 
| 85 | 
            -
             | 
| 125 | 
            +
                rb_hash_aset(stack_peek(&pi->stack)->val,
         | 
| 126 | 
            +
                             oj_calc_hash_key(pi, parent),
         | 
| 127 | 
            +
                             rstr);
         | 
| 86 128 | 
             
                if (Yes == pi->options.trace) {
         | 
| 87 129 | 
             
                    oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rstr);
         | 
| 88 130 | 
             
                }
         | 
| @@ -95,14 +137,18 @@ static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) { | |
| 95 137 | 
             
                    oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
         | 
| 96 138 | 
             
                }
         | 
| 97 139 | 
             
                v = oj_num_as_value(ni);
         | 
| 98 | 
            -
                rb_hash_aset(stack_peek(&pi->stack)->val, | 
| 140 | 
            +
                rb_hash_aset(stack_peek(&pi->stack)->val,
         | 
| 141 | 
            +
                             oj_calc_hash_key(pi, parent),
         | 
| 142 | 
            +
                             v);
         | 
| 99 143 | 
             
                if (Yes == pi->options.trace) {
         | 
| 100 144 | 
             
                    oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, v);
         | 
| 101 145 | 
             
                }
         | 
| 102 146 | 
             
            }
         | 
| 103 147 |  | 
| 104 148 | 
             
            static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
         | 
| 105 | 
            -
                rb_hash_aset(stack_peek(&pi->stack)->val, | 
| 149 | 
            +
                rb_hash_aset(stack_peek(&pi->stack)->val,
         | 
| 150 | 
            +
                             oj_calc_hash_key(pi, parent),
         | 
| 151 | 
            +
                             value);
         | 
| 106 152 | 
             
                if (Yes == pi->options.trace) {
         | 
| 107 153 | 
             
                    oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
         | 
| 108 154 | 
             
                }
         | 
| @@ -116,9 +162,8 @@ static VALUE start_array(ParseInfo pi) { | |
| 116 162 | 
             
            }
         | 
| 117 163 |  | 
| 118 164 | 
             
            static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
         | 
| 119 | 
            -
                volatile VALUE rstr =  | 
| 165 | 
            +
                volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
         | 
| 120 166 |  | 
| 121 | 
            -
                rstr = oj_encode(rstr);
         | 
| 122 167 | 
             
                rb_ary_push(stack_peek(&pi->stack)->val, rstr);
         | 
| 123 168 | 
             
                if (Yes == pi->options.trace) {
         | 
| 124 169 | 
             
                    oj_trace_parse_call("append_string", pi, __FILE__, __LINE__, rstr);
         | 
    
        data/ext/oj/wab.c
    CHANGED
    
    | @@ -10,6 +10,7 @@ | |
| 10 10 | 
             
            #include "dump.h"
         | 
| 11 11 | 
             
            #include "encode.h"
         | 
| 12 12 | 
             
            #include "err.h"
         | 
| 13 | 
            +
            #include "hash.h"
         | 
| 13 14 | 
             
            #include "oj.h"
         | 
| 14 15 | 
             
            #include "parse.h"
         | 
| 15 16 | 
             
            #include "trace.h"
         | 
| @@ -292,6 +293,34 @@ void oj_dump_wab_val(VALUE obj, int depth, Out out) { | |
| 292 293 |  | 
| 293 294 | 
             
            ///// load functions /////
         | 
| 294 295 |  | 
| 296 | 
            +
            static VALUE calc_hash_key(ParseInfo pi, Val parent) {
         | 
| 297 | 
            +
                volatile VALUE rkey = parent->key_val;
         | 
| 298 | 
            +
             | 
| 299 | 
            +
                if (Qundef != rkey) {
         | 
| 300 | 
            +
                    rkey = oj_encode(rkey);
         | 
| 301 | 
            +
                    rkey = rb_str_intern(rkey);
         | 
| 302 | 
            +
             | 
| 303 | 
            +
                    return rkey;
         | 
| 304 | 
            +
                }
         | 
| 305 | 
            +
                if (Yes != pi->options.cache_keys) {
         | 
| 306 | 
            +
                    rkey = rb_str_new(parent->key, parent->klen);
         | 
| 307 | 
            +
                    rkey = oj_encode(rkey);
         | 
| 308 | 
            +
            	rkey = rb_str_intern(rkey);
         | 
| 309 | 
            +
             | 
| 310 | 
            +
                    return rkey;
         | 
| 311 | 
            +
                }
         | 
| 312 | 
            +
                VALUE *slot;
         | 
| 313 | 
            +
             | 
| 314 | 
            +
                if (Qnil == (rkey = oj_sym_hash_get(parent->key, parent->klen, &slot))) {
         | 
| 315 | 
            +
                    rkey  = rb_str_new(parent->key, parent->klen);
         | 
| 316 | 
            +
                    rkey  = oj_encode(rkey);
         | 
| 317 | 
            +
                    rkey  = rb_str_intern(rkey);
         | 
| 318 | 
            +
                    *slot = rkey;
         | 
| 319 | 
            +
                    rb_gc_register_address(slot);
         | 
| 320 | 
            +
                }
         | 
| 321 | 
            +
                return rkey;
         | 
| 322 | 
            +
            }
         | 
| 323 | 
            +
             | 
| 295 324 | 
             
            static void hash_end(ParseInfo pi) {
         | 
| 296 325 | 
             
                if (Yes == pi->options.trace) {
         | 
| 297 326 | 
             
                    oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
         | 
| @@ -432,7 +461,7 @@ static VALUE protect_uri(VALUE rstr) { | |
| 432 461 | 
             
                return rb_funcall(resolve_uri_class(), oj_parse_id, 1, rstr);
         | 
| 433 462 | 
             
            }
         | 
| 434 463 |  | 
| 435 | 
            -
            static VALUE cstr_to_rstr(const char *str, size_t len) {
         | 
| 464 | 
            +
            static VALUE cstr_to_rstr(ParseInfo pi, const char *str, size_t len) {
         | 
| 436 465 | 
             
                volatile VALUE v = Qnil;
         | 
| 437 466 |  | 
| 438 467 | 
             
                if (30 == len && '-' == str[4] && '-' == str[7] && 'T' == str[10] && ':' == str[13] &&
         | 
| @@ -445,20 +474,20 @@ static VALUE cstr_to_rstr(const char *str, size_t len) { | |
| 445 474 | 
             
                    uuid_check(str, (int)len) && Qnil != resolve_wab_uuid_class()) {
         | 
| 446 475 | 
             
                    return rb_funcall(wab_uuid_clas, oj_new_id, 1, rb_str_new(str, len));
         | 
| 447 476 | 
             
                }
         | 
| 448 | 
            -
                v = rb_str_new(str, len);
         | 
| 449 477 | 
             
                if (7 < len && 0 == strncasecmp("http://", str, 7)) {
         | 
| 450 478 | 
             
                    int            err = 0;
         | 
| 479 | 
            +
            	v = rb_str_new(str, len);
         | 
| 451 480 | 
             
                    volatile VALUE uri = rb_protect(protect_uri, v, &err);
         | 
| 452 481 |  | 
| 453 482 | 
             
                    if (0 == err) {
         | 
| 454 483 | 
             
                        return uri;
         | 
| 455 484 | 
             
                    }
         | 
| 456 485 | 
             
                }
         | 
| 457 | 
            -
                return  | 
| 486 | 
            +
                return oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
         | 
| 458 487 | 
             
            }
         | 
| 459 488 |  | 
| 460 489 | 
             
            static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
         | 
| 461 | 
            -
                pi->stack.head->val = cstr_to_rstr(str, len);
         | 
| 490 | 
            +
                pi->stack.head->val = cstr_to_rstr(pi, str, len);
         | 
| 462 491 | 
             
                if (Yes == pi->options.trace) {
         | 
| 463 492 | 
             
                    oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
         | 
| 464 493 | 
             
                }
         | 
| @@ -484,20 +513,8 @@ static VALUE start_hash(ParseInfo pi) { | |
| 484 513 | 
             
                return rb_hash_new();
         | 
| 485 514 | 
             
            }
         | 
| 486 515 |  | 
| 487 | 
            -
            static VALUE calc_hash_key(ParseInfo pi, Val parent) {
         | 
| 488 | 
            -
                volatile VALUE rkey = parent->key_val;
         | 
| 489 | 
            -
             | 
| 490 | 
            -
                if (Qundef == rkey) {
         | 
| 491 | 
            -
                    rkey = rb_str_new(parent->key, parent->klen);
         | 
| 492 | 
            -
                }
         | 
| 493 | 
            -
                rkey = oj_encode(rkey);
         | 
| 494 | 
            -
                rkey = rb_str_intern(rkey);
         | 
| 495 | 
            -
             | 
| 496 | 
            -
                return rkey;
         | 
| 497 | 
            -
            }
         | 
| 498 | 
            -
             | 
| 499 516 | 
             
            static void hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
         | 
| 500 | 
            -
                volatile VALUE rval = cstr_to_rstr(str, len);
         | 
| 517 | 
            +
                volatile VALUE rval = cstr_to_rstr(pi, str, len);
         | 
| 501 518 |  | 
| 502 519 | 
             
                rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rval);
         | 
| 503 520 | 
             
                if (Yes == pi->options.trace) {
         | 
| @@ -533,7 +550,7 @@ static VALUE start_array(ParseInfo pi) { | |
| 533 550 | 
             
            }
         | 
| 534 551 |  | 
| 535 552 | 
             
            static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
         | 
| 536 | 
            -
                volatile VALUE rval = cstr_to_rstr(str, len);
         | 
| 553 | 
            +
                volatile VALUE rval = cstr_to_rstr(pi, str, len);
         | 
| 537 554 |  | 
| 538 555 | 
             
                rb_ary_push(stack_peek(&pi->stack)->val, rval);
         | 
| 539 556 | 
             
                if (Yes == pi->options.trace) {
         | 
    
        data/lib/oj/mimic.rb
    CHANGED
    
    
    
        data/lib/oj/version.rb
    CHANGED
    
    
    
        data/pages/Options.md
    CHANGED
    
    | @@ -251,7 +251,13 @@ compatibility. Using just indent as an integer gives better performance. | |
| 251 251 |  | 
| 252 252 | 
             
            ### :symbol_keys [Boolean]
         | 
| 253 253 |  | 
| 254 | 
            -
            Use symbols instead of strings for hash keys. | 
| 254 | 
            +
            Use symbols instead of strings for hash keys.
         | 
| 255 | 
            +
             | 
| 256 | 
            +
            ### :symbolize_names [Boolean]
         | 
| 257 | 
            +
             | 
| 258 | 
            +
            Like :symbol_keys has keys are made into symbols but only when
         | 
| 259 | 
            +
            mimicing the JSON gem and then only as the JSON gem honors it so
         | 
| 260 | 
            +
            JSON.parse honors the option but JSON.load does not.
         | 
| 255 261 |  | 
| 256 262 | 
             
            ### :trace
         | 
| 257 263 |  | 
    
        data/test/foo.rb
    CHANGED
    
    | @@ -7,14 +7,7 @@ $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__))) | |
| 7 7 | 
             
            end
         | 
| 8 8 |  | 
| 9 9 | 
             
            require 'oj'
         | 
| 10 | 
            -
            require 'active_support'
         | 
| 11 10 |  | 
| 12 | 
            -
             | 
| 11 | 
            +
            p = Oj::Parser.new(:debug)
         | 
| 13 12 |  | 
| 14 | 
            -
             | 
| 15 | 
            -
            #Oj.mimic_JSON
         | 
| 16 | 
            -
            begin
         | 
| 17 | 
            -
              ::JSON.load('foo=&bar')
         | 
| 18 | 
            -
            rescue Exception => e
         | 
| 19 | 
            -
              puts "*** #{e.class}: #{e.message}"
         | 
| 20 | 
            -
            end
         | 
| 13 | 
            +
            p.parse("[true, false]")
         | 
    
        data/test/perf.rb
    CHANGED
    
    
    
        data/test/perf_scp.rb
    CHANGED
    
    | @@ -14,16 +14,16 @@ require 'oj' | |
| 14 14 |  | 
| 15 15 | 
             
            $verbose = false
         | 
| 16 16 | 
             
            $indent = 0
         | 
| 17 | 
            -
            $iter =  | 
| 17 | 
            +
            $iter = 50_000
         | 
| 18 18 | 
             
            $with_bignum = false
         | 
| 19 | 
            -
            $size =  | 
| 19 | 
            +
            $size = 1
         | 
| 20 20 |  | 
| 21 21 | 
             
            opts = OptionParser.new
         | 
| 22 22 | 
             
            opts.on("-v", "verbose")                                  { $verbose = true }
         | 
| 23 23 | 
             
            opts.on("-c", "--count [Int]", Integer, "iterations")     { |i| $iter = i }
         | 
| 24 24 | 
             
            opts.on("-i", "--indent [Int]", Integer, "indentation")   { |i| $indent = i }
         | 
| 25 | 
            -
            opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") | 
| 26 | 
            -
            opts.on("-b", "with bignum") | 
| 25 | 
            +
            opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)")  { |i| $size = i }
         | 
| 26 | 
            +
            opts.on("-b", "with bignum")                              { $with_bignum = true }
         | 
| 27 27 | 
             
            opts.on("-h", "--help", "Show this display")              { puts opts; Process.exit!(0) }
         | 
| 28 28 | 
             
            files = opts.parse(ARGV)
         | 
| 29 29 |  | 
| @@ -47,7 +47,7 @@ if 0 < $size | |
| 47 47 | 
             
              end
         | 
| 48 48 | 
             
            end
         | 
| 49 49 |  | 
| 50 | 
            -
            Oj.default_options = { :indent => $indent, :mode => : | 
| 50 | 
            +
            Oj.default_options = { :indent => $indent, :mode => :strict, cache_keys: true, cache_str: 5 }
         | 
| 51 51 |  | 
| 52 52 | 
             
            $json = Oj.dump($obj)
         | 
| 53 53 | 
             
            $failed = {} # key is same as String used in tests later
         | 
| @@ -105,7 +105,7 @@ class AllHandler < Oj::ScHandler | |
| 105 105 |  | 
| 106 106 | 
             
              def hash_set(h, key, value)
         | 
| 107 107 | 
             
              end
         | 
| 108 | 
            -
             | 
| 108 | 
            +
             | 
| 109 109 | 
             
              def array_append(a, value)
         | 
| 110 110 | 
             
              end
         | 
| 111 111 |  | 
| @@ -137,10 +137,11 @@ end | |
| 137 137 | 
             
            puts '-' * 80
         | 
| 138 138 | 
             
            puts "Parse Performance"
         | 
| 139 139 | 
             
            perf = Perf.new()
         | 
| 140 | 
            -
            perf.add('Oj::Saj', 'all') { Oj.saj_parse(saj_handler, $json) }
         | 
| 141 | 
            -
            perf.add('Oj::Saj', 'none') { Oj.saj_parse(no_saj, $json) }
         | 
| 142 | 
            -
            perf.add('Oj::Scp', 'all') { Oj.sc_parse(sc_handler, $json) }
         | 
| 143 | 
            -
            perf.add('Oj::Scp', 'none') { Oj.sc_parse(no_handler, $json) }
         | 
| 140 | 
            +
            perf.add('Oj::Saj.all', 'all') { Oj.saj_parse(saj_handler, $json) }
         | 
| 141 | 
            +
            perf.add('Oj::Saj.none', 'none') { Oj.saj_parse(no_saj, $json) }
         | 
| 142 | 
            +
            perf.add('Oj::Scp.all', 'all') { Oj.sc_parse(sc_handler, $json) }
         | 
| 143 | 
            +
            perf.add('Oj::Scp.none', 'none') { Oj.sc_parse(no_handler, $json) }
         | 
| 144 | 
            +
            perf.add('Oj::load', 'none') { Oj.wab_load($json) }
         | 
| 144 145 | 
             
            perf.add('Yajl', 'parse') { Yajl::Parser.parse($json) } unless $failed.has_key?('Yajl')
         | 
| 145 146 | 
             
            perf.add('JSON::Ext', 'parse') { JSON::Ext::Parser.new($json).parse } unless $failed.has_key?('JSON::Ext')
         | 
| 146 147 | 
             
            perf.run($iter)
         | 
    
        data/test/perf_strict.rb
    CHANGED
    
    | @@ -15,6 +15,8 @@ $iter = 20000 | |
| 15 15 | 
             
            $with_bignum = false
         | 
| 16 16 | 
             
            $with_nums = true
         | 
| 17 17 | 
             
            $size = 0
         | 
| 18 | 
            +
            $symbolize = false
         | 
| 19 | 
            +
            $cache_keys = true
         | 
| 18 20 |  | 
| 19 21 | 
             
            opts = OptionParser.new
         | 
| 20 22 | 
             
            opts.on("-v", "verbose")                                    { $verbose = true }
         | 
| @@ -23,6 +25,8 @@ opts.on("-i", "--indent [Int]", Integer, "indentation")     { |i| $indent = i } | |
| 23 25 | 
             
            opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)")    { |i| $size = i }
         | 
| 24 26 | 
             
            opts.on("-b", "with bignum")                                { $with_bignum = true }
         | 
| 25 27 | 
             
            opts.on("-n", "without numbers")                            { $with_nums = false }
         | 
| 28 | 
            +
            opts.on("-z", "--symbolize", "symbolize keys")              { $symbolize = true }
         | 
| 29 | 
            +
            opts.on("-k", "--no-cache", "turn off key caching")         { $cache_keys = false }
         | 
| 26 30 | 
             
            opts.on("-h", "--help", "Show this display")                { puts opts; Process.exit!(0) }
         | 
| 27 31 | 
             
            files = opts.parse(ARGV)
         | 
| 28 32 |  | 
| @@ -51,7 +55,7 @@ else | |
| 51 55 | 
             
              }
         | 
| 52 56 | 
             
            end
         | 
| 53 57 |  | 
| 54 | 
            -
            Oj.default_options = { :indent => $indent, :mode => :strict }
         | 
| 58 | 
            +
            Oj.default_options = { :indent => $indent, :mode => :strict, cache_keys: $cache_keys, cache_str: 5 }
         | 
| 55 59 |  | 
| 56 60 | 
             
            if 0 < $size
         | 
| 57 61 | 
             
              o = $obj
         | 
| @@ -62,9 +66,6 @@ if 0 < $size | |
| 62 66 | 
             
            end
         | 
| 63 67 |  | 
| 64 68 | 
             
            $json = Oj.dump($obj)
         | 
| 65 | 
            -
            $obj_json = Oj.dump($obj, :mode => :object)
         | 
| 66 | 
            -
            #puts "*** size: #{$obj_json.size}"
         | 
| 67 | 
            -
            #puts "*** #{$obj_json}"
         | 
| 68 69 | 
             
            $failed = {} # key is same as String used in tests later
         | 
| 69 70 |  | 
| 70 71 | 
             
            def capture_error(tag, orig, load_key, dump_key, &blk)
         | 
| @@ -77,8 +78,13 @@ def capture_error(tag, orig, load_key, dump_key, &blk) | |
| 77 78 | 
             
            end
         | 
| 78 79 |  | 
| 79 80 | 
             
            # Verify that all packages dump and load correctly and return the same Object as the original.
         | 
| 80 | 
            -
            capture_error('Oj:strict', $obj, 'load', 'dump') { |o| | 
| 81 | 
            -
             | 
| 81 | 
            +
            capture_error('Oj:strict', $obj, 'load', 'dump') { |o|
         | 
| 82 | 
            +
              Oj.strict_load(Oj.dump(o))
         | 
| 83 | 
            +
            }
         | 
| 84 | 
            +
            capture_error('Yajl', $obj, 'encode', 'parse') { |o|
         | 
| 85 | 
            +
              require 'yajl'
         | 
| 86 | 
            +
              Yajl::Parser.parse(Yajl::Encoder.encode(o))
         | 
| 87 | 
            +
            }
         | 
| 82 88 | 
             
            capture_error('JSON::Ext', $obj, 'generate', 'parse') { |o|
         | 
| 83 89 | 
             
              require 'json'
         | 
| 84 90 | 
             
              require 'json/ext'
         | 
| @@ -86,16 +92,11 @@ capture_error('JSON::Ext', $obj, 'generate', 'parse') { |o| | |
| 86 92 | 
             
              JSON.parser = JSON::Ext::Parser
         | 
| 87 93 | 
             
              JSON.parse(JSON.generate(o))
         | 
| 88 94 | 
             
            }
         | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
              JSON.generator = JSON::Pure::Generator
         | 
| 92 | 
            -
              JSON.parser = JSON::Pure::Parser
         | 
| 93 | 
            -
              JSON.parse(JSON.generate(o))
         | 
| 94 | 
            -
            }
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            Oj.default_options = { symbol_keys: $symbolize }
         | 
| 95 97 |  | 
| 96 98 | 
             
            if $verbose
         | 
| 97 99 | 
             
              puts "json:\n#{$json}\n"
         | 
| 98 | 
            -
              puts "object json:\n#{$obj_json}\n"
         | 
| 99 100 | 
             
              puts "Oj loaded object:\n#{Oj.strict_load($json)}\n"
         | 
| 100 101 | 
             
              puts "Yajl loaded object:\n#{Yajl::Parser.parse($json)}\n"
         | 
| 101 102 | 
             
              puts "JSON loaded object:\n#{JSON::Ext::Parser.new($json).parse}\n"
         | 
| @@ -105,15 +106,12 @@ puts '-' * 80 | |
| 105 106 | 
             
            puts "Strict Parse Performance"
         | 
| 106 107 | 
             
            perf = Perf.new()
         | 
| 107 108 | 
             
            unless $failed.has_key?('JSON::Ext')
         | 
| 108 | 
            -
              perf.add('JSON::Ext', 'parse') { JSON.parse($json) }
         | 
| 109 | 
            +
              perf.add('JSON::Ext', 'parse') { JSON.parse($json, symbolize_names: $symbolize) }
         | 
| 109 110 | 
             
              perf.before('JSON::Ext') { JSON.parser = JSON::Ext::Parser }
         | 
| 110 111 | 
             
            end
         | 
| 111 | 
            -
            unless $failed.has_key?('JSON::Pure')
         | 
| 112 | 
            -
              perf.add('JSON::Pure', 'parse') { JSON.parse($json) }
         | 
| 113 | 
            -
              perf.before('JSON::Pure') { JSON.parser = JSON::Pure::Parser }
         | 
| 114 | 
            -
            end
         | 
| 115 112 | 
             
            unless $failed.has_key?('Oj:strict')
         | 
| 116 113 | 
             
              perf.add('Oj:strict', 'strict_load') { Oj.strict_load($json) }
         | 
| 114 | 
            +
              perf.add('Oj:wab', 'wab_load') { Oj.wab_load($json) }
         | 
| 117 115 | 
             
            end
         | 
| 118 116 | 
             
            perf.add('Yajl', 'parse') { Yajl::Parser.parse($json) } unless $failed.has_key?('Yajl')
         | 
| 119 117 | 
             
            perf.run($iter)
         | 
| @@ -125,12 +123,8 @@ unless $failed.has_key?('JSON::Ext') | |
| 125 123 | 
             
              perf.add('JSON::Ext', 'dump') { JSON.generate($obj) }
         | 
| 126 124 | 
             
              perf.before('JSON::Ext') { JSON.generator = JSON::Ext::Generator }
         | 
| 127 125 | 
             
            end
         | 
| 128 | 
            -
            unless $failed.has_key?('JSON::Pure')
         | 
| 129 | 
            -
              perf.add('JSON::Pure', 'generate') { JSON.generate($obj) }
         | 
| 130 | 
            -
              perf.before('JSON::Pure') { JSON.generator = JSON::Pure::Generator }
         | 
| 131 | 
            -
            end
         | 
| 132 126 | 
             
            unless $failed.has_key?('Oj:strict')
         | 
| 133 | 
            -
              perf.add('Oj:strict', 'dump') { Oj.dump($obj | 
| 127 | 
            +
              perf.add('Oj:strict', 'dump') { Oj.dump($obj) }
         | 
| 134 128 | 
             
            end
         | 
| 135 129 | 
             
            perf.add('Yajl', 'encode') { Yajl::Encoder.encode($obj) } unless $failed.has_key?('Yajl')
         | 
| 136 130 | 
             
            perf.run($iter)
         | 
    
        data/test/test_various.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: oj
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 3. | 
| 4 | 
            +
              version: 3.12.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Peter Ohler
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2021- | 
| 11 | 
            +
            date: 2021-07-25 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: rake-compiler
         | 
| @@ -285,7 +285,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 285 285 | 
             
                - !ruby/object:Gem::Version
         | 
| 286 286 | 
             
                  version: '0'
         | 
| 287 287 | 
             
            requirements: []
         | 
| 288 | 
            -
            rubygems_version: 3.2. | 
| 288 | 
            +
            rubygems_version: 3.2.22
         | 
| 289 289 | 
             
            signing_key:
         | 
| 290 290 | 
             
            specification_version: 4
         | 
| 291 291 | 
             
            summary: A fast JSON parser and serializer.
         |