oj 3.13.23 → 3.16.9
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 +81 -0
 - data/README.md +2 -2
 - data/ext/oj/buf.h +7 -6
 - data/ext/oj/cache.c +29 -26
 - data/ext/oj/cache.h +3 -2
 - data/ext/oj/cache8.c +10 -9
 - data/ext/oj/circarray.c +7 -5
 - data/ext/oj/circarray.h +2 -2
 - data/ext/oj/code.c +5 -12
 - data/ext/oj/code.h +2 -2
 - data/ext/oj/compat.c +20 -60
 - data/ext/oj/custom.c +26 -59
 - data/ext/oj/debug.c +3 -9
 - data/ext/oj/dump.c +103 -53
 - data/ext/oj/dump.h +1 -4
 - data/ext/oj/dump_compat.c +557 -592
 - data/ext/oj/dump_leaf.c +3 -5
 - data/ext/oj/dump_object.c +42 -48
 - data/ext/oj/dump_strict.c +10 -22
 - data/ext/oj/encoder.c +1 -1
 - data/ext/oj/err.c +2 -13
 - data/ext/oj/err.h +9 -12
 - data/ext/oj/extconf.rb +16 -7
 - data/ext/oj/fast.c +60 -92
 - data/ext/oj/intern.c +62 -47
 - data/ext/oj/intern.h +3 -7
 - data/ext/oj/mem.c +318 -0
 - data/ext/oj/mem.h +53 -0
 - data/ext/oj/mimic_json.c +51 -32
 - data/ext/oj/object.c +33 -43
 - data/ext/oj/odd.c +8 -6
 - data/ext/oj/odd.h +4 -4
 - data/ext/oj/oj.c +243 -212
 - data/ext/oj/oj.h +83 -81
 - data/ext/oj/parse.c +94 -148
 - data/ext/oj/parse.h +21 -24
 - data/ext/oj/parser.c +80 -67
 - data/ext/oj/parser.h +7 -8
 - data/ext/oj/rails.c +70 -92
 - data/ext/oj/reader.c +9 -14
 - data/ext/oj/reader.h +4 -2
 - data/ext/oj/resolve.c +3 -4
 - data/ext/oj/rxclass.c +6 -5
 - data/ext/oj/rxclass.h +1 -1
 - data/ext/oj/saj.c +10 -9
 - data/ext/oj/saj2.c +37 -49
 - data/ext/oj/saj2.h +1 -1
 - data/ext/oj/scp.c +3 -14
 - data/ext/oj/sparse.c +22 -70
 - data/ext/oj/stream_writer.c +45 -41
 - data/ext/oj/strict.c +20 -52
 - data/ext/oj/string_writer.c +64 -38
 - data/ext/oj/trace.h +31 -4
 - data/ext/oj/usual.c +125 -114
 - data/ext/oj/usual.h +7 -6
 - data/ext/oj/util.h +1 -1
 - data/ext/oj/val_stack.c +13 -2
 - data/ext/oj/val_stack.h +8 -7
 - data/ext/oj/wab.c +25 -57
 - data/lib/oj/active_support_helper.rb +1 -3
 - data/lib/oj/bag.rb +7 -1
 - data/lib/oj/easy_hash.rb +4 -5
 - data/lib/oj/error.rb +0 -1
 - data/lib/oj/json.rb +162 -150
 - data/lib/oj/mimic.rb +7 -7
 - data/lib/oj/schandler.rb +5 -4
 - data/lib/oj/state.rb +8 -5
 - data/lib/oj/version.rb +1 -2
 - data/lib/oj.rb +2 -0
 - data/pages/InstallOptions.md +20 -0
 - data/pages/Options.md +4 -0
 - data/test/_test_active.rb +8 -9
 - data/test/_test_active_mimic.rb +7 -8
 - data/test/_test_mimic_rails.rb +17 -20
 - data/test/activerecord/result_test.rb +5 -6
 - data/test/activesupport6/encoding_test.rb +63 -28
 - data/test/activesupport7/abstract_unit.rb +4 -1
 - data/test/activesupport7/encoding_test.rb +72 -22
 - data/test/files.rb +15 -15
 - data/test/foo.rb +18 -69
 - data/test/helper.rb +5 -8
 - data/test/isolated/shared.rb +3 -2
 - data/test/json_gem/json_addition_test.rb +2 -2
 - data/test/json_gem/json_common_interface_test.rb +8 -6
 - data/test/json_gem/json_encoding_test.rb +0 -0
 - data/test/json_gem/json_ext_parser_test.rb +1 -0
 - data/test/json_gem/json_fixtures_test.rb +3 -2
 - data/test/json_gem/json_generator_test.rb +50 -33
 - data/test/json_gem/json_generic_object_test.rb +11 -11
 - data/test/json_gem/json_parser_test.rb +46 -46
 - data/test/json_gem/json_string_matching_test.rb +9 -9
 - data/test/mem.rb +13 -12
 - data/test/perf.rb +21 -26
 - data/test/perf_compat.rb +31 -33
 - data/test/perf_dump.rb +28 -28
 - data/test/perf_fast.rb +80 -82
 - data/test/perf_file.rb +27 -29
 - data/test/perf_object.rb +65 -69
 - data/test/perf_once.rb +12 -11
 - data/test/perf_parser.rb +42 -48
 - data/test/perf_saj.rb +46 -54
 - data/test/perf_scp.rb +57 -69
 - data/test/perf_simple.rb +41 -39
 - data/test/perf_strict.rb +68 -70
 - data/test/perf_wab.rb +67 -69
 - data/test/prec.rb +5 -5
 - data/test/sample/change.rb +0 -1
 - data/test/sample/dir.rb +0 -1
 - data/test/sample/doc.rb +0 -1
 - data/test/sample/file.rb +0 -1
 - data/test/sample/group.rb +0 -1
 - data/test/sample/hasprops.rb +0 -1
 - data/test/sample/layer.rb +0 -1
 - data/test/sample/rect.rb +0 -1
 - data/test/sample/shape.rb +0 -1
 - data/test/sample/text.rb +0 -1
 - data/test/sample.rb +16 -16
 - data/test/sample_json.rb +8 -8
 - data/test/test_compat.rb +81 -54
 - data/test/test_custom.rb +63 -52
 - data/test/test_debian.rb +7 -10
 - data/test/test_fast.rb +86 -90
 - data/test/test_file.rb +24 -29
 - data/test/test_gc.rb +5 -5
 - data/test/test_generate.rb +5 -5
 - data/test/test_hash.rb +4 -4
 - data/test/test_integer_range.rb +9 -9
 - data/test/test_null.rb +20 -20
 - data/test/test_object.rb +92 -87
 - data/test/test_parser.rb +4 -4
 - data/test/test_parser_debug.rb +5 -5
 - data/test/test_parser_saj.rb +27 -25
 - data/test/test_parser_usual.rb +44 -6
 - data/test/test_rails.rb +2 -2
 - data/test/test_saj.rb +10 -8
 - data/test/test_scp.rb +35 -35
 - data/test/test_strict.rb +38 -32
 - data/test/test_various.rb +146 -97
 - data/test/test_wab.rb +46 -44
 - data/test/test_writer.rb +63 -47
 - data/test/tests.rb +7 -7
 - data/test/tests_mimic.rb +6 -6
 - data/test/tests_mimic_addition.rb +6 -6
 - metadata +46 -26
 - data/test/activesupport4/decoding_test.rb +0 -108
 - data/test/activesupport4/encoding_test.rb +0 -531
 - data/test/activesupport4/test_helper.rb +0 -41
 - data/test/activesupport5/abstract_unit.rb +0 -45
 - data/test/activesupport5/decoding_test.rb +0 -133
 - data/test/activesupport5/encoding_test.rb +0 -500
 - data/test/activesupport5/encoding_test_cases.rb +0 -98
 - data/test/activesupport5/test_helper.rb +0 -72
 - data/test/activesupport5/time_zone_test_helpers.rb +0 -39
 - data/test/bar.rb +0 -11
 - data/test/baz.rb +0 -16
 - data/test/bug.rb +0 -16
 - data/test/zoo.rb +0 -13
 
    
        data/ext/oj/parse.c
    CHANGED
    
    | 
         @@ -12,14 +12,19 @@ 
     | 
|
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
            #include "buf.h"
         
     | 
| 
       14 
14 
     | 
    
         
             
            #include "encode.h"
         
     | 
| 
      
 15 
     | 
    
         
            +
            #include "mem.h"
         
     | 
| 
       15 
16 
     | 
    
         
             
            #include "oj.h"
         
     | 
| 
       16 
17 
     | 
    
         
             
            #include "rxclass.h"
         
     | 
| 
       17 
18 
     | 
    
         
             
            #include "val_stack.h"
         
     | 
| 
       18 
19 
     | 
    
         | 
| 
      
 20 
     | 
    
         
            +
            #ifdef OJ_USE_SSE4_2
         
     | 
| 
      
 21 
     | 
    
         
            +
            #include <nmmintrin.h>
         
     | 
| 
      
 22 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
       19 
24 
     | 
    
         
             
            // Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
         
     | 
| 
       20 
25 
     | 
    
         
             
            #define OJ_INFINITY (1.0 / 0.0)
         
     | 
| 
       21 
26 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
      
 27 
     | 
    
         
            +
            // #define EXP_MAX		1023
         
     | 
| 
       23 
28 
     | 
    
         
             
            #define EXP_MAX 100000
         
     | 
| 
       24 
29 
     | 
    
         
             
            #define DEC_MAX 15
         
     | 
| 
       25 
30 
     | 
    
         | 
| 
         @@ -44,11 +49,7 @@ static void skip_comment(ParseInfo pi) { 
     | 
|
| 
       44 
49 
     | 
    
         
             
                            pi->cur += 2;
         
     | 
| 
       45 
50 
     | 
    
         
             
                            return;
         
     | 
| 
       46 
51 
     | 
    
         
             
                        } else if (pi->end <= pi->cur) {
         
     | 
| 
       47 
     | 
    
         
            -
                            oj_set_error_at(pi,
         
     | 
| 
       48 
     | 
    
         
            -
                                            oj_parse_error_class,
         
     | 
| 
       49 
     | 
    
         
            -
                                            __FILE__,
         
     | 
| 
       50 
     | 
    
         
            -
                                            __LINE__,
         
     | 
| 
       51 
     | 
    
         
            -
                                            "comment not terminated");
         
     | 
| 
      
 52 
     | 
    
         
            +
                            oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "comment not terminated");
         
     | 
| 
       52 
53 
     | 
    
         
             
                            return;
         
     | 
| 
       53 
54 
     | 
    
         
             
                        }
         
     | 
| 
       54 
55 
     | 
    
         
             
                    }
         
     | 
| 
         @@ -81,9 +82,8 @@ static void add_value(ParseInfo pi, VALUE rval) { 
     | 
|
| 
       81 
82 
     | 
    
         
             
                        break;
         
     | 
| 
       82 
83 
     | 
    
         
             
                    case NEXT_HASH_VALUE:
         
     | 
| 
       83 
84 
     | 
    
         
             
                        pi->hash_set_value(pi, parent, rval);
         
     | 
| 
       84 
     | 
    
         
            -
                        if (0 != parent->key && 0 < parent->klen &&
         
     | 
| 
       85 
     | 
    
         
            -
                            ( 
     | 
| 
       86 
     | 
    
         
            -
                            xfree((char *)parent->key);
         
     | 
| 
      
 85 
     | 
    
         
            +
                        if (0 != parent->key && 0 < parent->klen && (parent->key < pi->json || pi->cur < parent->key)) {
         
     | 
| 
      
 86 
     | 
    
         
            +
                            OJ_R_FREE((char *)parent->key);
         
     | 
| 
       87 
87 
     | 
    
         
             
                            parent->key = 0;
         
     | 
| 
       88 
88 
     | 
    
         
             
                        }
         
     | 
| 
       89 
89 
     | 
    
         
             
                        parent->next = NEXT_HASH_COMMA;
         
     | 
| 
         @@ -195,14 +195,18 @@ static inline const char *scan_string_noSIMD(const char *str, const char *end) { 
     | 
|
| 
       195 
195 
     | 
    
         
             
            #ifdef OJ_USE_SSE4_2
         
     | 
| 
       196 
196 
     | 
    
         
             
            static inline const char *scan_string_SIMD(const char *str, const char *end) {
         
     | 
| 
       197 
197 
     | 
    
         
             
                static const char chars[16] = "\x00\\\"";
         
     | 
| 
       198 
     | 
    
         
            -
                const __m128i 
     | 
| 
       199 
     | 
    
         
            -
                const char 
     | 
| 
      
 198 
     | 
    
         
            +
                const __m128i     terminate = _mm_loadu_si128((const __m128i *)&chars[0]);
         
     | 
| 
      
 199 
     | 
    
         
            +
                const char       *_end      = (const char *)(end - 16);
         
     | 
| 
       200 
200 
     | 
    
         | 
| 
       201 
201 
     | 
    
         
             
                for (; str <= _end; str += 16) {
         
     | 
| 
       202 
202 
     | 
    
         
             
                    const __m128i string = _mm_loadu_si128((const __m128i *)str);
         
     | 
| 
       203 
     | 
    
         
            -
                    const int 
     | 
| 
      
 203 
     | 
    
         
            +
                    const int     r      = _mm_cmpestri(terminate,
         
     | 
| 
      
 204 
     | 
    
         
            +
                                               3,
         
     | 
| 
      
 205 
     | 
    
         
            +
                                               string,
         
     | 
| 
      
 206 
     | 
    
         
            +
                                               16,
         
     | 
| 
      
 207 
     | 
    
         
            +
                                               _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT);
         
     | 
| 
       204 
208 
     | 
    
         
             
                    if (r != 16) {
         
     | 
| 
       205 
     | 
    
         
            -
                        str = (char*)(str + r);
         
     | 
| 
      
 209 
     | 
    
         
            +
                        str = (char *)(str + r);
         
     | 
| 
       206 
210 
     | 
    
         
             
                        return str;
         
     | 
| 
       207 
211 
     | 
    
         
             
                    }
         
     | 
| 
       208 
212 
     | 
    
         
             
                }
         
     | 
| 
         @@ -211,7 +215,7 @@ static inline const char *scan_string_SIMD(const char *str, const char *end) { 
     | 
|
| 
       211 
215 
     | 
    
         
             
            }
         
     | 
| 
       212 
216 
     | 
    
         
             
            #endif
         
     | 
| 
       213 
217 
     | 
    
         | 
| 
       214 
     | 
    
         
            -
            static const char *(*scan_func) 
     | 
| 
      
 218 
     | 
    
         
            +
            static const char *(*scan_func)(const char *str, const char *end) = scan_string_noSIMD;
         
     | 
| 
       215 
219 
     | 
    
         | 
| 
       216 
220 
     | 
    
         
             
            void oj_scanner_init(void) {
         
     | 
| 
       217 
221 
     | 
    
         
             
            #ifdef OJ_USE_SSE4_2
         
     | 
| 
         @@ -232,16 +236,12 @@ static void read_escaped_str(ParseInfo pi, const char *start) { 
     | 
|
| 
       232 
236 
     | 
    
         | 
| 
       233 
237 
     | 
    
         
             
                for (s = pi->cur; '"' != *s;) {
         
     | 
| 
       234 
238 
     | 
    
         
             
                    const char *scanned = scan_func(s, pi->end);
         
     | 
| 
       235 
     | 
    
         
            -
                    if (scanned >= pi->end) {
         
     | 
| 
       236 
     | 
    
         
            -
                         
     | 
| 
       237 
     | 
    
         
            -
             
     | 
| 
       238 
     | 
    
         
            -
                                        __FILE__,
         
     | 
| 
       239 
     | 
    
         
            -
                                        __LINE__,
         
     | 
| 
       240 
     | 
    
         
            -
                                        "quoted string not terminated");
         
     | 
| 
      
 239 
     | 
    
         
            +
                    if (scanned >= pi->end || '\0' == *scanned) {
         
     | 
| 
      
 240 
     | 
    
         
            +
                        // if (scanned >= pi->end) {
         
     | 
| 
      
 241 
     | 
    
         
            +
                        oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "quoted string not terminated");
         
     | 
| 
       241 
242 
     | 
    
         
             
                        buf_cleanup(&buf);
         
     | 
| 
       242 
243 
     | 
    
         
             
                        return;
         
     | 
| 
       243 
244 
     | 
    
         
             
                    }
         
     | 
| 
       244 
     | 
    
         
            -
             
     | 
| 
       245 
245 
     | 
    
         
             
                    buf_append_string(&buf, s, (size_t)(scanned - s));
         
     | 
| 
       246 
246 
     | 
    
         
             
                    s = scanned;
         
     | 
| 
       247 
247 
     | 
    
         | 
| 
         @@ -275,11 +275,7 @@ static void read_escaped_str(ParseInfo pi, const char *start) { 
     | 
|
| 
       275 
275 
     | 
    
         
             
                                        break;
         
     | 
| 
       276 
276 
     | 
    
         
             
                                    }
         
     | 
| 
       277 
277 
     | 
    
         
             
                                    pi->cur = s;
         
     | 
| 
       278 
     | 
    
         
            -
                                    oj_set_error_at(pi,
         
     | 
| 
       279 
     | 
    
         
            -
                                                    oj_parse_error_class,
         
     | 
| 
       280 
     | 
    
         
            -
                                                    __FILE__,
         
     | 
| 
       281 
     | 
    
         
            -
                                                    __LINE__,
         
     | 
| 
       282 
     | 
    
         
            -
                                                    "invalid escaped character");
         
     | 
| 
      
 278 
     | 
    
         
            +
                                    oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
         
     | 
| 
       283 
279 
     | 
    
         
             
                                    buf_cleanup(&buf);
         
     | 
| 
       284 
280 
     | 
    
         
             
                                    return;
         
     | 
| 
       285 
281 
     | 
    
         
             
                                }
         
     | 
| 
         @@ -306,11 +302,7 @@ static void read_escaped_str(ParseInfo pi, const char *start) { 
     | 
|
| 
       306 
302 
     | 
    
         
             
                                break;
         
     | 
| 
       307 
303 
     | 
    
         
             
                            }
         
     | 
| 
       308 
304 
     | 
    
         
             
                            pi->cur = s;
         
     | 
| 
       309 
     | 
    
         
            -
                            oj_set_error_at(pi,
         
     | 
| 
       310 
     | 
    
         
            -
                                            oj_parse_error_class,
         
     | 
| 
       311 
     | 
    
         
            -
                                            __FILE__,
         
     | 
| 
       312 
     | 
    
         
            -
                                            __LINE__,
         
     | 
| 
       313 
     | 
    
         
            -
                                            "invalid escaped character");
         
     | 
| 
      
 305 
     | 
    
         
            +
                            oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
         
     | 
| 
       314 
306 
     | 
    
         
             
                            buf_cleanup(&buf);
         
     | 
| 
       315 
307 
     | 
    
         
             
                            return;
         
     | 
| 
       316 
308 
     | 
    
         
             
                        }
         
     | 
| 
         @@ -330,7 +322,7 @@ static void read_escaped_str(ParseInfo pi, const char *start) { 
     | 
|
| 
       330 
322 
     | 
    
         
             
                    case NEXT_HASH_KEY:
         
     | 
| 
       331 
323 
     | 
    
         
             
                        if (Qundef == (parent->key_val = pi->hash_key(pi, buf.head, buf_len(&buf)))) {
         
     | 
| 
       332 
324 
     | 
    
         
             
                            parent->klen = buf_len(&buf);
         
     | 
| 
       333 
     | 
    
         
            -
                            parent->key  =  
     | 
| 
      
 325 
     | 
    
         
            +
                            parent->key  = OJ_MALLOC(parent->klen + 1);
         
     | 
| 
       334 
326 
     | 
    
         
             
                            memcpy((char *)parent->key, buf.head, parent->klen);
         
     | 
| 
       335 
327 
     | 
    
         
             
                            *(char *)(parent->key + parent->klen) = '\0';
         
     | 
| 
       336 
328 
     | 
    
         
             
                        } else {
         
     | 
| 
         @@ -342,9 +334,8 @@ static void read_escaped_str(ParseInfo pi, const char *start) { 
     | 
|
| 
       342 
334 
     | 
    
         
             
                        break;
         
     | 
| 
       343 
335 
     | 
    
         
             
                    case NEXT_HASH_VALUE:
         
     | 
| 
       344 
336 
     | 
    
         
             
                        pi->hash_set_cstr(pi, parent, buf.head, buf_len(&buf), start);
         
     | 
| 
       345 
     | 
    
         
            -
                        if (0 != parent->key && 0 < parent->klen &&
         
     | 
| 
       346 
     | 
    
         
            -
                            ( 
     | 
| 
       347 
     | 
    
         
            -
                            xfree((char *)parent->key);
         
     | 
| 
      
 337 
     | 
    
         
            +
                        if (0 != parent->key && 0 < parent->klen && (parent->key < pi->json || pi->cur < parent->key)) {
         
     | 
| 
      
 338 
     | 
    
         
            +
                            OJ_R_FREE((char *)parent->key);
         
     | 
| 
       348 
339 
     | 
    
         
             
                            parent->key = 0;
         
     | 
| 
       349 
340 
     | 
    
         
             
                        }
         
     | 
| 
       350 
341 
     | 
    
         
             
                        parent->next = NEXT_HASH_COMMA;
         
     | 
| 
         @@ -373,11 +364,7 @@ static void read_str(ParseInfo pi) { 
     | 
|
| 
       373 
364 
     | 
    
         | 
| 
       374 
365 
     | 
    
         
             
                pi->cur = scan_func(pi->cur, pi->end);
         
     | 
| 
       375 
366 
     | 
    
         
             
                if (RB_UNLIKELY(pi->end <= pi->cur)) {
         
     | 
| 
       376 
     | 
    
         
            -
                    oj_set_error_at(pi,
         
     | 
| 
       377 
     | 
    
         
            -
                                    oj_parse_error_class,
         
     | 
| 
       378 
     | 
    
         
            -
                                    __FILE__,
         
     | 
| 
       379 
     | 
    
         
            -
                                    __LINE__,
         
     | 
| 
       380 
     | 
    
         
            -
                                    "quoted string not terminated");
         
     | 
| 
      
 367 
     | 
    
         
            +
                    oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "quoted string not terminated");
         
     | 
| 
       381 
368 
     | 
    
         
             
                    return;
         
     | 
| 
       382 
369 
     | 
    
         
             
                }
         
     | 
| 
       383 
370 
     | 
    
         
             
                if (RB_UNLIKELY('\0' == *pi->cur)) {
         
     | 
| 
         @@ -412,9 +399,8 @@ static void read_str(ParseInfo pi) { 
     | 
|
| 
       412 
399 
     | 
    
         
             
                        break;
         
     | 
| 
       413 
400 
     | 
    
         
             
                    case NEXT_HASH_VALUE:
         
     | 
| 
       414 
401 
     | 
    
         
             
                        pi->hash_set_cstr(pi, parent, str, pi->cur - str, str);
         
     | 
| 
       415 
     | 
    
         
            -
                        if (0 != parent->key && 0 < parent->klen &&
         
     | 
| 
       416 
     | 
    
         
            -
                            ( 
     | 
| 
       417 
     | 
    
         
            -
                            xfree((char *)parent->key);
         
     | 
| 
      
 402 
     | 
    
         
            +
                        if (0 != parent->key && 0 < parent->klen && (parent->key < pi->json || pi->cur < parent->key)) {
         
     | 
| 
      
 403 
     | 
    
         
            +
                            OJ_R_FREE((char *)parent->key);
         
     | 
| 
       418 
404 
     | 
    
         
             
                            parent->key = 0;
         
     | 
| 
       419 
405 
     | 
    
         
             
                        }
         
     | 
| 
       420 
406 
     | 
    
         
             
                        parent->next = NEXT_HASH_COMMA;
         
     | 
| 
         @@ -440,6 +426,7 @@ static void read_num(ParseInfo pi) { 
     | 
|
| 
       440 
426 
     | 
    
         
             
                struct _numInfo ni;
         
     | 
| 
       441 
427 
     | 
    
         
             
                Val             parent = stack_peek(&pi->stack);
         
     | 
| 
       442 
428 
     | 
    
         | 
| 
      
 429 
     | 
    
         
            +
                ni.pi       = pi;
         
     | 
| 
       443 
430 
     | 
    
         
             
                ni.str      = pi->cur;
         
     | 
| 
       444 
431 
     | 
    
         
             
                ni.i        = 0;
         
     | 
| 
       445 
432 
     | 
    
         
             
                ni.num      = 0;
         
     | 
| 
         @@ -456,7 +443,7 @@ static void read_num(ParseInfo pi) { 
     | 
|
| 
       456 
443 
     | 
    
         
             
                    ni.no_big      = !pi->options.compat_bigdec;
         
     | 
| 
       457 
444 
     | 
    
         
             
                    ni.bigdec_load = pi->options.compat_bigdec;
         
     | 
| 
       458 
445 
     | 
    
         
             
                } else {
         
     | 
| 
       459 
     | 
    
         
            -
                    ni.no_big 
     | 
| 
      
 446 
     | 
    
         
            +
                    ni.no_big      = (FloatDec == pi->options.bigdec_load || FastDec == pi->options.bigdec_load ||
         
     | 
| 
       460 
447 
     | 
    
         
             
                                 RubyDec == pi->options.bigdec_load);
         
     | 
| 
       461 
448 
     | 
    
         
             
                    ni.bigdec_load = pi->options.bigdec_load;
         
     | 
| 
       462 
449 
     | 
    
         
             
                }
         
     | 
| 
         @@ -466,33 +453,21 @@ static void read_num(ParseInfo pi) { 
     | 
|
| 
       466 
453 
     | 
    
         
             
                    ni.neg = 1;
         
     | 
| 
       467 
454 
     | 
    
         
             
                } else if ('+' == *pi->cur) {
         
     | 
| 
       468 
455 
     | 
    
         
             
                    if (StrictMode == pi->options.mode) {
         
     | 
| 
       469 
     | 
    
         
            -
                        oj_set_error_at(pi,
         
     | 
| 
       470 
     | 
    
         
            -
                                        oj_parse_error_class,
         
     | 
| 
       471 
     | 
    
         
            -
                                        __FILE__,
         
     | 
| 
       472 
     | 
    
         
            -
                                        __LINE__,
         
     | 
| 
       473 
     | 
    
         
            -
                                        "not a number or other value");
         
     | 
| 
      
 456 
     | 
    
         
            +
                        oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
         
     | 
| 
       474 
457 
     | 
    
         
             
                        return;
         
     | 
| 
       475 
458 
     | 
    
         
             
                    }
         
     | 
| 
       476 
459 
     | 
    
         
             
                    pi->cur++;
         
     | 
| 
       477 
460 
     | 
    
         
             
                }
         
     | 
| 
       478 
461 
     | 
    
         
             
                if ('I' == *pi->cur) {
         
     | 
| 
       479 
462 
     | 
    
         
             
                    if (No == pi->options.allow_nan || 0 != strncmp("Infinity", pi->cur, 8)) {
         
     | 
| 
       480 
     | 
    
         
            -
                        oj_set_error_at(pi,
         
     | 
| 
       481 
     | 
    
         
            -
                                        oj_parse_error_class,
         
     | 
| 
       482 
     | 
    
         
            -
                                        __FILE__,
         
     | 
| 
       483 
     | 
    
         
            -
                                        __LINE__,
         
     | 
| 
       484 
     | 
    
         
            -
                                        "not a number or other value");
         
     | 
| 
      
 463 
     | 
    
         
            +
                        oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
         
     | 
| 
       485 
464 
     | 
    
         
             
                        return;
         
     | 
| 
       486 
465 
     | 
    
         
             
                    }
         
     | 
| 
       487 
466 
     | 
    
         
             
                    pi->cur += 8;
         
     | 
| 
       488 
467 
     | 
    
         
             
                    ni.infinity = 1;
         
     | 
| 
       489 
468 
     | 
    
         
             
                } else if ('N' == *pi->cur || 'n' == *pi->cur) {
         
     | 
| 
       490 
469 
     | 
    
         
             
                    if ('a' != pi->cur[1] || ('N' != pi->cur[2] && 'n' != pi->cur[2])) {
         
     | 
| 
       491 
     | 
    
         
            -
                        oj_set_error_at(pi,
         
     | 
| 
       492 
     | 
    
         
            -
                                        oj_parse_error_class,
         
     | 
| 
       493 
     | 
    
         
            -
                                        __FILE__,
         
     | 
| 
       494 
     | 
    
         
            -
                                        __LINE__,
         
     | 
| 
       495 
     | 
    
         
            -
                                        "not a number or other value");
         
     | 
| 
      
 470 
     | 
    
         
            +
                        oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
         
     | 
| 
       496 
471 
     | 
    
         
             
                        return;
         
     | 
| 
       497 
472 
     | 
    
         
             
                    }
         
     | 
| 
       498 
473 
     | 
    
         
             
                    pi->cur += 3;
         
     | 
| 
         @@ -515,11 +490,7 @@ static void read_num(ParseInfo pi) { 
     | 
|
| 
       515 
490 
     | 
    
         
             
                        ni.i = ni.i * 10 + d;
         
     | 
| 
       516 
491 
     | 
    
         
             
                    }
         
     | 
| 
       517 
492 
     | 
    
         
             
                    if (RB_UNLIKELY(0 != ni.i && zero1 && CompatMode == pi->options.mode)) {
         
     | 
| 
       518 
     | 
    
         
            -
                        oj_set_error_at(pi,
         
     | 
| 
       519 
     | 
    
         
            -
                                        oj_parse_error_class,
         
     | 
| 
       520 
     | 
    
         
            -
                                        __FILE__,
         
     | 
| 
       521 
     | 
    
         
            -
                                        __LINE__,
         
     | 
| 
       522 
     | 
    
         
            -
                                        "not a number");
         
     | 
| 
      
 493 
     | 
    
         
            +
                        oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number");
         
     | 
| 
       523 
494 
     | 
    
         
             
                        return;
         
     | 
| 
       524 
495 
     | 
    
         
             
                    }
         
     | 
| 
       525 
496 
     | 
    
         
             
                    if (INT64_MAX <= ni.i || DEC_MAX < dec_cnt) {
         
     | 
| 
         @@ -611,9 +582,8 @@ static void read_num(ParseInfo pi) { 
     | 
|
| 
       611 
582 
     | 
    
         
             
                        break;
         
     | 
| 
       612 
583 
     | 
    
         
             
                    case NEXT_HASH_VALUE:
         
     | 
| 
       613 
584 
     | 
    
         
             
                        pi->hash_set_num(pi, parent, &ni);
         
     | 
| 
       614 
     | 
    
         
            -
                        if (0 != parent->key && 0 < parent->klen &&
         
     | 
| 
       615 
     | 
    
         
            -
                            ( 
     | 
| 
       616 
     | 
    
         
            -
                            xfree((char *)parent->key);
         
     | 
| 
      
 585 
     | 
    
         
            +
                        if (0 != parent->key && 0 < parent->klen && (parent->key < pi->json || pi->cur < parent->key)) {
         
     | 
| 
      
 586 
     | 
    
         
            +
                            OJ_R_FREE((char *)parent->key);
         
     | 
| 
       617 
587 
     | 
    
         
             
                            parent->key = 0;
         
     | 
| 
       618 
588 
     | 
    
         
             
                        }
         
     | 
| 
       619 
589 
     | 
    
         
             
                        parent->next = NEXT_HASH_COMMA;
         
     | 
| 
         @@ -711,7 +681,7 @@ void oj_parse2(ParseInfo pi) { 
     | 
|
| 
       711 
681 
     | 
    
         
             
                pi->cur = pi->json;
         
     | 
| 
       712 
682 
     | 
    
         
             
                err_init(&pi->err);
         
     | 
| 
       713 
683 
     | 
    
         
             
                while (1) {
         
     | 
| 
       714 
     | 
    
         
            -
                    if (0 < pi->max_depth && pi->max_depth <= pi->stack.tail - pi->stack.head - 1) {
         
     | 
| 
      
 684 
     | 
    
         
            +
                    if (RB_UNLIKELY(0 < pi->max_depth && pi->max_depth <= pi->stack.tail - pi->stack.head - 1)) {
         
     | 
| 
       715 
685 
     | 
    
         
             
                        VALUE err_clas = oj_get_json_err_class("NestingError");
         
     | 
| 
       716 
686 
     | 
    
         | 
| 
       717 
687 
     | 
    
         
             
                        oj_set_error_at(pi, err_clas, __FILE__, __LINE__, "Too deeply nested.");
         
     | 
| 
         @@ -719,18 +689,20 @@ void oj_parse2(ParseInfo pi) { 
     | 
|
| 
       719 
689 
     | 
    
         
             
                        return;
         
     | 
| 
       720 
690 
     | 
    
         
             
                    }
         
     | 
| 
       721 
691 
     | 
    
         
             
                    next_non_white(pi);
         
     | 
| 
       722 
     | 
    
         
            -
                    if ( 
     | 
| 
       723 
     | 
    
         
            -
                         
     | 
| 
       724 
     | 
    
         
            -
             
     | 
| 
       725 
     | 
    
         
            -
             
     | 
| 
       726 
     | 
    
         
            -
             
     | 
| 
       727 
     | 
    
         
            -
             
     | 
| 
       728 
     | 
    
         
            -
                    }
         
     | 
| 
       729 
     | 
    
         
            -
             
     | 
| 
       730 
     | 
    
         
            -
             
     | 
| 
       731 
     | 
    
         
            -
             
     | 
| 
       732 
     | 
    
         
            -
             
     | 
| 
       733 
     | 
    
         
            -
             
     | 
| 
      
 692 
     | 
    
         
            +
                    if (first) {
         
     | 
| 
      
 693 
     | 
    
         
            +
                        // If no tokens are consumed (i.e. empty string), throw a parse error
         
     | 
| 
      
 694 
     | 
    
         
            +
                        // this is the behavior of JSON.parse in both Ruby and JS.
         
     | 
| 
      
 695 
     | 
    
         
            +
                        if (RB_UNLIKELY('\0' == *pi->cur && No == pi->options.empty_string)) {
         
     | 
| 
      
 696 
     | 
    
         
            +
                            oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
         
     | 
| 
      
 697 
     | 
    
         
            +
                        }
         
     | 
| 
      
 698 
     | 
    
         
            +
                    } else {
         
     | 
| 
      
 699 
     | 
    
         
            +
                        if (RB_UNLIKELY('\0' != *pi->cur)) {
         
     | 
| 
      
 700 
     | 
    
         
            +
                            oj_set_error_at(pi,
         
     | 
| 
      
 701 
     | 
    
         
            +
                                            oj_parse_error_class,
         
     | 
| 
      
 702 
     | 
    
         
            +
                                            __FILE__,
         
     | 
| 
      
 703 
     | 
    
         
            +
                                            __LINE__,
         
     | 
| 
      
 704 
     | 
    
         
            +
                                            "unexpected characters after the JSON document");
         
     | 
| 
      
 705 
     | 
    
         
            +
                        }
         
     | 
| 
       734 
706 
     | 
    
         
             
                    }
         
     | 
| 
       735 
707 
     | 
    
         | 
| 
       736 
708 
     | 
    
         
             
                    switch (*pi->cur++) {
         
     | 
| 
         @@ -740,17 +712,10 @@ void oj_parse2(ParseInfo pi) { 
     | 
|
| 
       740 
712 
     | 
    
         
             
                    case '[': array_start(pi); break;
         
     | 
| 
       741 
713 
     | 
    
         
             
                    case ']': array_end(pi); break;
         
     | 
| 
       742 
714 
     | 
    
         
             
                    case ',': comma(pi); break;
         
     | 
| 
       743 
     | 
    
         
            -
                    case '"':
         
     | 
| 
       744 
     | 
    
         
            -
                        read_str(pi);
         
     | 
| 
       745 
     | 
    
         
            -
                        break;
         
     | 
| 
       746 
     | 
    
         
            -
                        // case '+':
         
     | 
| 
      
 715 
     | 
    
         
            +
                    case '"': read_str(pi); break;
         
     | 
| 
       747 
716 
     | 
    
         
             
                    case '+':
         
     | 
| 
       748 
717 
     | 
    
         
             
                        if (CompatMode == pi->options.mode) {
         
     | 
| 
       749 
     | 
    
         
            -
                            oj_set_error_at(pi,
         
     | 
| 
       750 
     | 
    
         
            -
                                            oj_parse_error_class,
         
     | 
| 
       751 
     | 
    
         
            -
                                            __FILE__,
         
     | 
| 
       752 
     | 
    
         
            -
                                            __LINE__,
         
     | 
| 
       753 
     | 
    
         
            -
                                            "unexpected character");
         
     | 
| 
      
 718 
     | 
    
         
            +
                            oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
         
     | 
| 
       754 
719 
     | 
    
         
             
                            return;
         
     | 
| 
       755 
720 
     | 
    
         
             
                        }
         
     | 
| 
       756 
721 
     | 
    
         
             
                        pi->cur--;
         
     | 
| 
         @@ -776,11 +741,7 @@ void oj_parse2(ParseInfo pi) { 
     | 
|
| 
       776 
741 
     | 
    
         
             
                            pi->cur--;
         
     | 
| 
       777 
742 
     | 
    
         
             
                            read_num(pi);
         
     | 
| 
       778 
743 
     | 
    
         
             
                        } else {
         
     | 
| 
       779 
     | 
    
         
            -
                            oj_set_error_at(pi,
         
     | 
| 
       780 
     | 
    
         
            -
                                            oj_parse_error_class,
         
     | 
| 
       781 
     | 
    
         
            -
                                            __FILE__,
         
     | 
| 
       782 
     | 
    
         
            -
                                            __LINE__,
         
     | 
| 
       783 
     | 
    
         
            -
                                            "unexpected character");
         
     | 
| 
      
 744 
     | 
    
         
            +
                            oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
         
     | 
| 
       784 
745 
     | 
    
         
             
                        }
         
     | 
| 
       785 
746 
     | 
    
         
             
                        break;
         
     | 
| 
       786 
747 
     | 
    
         
             
                    case 't': read_true(pi); break;
         
     | 
| 
         @@ -800,11 +761,9 @@ void oj_parse2(ParseInfo pi) { 
     | 
|
| 
       800 
761 
     | 
    
         
             
                        }
         
     | 
| 
       801 
762 
     | 
    
         
             
                        break;
         
     | 
| 
       802 
763 
     | 
    
         
             
                    case '\0': pi->cur--; return;
         
     | 
| 
       803 
     | 
    
         
            -
                    default:
         
     | 
| 
       804 
     | 
    
         
            -
                        oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character");
         
     | 
| 
       805 
     | 
    
         
            -
                        return;
         
     | 
| 
      
 764 
     | 
    
         
            +
                    default: oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "unexpected character"); return;
         
     | 
| 
       806 
765 
     | 
    
         
             
                    }
         
     | 
| 
       807 
     | 
    
         
            -
                    if (err_has(&pi->err)) {
         
     | 
| 
      
 766 
     | 
    
         
            +
                    if (RB_UNLIKELY(err_has(&pi->err))) {
         
     | 
| 
       808 
767 
     | 
    
         
             
                        return;
         
     | 
| 
       809 
768 
     | 
    
         
             
                    }
         
     | 
| 
       810 
769 
     | 
    
         
             
                    if (stack_empty(&pi->stack)) {
         
     | 
| 
         @@ -839,11 +798,10 @@ static VALUE parse_big_decimal(VALUE str) { 
     | 
|
| 
       839 
798 
     | 
    
         
             
            }
         
     | 
| 
       840 
799 
     | 
    
         | 
| 
       841 
800 
     | 
    
         
             
            static long double exp_plus[] = {
         
     | 
| 
       842 
     | 
    
         
            -
                1.0,    1.0e1,  1.0e2,  1.0e3,  1.0e4,  1.0e5,  1.0e6,  1.0e7,  1.0e8,  1.0e9,
         
     | 
| 
       843 
     | 
    
         
            -
                1. 
     | 
| 
       844 
     | 
    
         
            -
                1. 
     | 
| 
       845 
     | 
    
         
            -
                1. 
     | 
| 
       846 
     | 
    
         
            -
                1.0e40, 1.0e41, 1.0e42, 1.0e43, 1.0e44, 1.0e45, 1.0e46, 1.0e47, 1.0e48, 1.0e49,
         
     | 
| 
      
 801 
     | 
    
         
            +
                1.0,    1.0e1,  1.0e2,  1.0e3,  1.0e4,  1.0e5,  1.0e6,  1.0e7,  1.0e8,  1.0e9,  1.0e10, 1.0e11, 1.0e12,
         
     | 
| 
      
 802 
     | 
    
         
            +
                1.0e13, 1.0e14, 1.0e15, 1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20, 1.0e21, 1.0e22, 1.0e23, 1.0e24, 1.0e25,
         
     | 
| 
      
 803 
     | 
    
         
            +
                1.0e26, 1.0e27, 1.0e28, 1.0e29, 1.0e30, 1.0e31, 1.0e32, 1.0e33, 1.0e34, 1.0e35, 1.0e36, 1.0e37, 1.0e38,
         
     | 
| 
      
 804 
     | 
    
         
            +
                1.0e39, 1.0e40, 1.0e41, 1.0e42, 1.0e43, 1.0e44, 1.0e45, 1.0e46, 1.0e47, 1.0e48, 1.0e49,
         
     | 
| 
       847 
805 
     | 
    
         
             
            };
         
     | 
| 
       848 
806 
     | 
    
         | 
| 
       849 
807 
     | 
    
         
             
            VALUE
         
     | 
| 
         @@ -867,12 +825,12 @@ oj_num_as_value(NumInfo ni) { 
     | 
|
| 
       867 
825 
     | 
    
         
             
                            buf[ni->len] = '\0';
         
     | 
| 
       868 
826 
     | 
    
         
             
                            rnum         = rb_cstr_to_inum(buf, 10, 0);
         
     | 
| 
       869 
827 
     | 
    
         
             
                        } else {
         
     | 
| 
       870 
     | 
    
         
            -
                            char *buf =  
     | 
| 
      
 828 
     | 
    
         
            +
                            char *buf = OJ_R_ALLOC_N(char, ni->len + 1);
         
     | 
| 
       871 
829 
     | 
    
         | 
| 
       872 
830 
     | 
    
         
             
                            memcpy(buf, ni->str, ni->len);
         
     | 
| 
       873 
831 
     | 
    
         
             
                            buf[ni->len] = '\0';
         
     | 
| 
       874 
832 
     | 
    
         
             
                            rnum         = rb_cstr_to_inum(buf, 10, 0);
         
     | 
| 
       875 
     | 
    
         
            -
                             
     | 
| 
      
 833 
     | 
    
         
            +
                            OJ_R_FREE(buf);
         
     | 
| 
       876 
834 
     | 
    
         
             
                        }
         
     | 
| 
       877 
835 
     | 
    
         
             
                    } else {
         
     | 
| 
       878 
836 
     | 
    
         
             
                        if (ni->neg) {
         
     | 
| 
         @@ -915,11 +873,15 @@ oj_num_as_value(NumInfo ni) { 
     | 
|
| 
       915 
873 
     | 
    
         | 
| 
       916 
874 
     | 
    
         
             
                        rnum = rb_funcall(sv, rb_intern("to_f"), 0);
         
     | 
| 
       917 
875 
     | 
    
         
             
                    } else {
         
     | 
| 
       918 
     | 
    
         
            -
                        char 
     | 
| 
      
 876 
     | 
    
         
            +
                        char  *end;
         
     | 
| 
       919 
877 
     | 
    
         
             
                        double d = strtod(ni->str, &end);
         
     | 
| 
       920 
878 
     | 
    
         | 
| 
       921 
879 
     | 
    
         
             
                        if ((long)ni->len != (long)(end - ni->str)) {
         
     | 
| 
       922 
     | 
    
         
            -
                             
     | 
| 
      
 880 
     | 
    
         
            +
                            if (Qnil == ni->pi->err_class) {
         
     | 
| 
      
 881 
     | 
    
         
            +
                                rb_raise(oj_parse_error_class, "Invalid float");
         
     | 
| 
      
 882 
     | 
    
         
            +
                            } else {
         
     | 
| 
      
 883 
     | 
    
         
            +
                                rb_raise(ni->pi->err_class, "Invalid float");
         
     | 
| 
      
 884 
     | 
    
         
            +
                            }
         
     | 
| 
       923 
885 
     | 
    
         
             
                        }
         
     | 
| 
       924 
886 
     | 
    
         
             
                        rnum = rb_float_new(d);
         
     | 
| 
       925 
887 
     | 
    
         
             
                    }
         
     | 
| 
         @@ -927,28 +889,23 @@ oj_num_as_value(NumInfo ni) { 
     | 
|
| 
       927 
889 
     | 
    
         
             
                return rnum;
         
     | 
| 
       928 
890 
     | 
    
         
             
            }
         
     | 
| 
       929 
891 
     | 
    
         | 
| 
       930 
     | 
    
         
            -
            void oj_set_error_at(ParseInfo 
     | 
| 
       931 
     | 
    
         
            -
                                 VALUE       err_clas,
         
     | 
| 
       932 
     | 
    
         
            -
                                 const char *file,
         
     | 
| 
       933 
     | 
    
         
            -
                                 int         line,
         
     | 
| 
       934 
     | 
    
         
            -
                                 const char *format,
         
     | 
| 
       935 
     | 
    
         
            -
                                 ...) {
         
     | 
| 
      
 892 
     | 
    
         
            +
            void oj_set_error_at(ParseInfo pi, VALUE err_clas, const char *file, int line, const char *format, ...) {
         
     | 
| 
       936 
893 
     | 
    
         
             
                va_list ap;
         
     | 
| 
       937 
894 
     | 
    
         
             
                char    msg[256];
         
     | 
| 
       938 
     | 
    
         
            -
                char 
     | 
| 
       939 
     | 
    
         
            -
                char 
     | 
| 
       940 
     | 
    
         
            -
                char 
     | 
| 
      
 895 
     | 
    
         
            +
                char   *p   = msg;
         
     | 
| 
      
 896 
     | 
    
         
            +
                char   *end = p + sizeof(msg) - 2;
         
     | 
| 
      
 897 
     | 
    
         
            +
                char   *start;
         
     | 
| 
       941 
898 
     | 
    
         
             
                Val     vp;
         
     | 
| 
       942 
     | 
    
         
            -
                int 
     | 
| 
      
 899 
     | 
    
         
            +
                int     mlen;
         
     | 
| 
       943 
900 
     | 
    
         | 
| 
       944 
901 
     | 
    
         
             
                va_start(ap, format);
         
     | 
| 
       945 
902 
     | 
    
         
             
                mlen = vsnprintf(msg, sizeof(msg) - 1, format, ap);
         
     | 
| 
       946 
903 
     | 
    
         
             
                if (0 < mlen) {
         
     | 
| 
       947 
     | 
    
         
            -
             
     | 
| 
       948 
     | 
    
         
            -
             
     | 
| 
       949 
     | 
    
         
            -
             
     | 
| 
       950 
     | 
    
         
            -
             
     | 
| 
       951 
     | 
    
         
            -
             
     | 
| 
      
 904 
     | 
    
         
            +
                    if (sizeof(msg) - 2 < (size_t)mlen) {
         
     | 
| 
      
 905 
     | 
    
         
            +
                        p = end - 2;
         
     | 
| 
      
 906 
     | 
    
         
            +
                    } else {
         
     | 
| 
      
 907 
     | 
    
         
            +
                        p += mlen;
         
     | 
| 
      
 908 
     | 
    
         
            +
                    }
         
     | 
| 
       952 
909 
     | 
    
         
             
                }
         
     | 
| 
       953 
910 
     | 
    
         
             
                va_end(ap);
         
     | 
| 
       954 
911 
     | 
    
         
             
                pi->err.clas = err_clas;
         
     | 
| 
         @@ -985,14 +942,7 @@ void oj_set_error_at(ParseInfo   pi, 
     | 
|
| 
       985 
942 
     | 
    
         
             
                }
         
     | 
| 
       986 
943 
     | 
    
         
             
                *p = '\0';
         
     | 
| 
       987 
944 
     | 
    
         
             
                if (0 == pi->json) {
         
     | 
| 
       988 
     | 
    
         
            -
                    oj_err_set(&pi->err,
         
     | 
| 
       989 
     | 
    
         
            -
                               err_clas,
         
     | 
| 
       990 
     | 
    
         
            -
                               "%s at line %d, column %d [%s:%d]",
         
     | 
| 
       991 
     | 
    
         
            -
                               msg,
         
     | 
| 
       992 
     | 
    
         
            -
                               pi->rd.line,
         
     | 
| 
       993 
     | 
    
         
            -
                               pi->rd.col,
         
     | 
| 
       994 
     | 
    
         
            -
                               file,
         
     | 
| 
       995 
     | 
    
         
            -
                               line);
         
     | 
| 
      
 945 
     | 
    
         
            +
                    oj_err_set(&pi->err, err_clas, "%s at line %d, column %d [%s:%d]", msg, pi->rd.line, pi->rd.col, file, line);
         
     | 
| 
       996 
946 
     | 
    
         
             
                } else {
         
     | 
| 
       997 
947 
     | 
    
         
             
                    _oj_err_set_with_location(&pi->err, err_clas, msg, pi->json, pi->cur - 1, file, line);
         
     | 
| 
       998 
948 
     | 
    
         
             
                }
         
     | 
| 
         @@ -1011,7 +961,7 @@ static void oj_pi_set_input_str(ParseInfo pi, VALUE *inputp) { 
     | 
|
| 
       1011 
961 
     | 
    
         | 
| 
       1012 
962 
     | 
    
         
             
                if (oj_utf8_encoding_index != idx) {
         
     | 
| 
       1013 
963 
     | 
    
         
             
                    rb_encoding *enc = rb_enc_from_index(idx);
         
     | 
| 
       1014 
     | 
    
         
            -
                    *inputp 
     | 
| 
      
 964 
     | 
    
         
            +
                    *inputp          = rb_str_conv_enc(*inputp, enc, oj_utf8_encoding);
         
     | 
| 
       1015 
965 
     | 
    
         
             
                }
         
     | 
| 
       1016 
966 
     | 
    
         
             
                pi->json = RSTRING_PTR(*inputp);
         
     | 
| 
       1017 
967 
     | 
    
         
             
                pi->end  = pi->json + RSTRING_LEN(*inputp);
         
     | 
| 
         @@ -1019,12 +969,12 @@ static void oj_pi_set_input_str(ParseInfo pi, VALUE *inputp) { 
     | 
|
| 
       1019 
969 
     | 
    
         | 
| 
       1020 
970 
     | 
    
         
             
            VALUE
         
     | 
| 
       1021 
971 
     | 
    
         
             
            oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yieldOk) {
         
     | 
| 
       1022 
     | 
    
         
            -
                char * 
     | 
| 
       1023 
     | 
    
         
            -
                VALUE 
     | 
| 
       1024 
     | 
    
         
            -
                VALUE 
     | 
| 
       1025 
     | 
    
         
            -
                VALUE 
     | 
| 
       1026 
     | 
    
         
            -
                int 
     | 
| 
       1027 
     | 
    
         
            -
                int 
     | 
| 
      
 972 
     | 
    
         
            +
                char *buf = 0;
         
     | 
| 
      
 973 
     | 
    
         
            +
                VALUE input;
         
     | 
| 
      
 974 
     | 
    
         
            +
                VALUE wrapped_stack;
         
     | 
| 
      
 975 
     | 
    
         
            +
                VALUE result    = Qnil;
         
     | 
| 
      
 976 
     | 
    
         
            +
                int   line      = 0;
         
     | 
| 
      
 977 
     | 
    
         
            +
                int   free_json = 0;
         
     | 
| 
       1028 
978 
     | 
    
         | 
| 
       1029 
979 
     | 
    
         
             
                if (argc < 1) {
         
     | 
| 
       1030 
980 
     | 
    
         
             
                    rb_raise(rb_eArgError, "Wrong number of arguments to parse.");
         
     | 
| 
         @@ -1073,19 +1023,18 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie 
     | 
|
| 
       1073 
1023 
     | 
    
         
             
                        size_t  len = lseek(fd, 0, SEEK_END);
         
     | 
| 
       1074 
1024 
     | 
    
         | 
| 
       1075 
1025 
     | 
    
         
             
                        lseek(fd, 0, SEEK_SET);
         
     | 
| 
       1076 
     | 
    
         
            -
                        buf      =  
     | 
| 
      
 1026 
     | 
    
         
            +
                        buf      = OJ_R_ALLOC_N(char, len + 1);
         
     | 
| 
       1077 
1027 
     | 
    
         
             
                        pi->json = buf;
         
     | 
| 
       1078 
1028 
     | 
    
         
             
                        pi->end  = buf + len;
         
     | 
| 
       1079 
1029 
     | 
    
         
             
                        if (0 >= (cnt = read(fd, (char *)pi->json, len)) || cnt != (ssize_t)len) {
         
     | 
| 
       1080 
1030 
     | 
    
         
             
                            if (0 != buf) {
         
     | 
| 
       1081 
     | 
    
         
            -
                                 
     | 
| 
      
 1031 
     | 
    
         
            +
                                OJ_R_FREE(buf);
         
     | 
| 
       1082 
1032 
     | 
    
         
             
                            }
         
     | 
| 
       1083 
1033 
     | 
    
         
             
                            rb_raise(rb_eIOError, "failed to read from IO Object.");
         
     | 
| 
       1084 
1034 
     | 
    
         
             
                        }
         
     | 
| 
       1085 
1035 
     | 
    
         
             
                        ((char *)pi->json)[len] = '\0';
         
     | 
| 
       1086 
1036 
     | 
    
         
             
                        /* skip UTF-8 BOM if present */
         
     | 
| 
       1087 
     | 
    
         
            -
                        if (0xEF == (uint8_t)*pi->json && 0xBB == (uint8_t)pi->json[1] &&
         
     | 
| 
       1088 
     | 
    
         
            -
                            0xBF == (uint8_t)pi->json[2]) {
         
     | 
| 
      
 1037 
     | 
    
         
            +
                        if (0xEF == (uint8_t)*pi->json && 0xBB == (uint8_t)pi->json[1] && 0xBF == (uint8_t)pi->json[2]) {
         
     | 
| 
       1089 
1038 
     | 
    
         
             
                            pi->cur += 3;
         
     | 
| 
       1090 
1039 
     | 
    
         
             
                        }
         
     | 
| 
       1091 
1040 
     | 
    
         
             
            #endif
         
     | 
| 
         @@ -1111,8 +1060,7 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie 
     | 
|
| 
       1111 
1060 
     | 
    
         
             
                wrapped_stack = oj_stack_init(&pi->stack);
         
     | 
| 
       1112 
1061 
     | 
    
         
             
                rb_protect(protect_parse, (VALUE)pi, &line);
         
     | 
| 
       1113 
1062 
     | 
    
         
             
                if (Qundef == pi->stack.head->val && !empty_ok(&pi->options)) {
         
     | 
| 
       1114 
     | 
    
         
            -
                    if (No == pi->options.nilnil ||
         
     | 
| 
       1115 
     | 
    
         
            -
                        (CompatMode == pi->options.mode && 0 < pi->cur - pi->json)) {
         
     | 
| 
      
 1063 
     | 
    
         
            +
                    if (No == pi->options.nilnil || (CompatMode == pi->options.mode && 0 < pi->cur - pi->json)) {
         
     | 
| 
       1116 
1064 
     | 
    
         
             
                        oj_set_error_at(pi, oj_json_parser_error_class, __FILE__, __LINE__, "Empty input");
         
     | 
| 
       1117 
1065 
     | 
    
         
             
                    }
         
     | 
| 
       1118 
1066 
     | 
    
         
             
                }
         
     | 
| 
         @@ -1140,9 +1088,7 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yie 
     | 
|
| 
       1140 
1088 
     | 
    
         
             
                        switch (v->next) {
         
     | 
| 
       1141 
1089 
     | 
    
         
             
                        case NEXT_ARRAY_NEW:
         
     | 
| 
       1142 
1090 
     | 
    
         
             
                        case NEXT_ARRAY_ELEMENT:
         
     | 
| 
       1143 
     | 
    
         
            -
                        case NEXT_ARRAY_COMMA:
         
     | 
| 
       1144 
     | 
    
         
            -
                            oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Array not terminated");
         
     | 
| 
       1145 
     | 
    
         
            -
                            break;
         
     | 
| 
      
 1091 
     | 
    
         
            +
                        case NEXT_ARRAY_COMMA: oj_set_error_at(pi, err_class, __FILE__, __LINE__, "Array not terminated"); break;
         
     | 
| 
       1146 
1092 
     | 
    
         
             
                        case NEXT_HASH_NEW:
         
     | 
| 
       1147 
1093 
     | 
    
         
             
                        case NEXT_HASH_KEY:
         
     | 
| 
       1148 
1094 
     | 
    
         
             
                        case NEXT_HASH_COLON:
         
     | 
| 
         @@ -1160,9 +1106,9 @@ CLEANUP: 
     | 
|
| 
       1160 
1106 
     | 
    
         
             
                    oj_circ_array_free(pi->circ_array);
         
     | 
| 
       1161 
1107 
     | 
    
         
             
                }
         
     | 
| 
       1162 
1108 
     | 
    
         
             
                if (0 != buf) {
         
     | 
| 
       1163 
     | 
    
         
            -
                     
     | 
| 
      
 1109 
     | 
    
         
            +
                    OJ_R_FREE(buf);
         
     | 
| 
       1164 
1110 
     | 
    
         
             
                } else if (free_json) {
         
     | 
| 
       1165 
     | 
    
         
            -
                     
     | 
| 
      
 1111 
     | 
    
         
            +
                    OJ_R_FREE(json);
         
     | 
| 
       1166 
1112 
     | 
    
         
             
                }
         
     | 
| 
       1167 
1113 
     | 
    
         
             
                stack_cleanup(&pi->stack);
         
     | 
| 
       1168 
1114 
     | 
    
         
             
                if (pi->str_rx.head != oj_default_options.str_rx.head) {
         
     | 
    
        data/ext/oj/parse.h
    CHANGED
    
    | 
         @@ -16,23 +16,25 @@ 
     | 
|
| 
       16 
16 
     | 
    
         
             
            #include "val_stack.h"
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         
             
            struct _rxClass;
         
     | 
| 
      
 19 
     | 
    
         
            +
            struct _parseInfo;
         
     | 
| 
       19 
20 
     | 
    
         | 
| 
       20 
21 
     | 
    
         
             
            typedef struct _numInfo {
         
     | 
| 
       21 
     | 
    
         
            -
                int64_t 
     | 
| 
       22 
     | 
    
         
            -
                int64_t 
     | 
| 
       23 
     | 
    
         
            -
                int64_t 
     | 
| 
       24 
     | 
    
         
            -
                int64_t 
     | 
| 
       25 
     | 
    
         
            -
                const char 
     | 
| 
       26 
     | 
    
         
            -
                size_t 
     | 
| 
       27 
     | 
    
         
            -
                long 
     | 
| 
       28 
     | 
    
         
            -
                 
     | 
| 
       29 
     | 
    
         
            -
                int 
     | 
| 
       30 
     | 
    
         
            -
                int 
     | 
| 
       31 
     | 
    
         
            -
                int 
     | 
| 
       32 
     | 
    
         
            -
                int 
     | 
| 
       33 
     | 
    
         
            -
                int 
     | 
| 
       34 
     | 
    
         
            -
                int 
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
      
 22 
     | 
    
         
            +
                int64_t            i;
         
     | 
| 
      
 23 
     | 
    
         
            +
                int64_t            num;
         
     | 
| 
      
 24 
     | 
    
         
            +
                int64_t            div;
         
     | 
| 
      
 25 
     | 
    
         
            +
                int64_t            di;
         
     | 
| 
      
 26 
     | 
    
         
            +
                const char        *str;
         
     | 
| 
      
 27 
     | 
    
         
            +
                size_t             len;
         
     | 
| 
      
 28 
     | 
    
         
            +
                long               exp;
         
     | 
| 
      
 29 
     | 
    
         
            +
                struct _parseInfo *pi;
         
     | 
| 
      
 30 
     | 
    
         
            +
                int                big;
         
     | 
| 
      
 31 
     | 
    
         
            +
                int                infinity;
         
     | 
| 
      
 32 
     | 
    
         
            +
                int                nan;
         
     | 
| 
      
 33 
     | 
    
         
            +
                int                neg;
         
     | 
| 
      
 34 
     | 
    
         
            +
                int                has_exp;
         
     | 
| 
      
 35 
     | 
    
         
            +
                int                no_big;
         
     | 
| 
      
 36 
     | 
    
         
            +
                int                bigdec_load;
         
     | 
| 
      
 37 
     | 
    
         
            +
            } *NumInfo;
         
     | 
| 
       36 
38 
     | 
    
         | 
| 
       37 
39 
     | 
    
         
             
            typedef struct _parseInfo {
         
     | 
| 
       38 
40 
     | 
    
         
             
                // used for the string parser
         
     | 
| 
         @@ -54,11 +56,7 @@ typedef struct _parseInfo { 
     | 
|
| 
       54 
56 
     | 
    
         
             
                VALUE (*start_hash)(struct _parseInfo *pi);
         
     | 
| 
       55 
57 
     | 
    
         
             
                void (*end_hash)(struct _parseInfo *pi);
         
     | 
| 
       56 
58 
     | 
    
         
             
                VALUE (*hash_key)(struct _parseInfo *pi, const char *key, size_t klen);
         
     | 
| 
       57 
     | 
    
         
            -
                void (*hash_set_cstr)(struct _parseInfo *pi,
         
     | 
| 
       58 
     | 
    
         
            -
                                      Val                kval,
         
     | 
| 
       59 
     | 
    
         
            -
                                      const char *       str,
         
     | 
| 
       60 
     | 
    
         
            -
                                      size_t             len,
         
     | 
| 
       61 
     | 
    
         
            -
                                      const char *       orig);
         
     | 
| 
      
 59 
     | 
    
         
            +
                void (*hash_set_cstr)(struct _parseInfo *pi, Val kval, const char *str, size_t len, const char *orig);
         
     | 
| 
       62 
60 
     | 
    
         
             
                void (*hash_set_num)(struct _parseInfo *pi, Val kval, NumInfo ni);
         
     | 
| 
       63 
61 
     | 
    
         
             
                void (*hash_set_value)(struct _parseInfo *pi, Val kval, VALUE value);
         
     | 
| 
       64 
62 
     | 
    
         | 
| 
         @@ -73,11 +71,10 @@ typedef struct _parseInfo { 
     | 
|
| 
       73 
71 
     | 
    
         
             
                void (*add_value)(struct _parseInfo *pi, VALUE val);
         
     | 
| 
       74 
72 
     | 
    
         
             
                VALUE err_class;
         
     | 
| 
       75 
73 
     | 
    
         
             
                bool  has_callbacks;
         
     | 
| 
       76 
     | 
    
         
            -
            } * 
     | 
| 
      
 74 
     | 
    
         
            +
            } *ParseInfo;
         
     | 
| 
       77 
75 
     | 
    
         | 
| 
       78 
     | 
    
         
            -
            extern void 
     | 
| 
       79 
     | 
    
         
            -
            extern void
         
     | 
| 
       80 
     | 
    
         
            -
                         oj_set_error_at(ParseInfo pi, VALUE err_clas, const char *file, int line, const char *format, ...);
         
     | 
| 
      
 76 
     | 
    
         
            +
            extern void  oj_parse2(ParseInfo pi);
         
     | 
| 
      
 77 
     | 
    
         
            +
            extern void  oj_set_error_at(ParseInfo pi, VALUE err_clas, const char *file, int line, const char *format, ...);
         
     | 
| 
       81 
78 
     | 
    
         
             
            extern VALUE oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json, size_t len, int yieldOk);
         
     | 
| 
       82 
79 
     | 
    
         
             
            extern VALUE oj_num_as_value(NumInfo ni);
         
     | 
| 
       83 
80 
     | 
    
         |