oj 3.13.7 → 3.13.8
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.md +13 -0
 - data/ext/oj/fast.c +6 -2
 - data/ext/oj/intern.c +7 -1
 - data/ext/oj/object.c +26 -45
 - data/ext/oj/parse.c +9 -1
 - data/ext/oj/usual.c +4 -2
 - data/lib/oj/version.rb +1 -1
 - data/test/bug.rb +16 -0
 - data/test/foo.rb +9 -8
 - data/test/test_fast.rb +18 -7
 - metadata +4 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 182e77505f61b9f1327d36552a04ac18a960831d01d675b02ec00ec6e33d3239
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 4b56206268f665fe45a8cbd63b605bab35a0adf834e2ad1d603d4e99a1d8b118
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: cc57186d14210b95b7875948ceb2e1782f7a3223cfabcf7e45a5cad617eba67fe506bfe17820decf1881d341e6233c114f617c3ad8395033d75c7be8b72804b9
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: cc069dec094cde64f098fa65131d81f6552f2302af87730e19442ad027ad5722f7d6555de1e4a888196b994fcbb8f809f3892a10b05afd955b805851e7d53928
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    | 
         @@ -1,5 +1,18 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # CHANGELOG
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            ## 3.13.8 - 2021-09-27
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            - Fix `Oj::Doc` behaviour for inexisting path.
         
     | 
| 
      
 7 
     | 
    
         
            +
              ```ruby
         
     | 
| 
      
 8 
     | 
    
         
            +
              Oj::Doc.open('{"foo":1}') do |doc|
         
     | 
| 
      
 9 
     | 
    
         
            +
                doc.fetch('/foo/bar') # used to give `1`, now gives `nil`
         
     | 
| 
      
 10 
     | 
    
         
            +
                doc.exists?('/foo/bar') # used to give `true`, now gives `false`
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
              ```
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            - Fix `Oj::Parser` handling of BigDecimal. `snprint()` does not handle `%Lg` correctly but `sprintf()` does.
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
       3 
16 
     | 
    
         
             
            ## 3.13.7 - 2021-09-16
         
     | 
| 
       4 
17 
     | 
    
         | 
| 
       5 
18 
     | 
    
         
             
            - The JSON gem allows invalid unicode so Oj, when mimicing JSON now
         
     | 
    
        data/ext/oj/fast.c
    CHANGED
    
    | 
         @@ -879,6 +879,10 @@ static Leaf get_leaf(Leaf *stack, Leaf *lp, const char *path) { 
     | 
|
| 
       879 
879 
     | 
    
         
             
                        }
         
     | 
| 
       880 
880 
     | 
    
         
             
                    } else if (NULL == leaf->elements) {
         
     | 
| 
       881 
881 
     | 
    
         
             
                        leaf = NULL;
         
     | 
| 
      
 882 
     | 
    
         
            +
                    } else if (STR_VAL == leaf->value_type || RUBY_VAL == leaf->value_type) {
         
     | 
| 
      
 883 
     | 
    
         
            +
                        // We are trying to get a children of a leaf, which
         
     | 
| 
      
 884 
     | 
    
         
            +
                        // doesn't exist.
         
     | 
| 
      
 885 
     | 
    
         
            +
                        leaf = NULL;
         
     | 
| 
       882 
886 
     | 
    
         
             
                    } else if (COL_VAL == leaf->value_type) {
         
     | 
| 
       883 
887 
     | 
    
         
             
                        Leaf first = leaf->elements->next;
         
     | 
| 
       884 
888 
     | 
    
         
             
                        Leaf e     = first;
         
     | 
| 
         @@ -1373,8 +1377,8 @@ static VALUE doc_fetch(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       1373 
1377 
     | 
    
         
             
             * Returns true if the value at the location identified by the path exists.
         
     | 
| 
       1374 
1378 
     | 
    
         
             
             *   @param [String] path path to the location
         
     | 
| 
       1375 
1379 
     | 
    
         
             
             * @example
         
     | 
| 
       1376 
     | 
    
         
            -
             *   Oj::Doc.open('[1,2]') { |doc| doc.exists('/1') }  #=> true
         
     | 
| 
       1377 
     | 
    
         
            -
             *   Oj::Doc.open('[1,2]') { |doc| doc.exists('/3') }  #=> false
         
     | 
| 
      
 1380 
     | 
    
         
            +
             *   Oj::Doc.open('[1,2]') { |doc| doc.exists?('/1') }  #=> true
         
     | 
| 
      
 1381 
     | 
    
         
            +
             *   Oj::Doc.open('[1,2]') { |doc| doc.exists?('/3') }  #=> false
         
     | 
| 
       1378 
1382 
     | 
    
         
             
             */
         
     | 
| 
       1379 
1383 
     | 
    
         
             
            static VALUE doc_exists(VALUE self, VALUE str) {
         
     | 
| 
       1380 
1384 
     | 
    
         
             
                Doc  doc;
         
     | 
    
        data/ext/oj/intern.c
    CHANGED
    
    | 
         @@ -186,6 +186,7 @@ static VALUE resolve_classpath(ParseInfo pi, const char *name, size_t len, int a 
     | 
|
| 
       186 
186 
     | 
    
         
             
                char *      end = class_name + sizeof(class_name) - 1;
         
     | 
| 
       187 
187 
     | 
    
         
             
                char *      s;
         
     | 
| 
       188 
188 
     | 
    
         
             
                const char *n = name;
         
     | 
| 
      
 189 
     | 
    
         
            +
                size_t	nlen = len;
         
     | 
| 
       189 
190 
     | 
    
         | 
| 
       190 
191 
     | 
    
         
             
                clas = rb_cObject;
         
     | 
| 
       191 
192 
     | 
    
         
             
                for (s = class_name; 0 < len; n++, len--) {
         
     | 
| 
         @@ -208,7 +209,12 @@ static VALUE resolve_classpath(ParseInfo pi, const char *name, size_t len, int a 
     | 
|
| 
       208 
209 
     | 
    
         
             
                }
         
     | 
| 
       209 
210 
     | 
    
         
             
                *s = '\0';
         
     | 
| 
       210 
211 
     | 
    
         
             
                if (Qundef == (clas = resolve_classname(clas, class_name, auto_define))) {
         
     | 
| 
       211 
     | 
    
         
            -
             
     | 
| 
      
 212 
     | 
    
         
            +
            	if (sizeof(class_name) <= nlen) {
         
     | 
| 
      
 213 
     | 
    
         
            +
            	    nlen = sizeof(class_name) - 1;
         
     | 
| 
      
 214 
     | 
    
         
            +
            	}
         
     | 
| 
      
 215 
     | 
    
         
            +
            	strncpy(class_name, name, nlen);
         
     | 
| 
      
 216 
     | 
    
         
            +
            	class_name[nlen] = '\0';
         
     | 
| 
      
 217 
     | 
    
         
            +
                    oj_set_error_at(pi, error_class, __FILE__, __LINE__, "class '%s' is not defined", class_name);
         
     | 
| 
       212 
218 
     | 
    
         
             
                    if (Qnil != error_class) {
         
     | 
| 
       213 
219 
     | 
    
         
             
                        pi->err_class = error_class;
         
     | 
| 
       214 
220 
     | 
    
         
             
                    }
         
     | 
    
        data/ext/oj/object.c
    CHANGED
    
    | 
         @@ -35,7 +35,7 @@ static VALUE calc_hash_key(ParseInfo pi, Val kval, char k1) { 
     | 
|
| 
       35 
35 
     | 
    
         
             
                    return ID2SYM(rb_intern3(kval->key + 1, kval->klen - 1, oj_utf8_encoding));
         
     | 
| 
       36 
36 
     | 
    
         
             
                }
         
     | 
| 
       37 
37 
     | 
    
         
             
                if (Yes == pi->options.sym_key) {
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
      
 38 
     | 
    
         
            +
                    return ID2SYM(rb_intern3(kval->key, kval->klen, oj_utf8_encoding));
         
     | 
| 
       39 
39 
     | 
    
         
             
                }
         
     | 
| 
       40 
40 
     | 
    
         
             
            #if HAVE_RB_ENC_INTERNED_STR
         
     | 
| 
       41 
41 
     | 
    
         
             
                rkey = rb_enc_interned_str(kval->key, kval->klen, oj_utf8_encoding);
         
     | 
| 
         @@ -60,21 +60,16 @@ static VALUE str_to_value(ParseInfo pi, const char *str, size_t len, const char 
     | 
|
| 
       60 
60 
     | 
    
         
             
                    }
         
     | 
| 
       61 
61 
     | 
    
         
             
                    rstr = oj_circ_array_get(pi->circ_array, i);
         
     | 
| 
       62 
62 
     | 
    
         
             
                } else {
         
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
      
 63 
     | 
    
         
            +
                    rstr = rb_utf8_str_new(str, len);
         
     | 
| 
       64 
64 
     | 
    
         
             
                }
         
     | 
| 
       65 
65 
     | 
    
         
             
                return rstr;
         
     | 
| 
       66 
66 
     | 
    
         
             
            }
         
     | 
| 
       67 
67 
     | 
    
         | 
| 
       68 
     | 
    
         
            -
            #if (RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8)
         
     | 
| 
       69 
     | 
    
         
            -
            static VALUE oj_parse_xml_time(const char *str, int len) {
         
     | 
| 
       70 
     | 
    
         
            -
                return rb_funcall(rb_cTime, oj_parse_id, 1, rb_str_new(str, len));
         
     | 
| 
       71 
     | 
    
         
            -
            }
         
     | 
| 
       72 
     | 
    
         
            -
            #else
         
     | 
| 
       73 
68 
     | 
    
         
             
            // The much faster approach (4x faster)
         
     | 
| 
       74 
69 
     | 
    
         
             
            static int parse_num(const char *str, const char *end, int cnt) {
         
     | 
| 
       75 
     | 
    
         
            -
                int 
     | 
| 
      
 70 
     | 
    
         
            +
                int n = 0;
         
     | 
| 
       76 
71 
     | 
    
         
             
                char c;
         
     | 
| 
       77 
     | 
    
         
            -
                int 
     | 
| 
      
 72 
     | 
    
         
            +
                int i;
         
     | 
| 
       78 
73 
     | 
    
         | 
| 
       79 
74 
     | 
    
         
             
                for (i = cnt; 0 < i; i--, str++) {
         
     | 
| 
       80 
75 
     | 
    
         
             
                    c = *str;
         
     | 
| 
         @@ -88,9 +83,9 @@ static int parse_num(const char *str, const char *end, int cnt) { 
     | 
|
| 
       88 
83 
     | 
    
         | 
| 
       89 
84 
     | 
    
         
             
            VALUE
         
     | 
| 
       90 
85 
     | 
    
         
             
            oj_parse_xml_time(const char *str, int len) {
         
     | 
| 
       91 
     | 
    
         
            -
                VALUE 
     | 
| 
      
 86 
     | 
    
         
            +
                VALUE args[8];
         
     | 
| 
       92 
87 
     | 
    
         
             
                const char *end = str + len;
         
     | 
| 
       93 
     | 
    
         
            -
                int 
     | 
| 
      
 88 
     | 
    
         
            +
                int n;
         
     | 
| 
       94 
89 
     | 
    
         | 
| 
       95 
90 
     | 
    
         
             
                // year
         
     | 
| 
       96 
91 
     | 
    
         
             
                if (0 > (n = parse_num(str, end, 4))) {
         
     | 
| 
         @@ -201,7 +196,6 @@ oj_parse_xml_time(const char *str, int len) { 
     | 
|
| 
       201 
196 
     | 
    
         
             
                }
         
     | 
| 
       202 
197 
     | 
    
         
             
                return rb_funcall2(rb_cTime, oj_new_id, 7, args);
         
     | 
| 
       203 
198 
     | 
    
         
             
            }
         
     | 
| 
       204 
     | 
    
         
            -
            #endif
         
     | 
| 
       205 
199 
     | 
    
         | 
| 
       206 
200 
     | 
    
         
             
            static int hat_cstr(ParseInfo pi, Val parent, Val kval, const char *str, size_t len) {
         
     | 
| 
       207 
201 
     | 
    
         
             
                const char *key  = kval->key;
         
     | 
| 
         @@ -226,13 +220,10 @@ static int hat_cstr(ParseInfo pi, Val parent, Val kval, const char *str, size_t 
     | 
|
| 
       226 
220 
     | 
    
         
             
                        }
         
     | 
| 
       227 
221 
     | 
    
         
             
                        parent->val      = odd->clas;
         
     | 
| 
       228 
222 
     | 
    
         
             
                        parent->odd_args = oj_odd_alloc_args(odd);
         
     | 
| 
       229 
     | 
    
         
            -
                    } break;
         
     | 
| 
       230 
     | 
    
         
            -
                    case 'm':
         
     | 
| 
       231 
     | 
    
         
            -
                        parent->val = ID2SYM(rb_intern3(str + 1, len - 1, oj_utf8_encoding));
         
     | 
| 
       232 
     | 
    
         
            -
                        break;
         
     | 
| 
       233 
     | 
    
         
            -
                    case 's':
         
     | 
| 
       234 
     | 
    
         
            -
            	    parent->val = rb_utf8_str_new(str, len);
         
     | 
| 
       235 
223 
     | 
    
         
             
                        break;
         
     | 
| 
      
 224 
     | 
    
         
            +
                    }
         
     | 
| 
      
 225 
     | 
    
         
            +
                    case 'm': parent->val = ID2SYM(rb_intern3(str + 1, len - 1, oj_utf8_encoding)); break;
         
     | 
| 
      
 226 
     | 
    
         
            +
                    case 's': parent->val = rb_utf8_str_new(str, len); break;
         
     | 
| 
       236 
227 
     | 
    
         
             
                    case 'c':  // class
         
     | 
| 
       237 
228 
     | 
    
         
             
                    {
         
     | 
| 
       238 
229 
     | 
    
         
             
                        VALUE clas = oj_name2class(pi, str, len, Yes == pi->options.auto_define, rb_eArgError);
         
     | 
| 
         @@ -242,7 +233,8 @@ static int hat_cstr(ParseInfo pi, Val parent, Val kval, const char *str, size_t 
     | 
|
| 
       242 
233 
     | 
    
         
             
                        } else {
         
     | 
| 
       243 
234 
     | 
    
         
             
                            parent->val = clas;
         
     | 
| 
       244 
235 
     | 
    
         
             
                        }
         
     | 
| 
       245 
     | 
    
         
            -
             
     | 
| 
      
 236 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 237 
     | 
    
         
            +
                    }
         
     | 
| 
       246 
238 
     | 
    
         
             
                    case 't':  // time
         
     | 
| 
       247 
239 
     | 
    
         
             
                        parent->val = oj_parse_xml_time(str, (int)len);
         
     | 
| 
       248 
240 
     | 
    
         
             
                        break;
         
     | 
| 
         @@ -282,22 +274,21 @@ static int hat_num(ParseInfo pi, Val parent, Val kval, NumInfo ni) { 
     | 
|
| 
       282 
274 
     | 
    
         
             
                                VALUE            args[8];
         
     | 
| 
       283 
275 
     | 
    
         | 
| 
       284 
276 
     | 
    
         
             
                                sec_as_time(t, &ti);
         
     | 
| 
       285 
     | 
    
         
            -
                                args[0] 
     | 
| 
       286 
     | 
    
         
            -
                                args[1] 
     | 
| 
       287 
     | 
    
         
            -
                                args[2] 
     | 
| 
       288 
     | 
    
         
            -
                                args[3] 
     | 
| 
       289 
     | 
    
         
            -
                                args[4] 
     | 
| 
       290 
     | 
    
         
            -
                                args[5] 
     | 
| 
       291 
     | 
    
         
            -
                                args[6] 
     | 
| 
      
 277 
     | 
    
         
            +
                                args[0]     = LONG2NUM((long)(ti.year));
         
     | 
| 
      
 278 
     | 
    
         
            +
                                args[1]     = LONG2NUM(ti.mon);
         
     | 
| 
      
 279 
     | 
    
         
            +
                                args[2]     = LONG2NUM(ti.day);
         
     | 
| 
      
 280 
     | 
    
         
            +
                                args[3]     = LONG2NUM(ti.hour);
         
     | 
| 
      
 281 
     | 
    
         
            +
                                args[4]     = LONG2NUM(ti.min);
         
     | 
| 
      
 282 
     | 
    
         
            +
                                args[5]     = rb_float_new((double)ti.sec + ((double)nsec + 0.5) / 1000000000.0);
         
     | 
| 
      
 283 
     | 
    
         
            +
                                args[6]     = LONG2NUM(ni->exp);
         
     | 
| 
       292 
284 
     | 
    
         
             
                                parent->val = rb_funcall2(rb_cTime, oj_new_id, 7, args);
         
     | 
| 
       293 
285 
     | 
    
         
             
                            } else {
         
     | 
| 
       294 
286 
     | 
    
         
             
                                parent->val = rb_time_nano_new(ni->i, (long)nsec);
         
     | 
| 
       295 
287 
     | 
    
         
             
                            }
         
     | 
| 
       296 
288 
     | 
    
         
             
                        }
         
     | 
| 
       297 
289 
     | 
    
         
             
                        break;
         
     | 
| 
       298 
     | 
    
         
            -
                    case 'i': 
     | 
| 
       299 
     | 
    
         
            -
                        if (!ni->infinity && !ni->neg && 1 == ni->div && 0 == ni->exp &&
         
     | 
| 
       300 
     | 
    
         
            -
                            0 != pi->circ_array) {  // fixnum
         
     | 
| 
      
 290 
     | 
    
         
            +
                    case 'i':                                                                                    // circular index
         
     | 
| 
      
 291 
     | 
    
         
            +
                        if (!ni->infinity && !ni->neg && 1 == ni->div && 0 == ni->exp && 0 != pi->circ_array) {  // fixnum
         
     | 
| 
       301 
292 
     | 
    
         
             
                            if (Qnil == parent->val) {
         
     | 
| 
       302 
293 
     | 
    
         
             
                                parent->val = rb_hash_new();
         
     | 
| 
       303 
294 
     | 
    
         
             
                            }
         
     | 
| 
         @@ -402,9 +393,7 @@ WHICH_TYPE: 
     | 
|
| 
       402 
393 
     | 
    
         
             
                    }
         
     | 
| 
       403 
394 
     | 
    
         
             
                    break;
         
     | 
| 
       404 
395 
     | 
    
         
             
                case T_HASH:
         
     | 
| 
       405 
     | 
    
         
            -
                    rb_hash_aset(parent->val,
         
     | 
| 
       406 
     | 
    
         
            -
                                 calc_hash_key(pi, kval, parent->k1),
         
     | 
| 
       407 
     | 
    
         
            -
                                 str_to_value(pi, str, len, orig));
         
     | 
| 
      
 396 
     | 
    
         
            +
                    rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), str_to_value(pi, str, len, orig));
         
     | 
| 
       408 
397 
     | 
    
         
             
                    break;
         
     | 
| 
       409 
398 
     | 
    
         
             
                case T_STRING:
         
     | 
| 
       410 
399 
     | 
    
         
             
                    rval = str_to_value(pi, str, len, orig);
         
     | 
| 
         @@ -481,8 +470,8 @@ WHICH_TYPE: 
     | 
|
| 
       481 
470 
     | 
    
         
             
                    rb_hash_aset(parent->val, calc_hash_key(pi, kval, parent->k1), rval);
         
     | 
| 
       482 
471 
     | 
    
         
             
                    break;
         
     | 
| 
       483 
472 
     | 
    
         
             
                case T_OBJECT:
         
     | 
| 
       484 
     | 
    
         
            -
                    if (2 == klen && '^' == *key && 'i' == key[1] && !ni->infinity && !ni->neg &&
         
     | 
| 
       485 
     | 
    
         
            -
                         
     | 
| 
      
 473 
     | 
    
         
            +
                    if (2 == klen && '^' == *key && 'i' == key[1] && !ni->infinity && !ni->neg && 1 == ni->div && 0 == ni->exp &&
         
     | 
| 
      
 474 
     | 
    
         
            +
                        0 != pi->circ_array) {  // fixnum
         
     | 
| 
       486 
475 
     | 
    
         
             
                        oj_circ_array_set(pi->circ_array, parent->val, ni->i);
         
     | 
| 
       487 
476 
     | 
    
         
             
                    } else {
         
     | 
| 
       488 
477 
     | 
    
         
             
                        rval = oj_num_as_value(ni);
         
     | 
| 
         @@ -559,11 +548,7 @@ WHICH_TYPE: 
     | 
|
| 
       559 
548 
     | 
    
         
             
                            volatile VALUE *a   = RARRAY_PTR(value);
         
     | 
| 
       560 
549 
     | 
    
         | 
| 
       561 
550 
     | 
    
         
             
                            if (2 != len) {
         
     | 
| 
       562 
     | 
    
         
            -
                                oj_set_error_at(pi,
         
     | 
| 
       563 
     | 
    
         
            -
                                                oj_parse_error_class,
         
     | 
| 
       564 
     | 
    
         
            -
                                                __FILE__,
         
     | 
| 
       565 
     | 
    
         
            -
                                                __LINE__,
         
     | 
| 
       566 
     | 
    
         
            -
                                                "invalid hash pair");
         
     | 
| 
      
 551 
     | 
    
         
            +
                                oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid hash pair");
         
     | 
| 
       567 
552 
     | 
    
         
             
                                return;
         
     | 
| 
       568 
553 
     | 
    
         
             
                            }
         
     | 
| 
       569 
554 
     | 
    
         
             
                            rb_hash_aset(parent->val, *a, a[1]);
         
     | 
| 
         @@ -637,10 +622,7 @@ static void end_hash(ParseInfo pi) { 
     | 
|
| 
       637 
622 
     | 
    
         
             
                } else if (NULL != parent->odd_args) {
         
     | 
| 
       638 
623 
     | 
    
         
             
                    OddArgs oa = parent->odd_args;
         
     | 
| 
       639 
624 
     | 
    
         | 
| 
       640 
     | 
    
         
            -
                    parent->val = rb_funcall2(oa->odd->create_obj,
         
     | 
| 
       641 
     | 
    
         
            -
                                              oa->odd->create_op,
         
     | 
| 
       642 
     | 
    
         
            -
                                              oa->odd->attr_cnt,
         
     | 
| 
       643 
     | 
    
         
            -
                                              oa->args);
         
     | 
| 
      
 625 
     | 
    
         
            +
                    parent->val = rb_funcall2(oa->odd->create_obj, oa->odd->create_op, oa->odd->attr_cnt, oa->args);
         
     | 
| 
       644 
626 
     | 
    
         
             
                    oj_odd_free(oa);
         
     | 
| 
       645 
627 
     | 
    
         
             
                    parent->odd_args = NULL;
         
     | 
| 
       646 
628 
     | 
    
         
             
                }
         
     | 
| 
         @@ -653,8 +635,7 @@ static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const c 
     | 
|
| 
       653 
635 
     | 
    
         
             
                volatile VALUE rval = Qnil;
         
     | 
| 
       654 
636 
     | 
    
         | 
| 
       655 
637 
     | 
    
         
             
                // orig lets us know whether the string was ^r1 or \u005er1
         
     | 
| 
       656 
     | 
    
         
            -
                if (3 <= len && 0 != pi->circ_array && '^' == orig[0] &&
         
     | 
| 
       657 
     | 
    
         
            -
                    0 == rb_array_len(stack_peek(&pi->stack)->val)) {
         
     | 
| 
      
 638 
     | 
    
         
            +
                if (3 <= len && 0 != pi->circ_array && '^' == orig[0] && 0 == rb_array_len(stack_peek(&pi->stack)->val)) {
         
     | 
| 
       658 
639 
     | 
    
         
             
                    if ('i' == str[1]) {
         
     | 
| 
       659 
640 
     | 
    
         
             
                        long i = read_long(str + 2, len - 2);
         
     | 
| 
       660 
641 
     | 
    
         | 
    
        data/ext/oj/parse.c
    CHANGED
    
    | 
         @@ -904,9 +904,17 @@ void oj_set_error_at(ParseInfo   pi, 
     | 
|
| 
       904 
904 
     | 
    
         
             
                char *  end = p + sizeof(msg) - 2;
         
     | 
| 
       905 
905 
     | 
    
         
             
                char *  start;
         
     | 
| 
       906 
906 
     | 
    
         
             
                Val     vp;
         
     | 
| 
      
 907 
     | 
    
         
            +
                int	mlen;
         
     | 
| 
       907 
908 
     | 
    
         | 
| 
       908 
909 
     | 
    
         
             
                va_start(ap, format);
         
     | 
| 
       909 
     | 
    
         
            -
                 
     | 
| 
      
 910 
     | 
    
         
            +
                mlen = vsnprintf(msg, sizeof(msg) - 1, format, ap);
         
     | 
| 
      
 911 
     | 
    
         
            +
                if (0 < mlen) {
         
     | 
| 
      
 912 
     | 
    
         
            +
            	if (sizeof(msg) - 2 < (size_t)mlen) {
         
     | 
| 
      
 913 
     | 
    
         
            +
            	    p = end - 2;
         
     | 
| 
      
 914 
     | 
    
         
            +
            	} else {
         
     | 
| 
      
 915 
     | 
    
         
            +
            	    p += mlen;
         
     | 
| 
      
 916 
     | 
    
         
            +
            	}
         
     | 
| 
      
 917 
     | 
    
         
            +
                }
         
     | 
| 
       910 
918 
     | 
    
         
             
                va_end(ap);
         
     | 
| 
       911 
919 
     | 
    
         
             
                pi->err.clas = err_clas;
         
     | 
| 
       912 
920 
     | 
    
         
             
                if (p + 3 < end) {
         
     | 
    
        data/ext/oj/usual.c
    CHANGED
    
    | 
         @@ -537,7 +537,7 @@ static void add_float_key(ojParser p) { 
     | 
|
| 
       537 
537 
     | 
    
         
             
            static void add_float_as_big(ojParser p) {
         
     | 
| 
       538 
538 
     | 
    
         
             
                char buf[64];
         
     | 
| 
       539 
539 
     | 
    
         | 
| 
       540 
     | 
    
         
            -
                // fails on ubuntu
         
     | 
| 
      
 540 
     | 
    
         
            +
                // snprintf fails on ubuntu and macOS for long double
         
     | 
| 
       541 
541 
     | 
    
         
             
                // snprintf(buf, sizeof(buf), "%Lg", p->num.dub);
         
     | 
| 
       542 
542 
     | 
    
         
             
                sprintf(buf, "%Lg", p->num.dub);
         
     | 
| 
       543 
543 
     | 
    
         
             
                push(p, rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(buf)));
         
     | 
| 
         @@ -546,7 +546,9 @@ static void add_float_as_big(ojParser p) { 
     | 
|
| 
       546 
546 
     | 
    
         
             
            static void add_float_as_big_key(ojParser p) {
         
     | 
| 
       547 
547 
     | 
    
         
             
                char buf[64];
         
     | 
| 
       548 
548 
     | 
    
         | 
| 
       549 
     | 
    
         
            -
                snprintf 
     | 
| 
      
 549 
     | 
    
         
            +
                // snprintf fails on ubuntu and macOS for long double
         
     | 
| 
      
 550 
     | 
    
         
            +
                // snprintf(buf, sizeof(buf), "%Lg", p->num.dub);
         
     | 
| 
      
 551 
     | 
    
         
            +
                sprintf(buf, "%Lg", p->num.dub);
         
     | 
| 
       550 
552 
     | 
    
         
             
                push_key(p);
         
     | 
| 
       551 
553 
     | 
    
         
             
                push2(p, rb_funcall(rb_cObject, oj_bigdecimal_id, 1, rb_str_new2(buf)));
         
     | 
| 
       552 
554 
     | 
    
         
             
            }
         
     | 
    
        data/lib/oj/version.rb
    CHANGED
    
    
    
        data/test/bug.rb
    ADDED
    
    | 
         @@ -0,0 +1,16 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            $: << '.'
         
     | 
| 
      
 2 
     | 
    
         
            +
            $: << File.join(File.dirname(__FILE__), "../lib")
         
     | 
| 
      
 3 
     | 
    
         
            +
            $: << File.join(File.dirname(__FILE__), "../ext")
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            #require 'bundler/setup'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'oj'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'active_support'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'active_support/time_with_zone'
         
     | 
| 
      
 10 
     | 
    
         
            +
            require 'tzinfo'
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            puts ActiveSupport::TimeWithZone
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            json = File.read('./bug.json')
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            Oj.load(json)
         
     | 
    
        data/test/foo.rb
    CHANGED
    
    | 
         @@ -1,13 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            #!/usr/bin/env ruby
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
      
 3 
     | 
    
         
            +
            $: << '.'
         
     | 
| 
      
 4 
     | 
    
         
            +
            $: << File.join(File.dirname(__FILE__), "../lib")
         
     | 
| 
      
 5 
     | 
    
         
            +
            $: << File.join(File.dirname(__FILE__), "../ext")
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
            puts "Oj version: #{Oj::VERSION}"
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'oj'
         
     | 
| 
       9 
8 
     | 
    
         | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
      
 9 
     | 
    
         
            +
            parser = Oj::Parser.new(:usual, cache_keys: true, cache_strings: 30, decimal: :bigdecimal, symbol_keys: false)
         
     | 
| 
      
 10 
     | 
    
         
            +
            raw = %({"amount":0.10})
         
     | 
| 
      
 11 
     | 
    
         
            +
            parsed = parser.parse(raw)
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
      
 13 
     | 
    
         
            +
            pp parsed
         
     | 
| 
      
 14 
     | 
    
         
            +
            puts parsed['amount'].class
         
     | 
    
        data/test/test_fast.rb
    CHANGED
    
    | 
         @@ -1,5 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            #!/usr/bin/env ruby
         
     | 
| 
       2 
     | 
    
         
            -
            #  
     | 
| 
      
 2 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            $: << File.dirname(__FILE__)
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
         @@ -36,6 +36,17 @@ class DocTest < Minitest::Test 
     | 
|
| 
       36 
36 
     | 
    
         
             
                end
         
     | 
| 
       37 
37 
     | 
    
         
             
              end
         
     | 
| 
       38 
38 
     | 
    
         | 
| 
      
 39 
     | 
    
         
            +
              def test_leaf_of_existing_path
         
     | 
| 
      
 40 
     | 
    
         
            +
                json = %{{"foo": 1, "fizz": true}}
         
     | 
| 
      
 41 
     | 
    
         
            +
                Oj::Doc.open(json) do |doc|
         
     | 
| 
      
 42 
     | 
    
         
            +
                  %w(/foo/bar /fizz/bar).each do |path|
         
     | 
| 
      
 43 
     | 
    
         
            +
                    assert_nil(doc.fetch(path))
         
     | 
| 
      
 44 
     | 
    
         
            +
                    assert_equal(:default, doc.fetch(path, :default))
         
     | 
| 
      
 45 
     | 
    
         
            +
                    refute(doc.exists?(path))
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
       39 
50 
     | 
    
         
             
              def test_true
         
     | 
| 
       40 
51 
     | 
    
         
             
                json = %{true}
         
     | 
| 
       41 
52 
     | 
    
         
             
                Oj::Doc.open(json) do |doc|
         
     | 
| 
         @@ -282,11 +293,11 @@ class DocTest < Minitest::Test 
     | 
|
| 
       282 
293 
     | 
    
         
             
                   ['/nothing', nil],
         
     | 
| 
       283 
294 
     | 
    
         
             
                   ['/array/10', nil],
         
     | 
| 
       284 
295 
     | 
    
         
             
                  ].each do |path,val|
         
     | 
| 
       285 
     | 
    
         
            -
             
     | 
| 
       286 
     | 
    
         
            -
             
     | 
| 
       287 
     | 
    
         
            -
             
     | 
| 
      
 296 
     | 
    
         
            +
                    if val.nil?
         
     | 
| 
      
 297 
     | 
    
         
            +
                      assert_nil(doc.fetch(path))
         
     | 
| 
      
 298 
     | 
    
         
            +
                    else
         
     | 
| 
       288 
299 
     | 
    
         
             
                      assert_equal(val, doc.fetch(path))
         
     | 
| 
       289 
     | 
    
         
            -
             
     | 
| 
      
 300 
     | 
    
         
            +
                    end
         
     | 
| 
       290 
301 
     | 
    
         
             
                  end
         
     | 
| 
       291 
302 
     | 
    
         
             
                end
         
     | 
| 
       292 
303 
     | 
    
         
             
                # verify empty hash and arrays return nil when a member is requested
         
     | 
| 
         @@ -313,7 +324,7 @@ class DocTest < Minitest::Test 
     | 
|
| 
       313 
324 
     | 
    
         
             
                end
         
     | 
| 
       314 
325 
     | 
    
         
             
              end
         
     | 
| 
       315 
326 
     | 
    
         | 
| 
       316 
     | 
    
         
            -
              def  
     | 
| 
      
 327 
     | 
    
         
            +
              def test_exists
         
     | 
| 
       317 
328 
     | 
    
         
             
                Oj::Doc.open(@json1) do |doc|
         
     | 
| 
       318 
329 
     | 
    
         
             
                  [['/array/1', true],
         
     | 
| 
       319 
330 
     | 
    
         
             
                   ['/array/1', true],
         
     | 
| 
         @@ -322,7 +333,7 @@ class DocTest < Minitest::Test 
     | 
|
| 
       322 
333 
     | 
    
         
             
                   ['/array/3', false],
         
     | 
| 
       323 
334 
     | 
    
         
             
                   ['/nothing', false],
         
     | 
| 
       324 
335 
     | 
    
         
             
                  ].each do |path,val|
         
     | 
| 
       325 
     | 
    
         
            -
                    assert_equal(val, doc.exists?(path))
         
     | 
| 
      
 336 
     | 
    
         
            +
                    assert_equal(val, doc.exists?(path), "failed for #{path.inspect}")
         
     | 
| 
       326 
337 
     | 
    
         
             
                  end
         
     | 
| 
       327 
338 
     | 
    
         
             
                end
         
     | 
| 
       328 
339 
     | 
    
         
             
              end
         
     | 
    
        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.13. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 3.13.8
         
     | 
| 
       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-09- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2021-09-27 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: rake-compiler
         
     | 
| 
         @@ -201,6 +201,7 @@ files: 
     | 
|
| 
       201 
201 
     | 
    
         
             
            - test/activesupport6/time_zone_test_helpers.rb
         
     | 
| 
       202 
202 
     | 
    
         
             
            - test/bar.rb
         
     | 
| 
       203 
203 
     | 
    
         
             
            - test/baz.rb
         
     | 
| 
      
 204 
     | 
    
         
            +
            - test/bug.rb
         
     | 
| 
       204 
205 
     | 
    
         
             
            - test/files.rb
         
     | 
| 
       205 
206 
     | 
    
         
             
            - test/foo.rb
         
     | 
| 
       206 
207 
     | 
    
         
             
            - test/helper.rb
         
     | 
| 
         @@ -332,6 +333,7 @@ test_files: 
     | 
|
| 
       332 
333 
     | 
    
         
             
            - test/activesupport6/time_zone_test_helpers.rb
         
     | 
| 
       333 
334 
     | 
    
         
             
            - test/bar.rb
         
     | 
| 
       334 
335 
     | 
    
         
             
            - test/baz.rb
         
     | 
| 
      
 336 
     | 
    
         
            +
            - test/bug.rb
         
     | 
| 
       335 
337 
     | 
    
         
             
            - test/files.rb
         
     | 
| 
       336 
338 
     | 
    
         
             
            - test/foo.rb
         
     | 
| 
       337 
339 
     | 
    
         
             
            - test/helper.rb
         
     |