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/fast.c
    CHANGED
    
    | 
         @@ -11,14 +11,15 @@ 
     | 
|
| 
       11 
11 
     | 
    
         
             
            #include <stdlib.h>
         
     | 
| 
       12 
12 
     | 
    
         
             
            #include <string.h>
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
      
 14 
     | 
    
         
            +
            #include "dump.h"
         
     | 
| 
       14 
15 
     | 
    
         
             
            #include "encode.h"
         
     | 
| 
      
 16 
     | 
    
         
            +
            #include "mem.h"
         
     | 
| 
       15 
17 
     | 
    
         
             
            #include "oj.h"
         
     | 
| 
       16 
     | 
    
         
            -
            #include "dump.h"
         
     | 
| 
       17 
18 
     | 
    
         | 
| 
       18 
19 
     | 
    
         
             
            // maximum to allocate on the stack, arbitrary limit
         
     | 
| 
       19 
20 
     | 
    
         
             
            #define SMALL_JSON 65536
         
     | 
| 
       20 
21 
     | 
    
         
             
            #define MAX_STACK 100
         
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
      
 22 
     | 
    
         
            +
            // #define BATCH_SIZE	(4096 / sizeof(struct _leaf) - 1)
         
     | 
| 
       22 
23 
     | 
    
         
             
            #define BATCH_SIZE 100
         
     | 
| 
       23 
24 
     | 
    
         | 
| 
       24 
25 
     | 
    
         
             
            // Support for compaction
         
     | 
| 
         @@ -32,25 +33,25 @@ typedef struct _batch { 
     | 
|
| 
       32 
33 
     | 
    
         
             
                struct _batch *next;
         
     | 
| 
       33 
34 
     | 
    
         
             
                int            next_avail;
         
     | 
| 
       34 
35 
     | 
    
         
             
                struct _leaf   leaves[BATCH_SIZE];
         
     | 
| 
       35 
     | 
    
         
            -
            } * 
     | 
| 
      
 36 
     | 
    
         
            +
            } *Batch;
         
     | 
| 
       36 
37 
     | 
    
         | 
| 
       37 
38 
     | 
    
         
             
            typedef struct _doc {
         
     | 
| 
       38 
39 
     | 
    
         
             
                Leaf          data;
         
     | 
| 
       39 
     | 
    
         
            -
                Leaf 
     | 
| 
      
 40 
     | 
    
         
            +
                Leaf         *where;                  // points to current location
         
     | 
| 
       40 
41 
     | 
    
         
             
                Leaf          where_path[MAX_STACK];  // points to head of path
         
     | 
| 
       41 
     | 
    
         
            -
                char 
     | 
| 
      
 42 
     | 
    
         
            +
                char         *json;
         
     | 
| 
       42 
43 
     | 
    
         
             
                unsigned long size;  // number of leaves/branches in the doc
         
     | 
| 
       43 
44 
     | 
    
         
             
                VALUE         self;
         
     | 
| 
       44 
45 
     | 
    
         
             
                Batch         batches;
         
     | 
| 
       45 
46 
     | 
    
         
             
                struct _batch batch0;
         
     | 
| 
       46 
     | 
    
         
            -
            } * 
     | 
| 
      
 47 
     | 
    
         
            +
            } *Doc;
         
     | 
| 
       47 
48 
     | 
    
         | 
| 
       48 
49 
     | 
    
         
             
            typedef struct _parseInfo {
         
     | 
| 
       49 
50 
     | 
    
         
             
                char *str;  // buffer being read from
         
     | 
| 
       50 
51 
     | 
    
         
             
                char *s;    // current position in buffer
         
     | 
| 
       51 
52 
     | 
    
         
             
                Doc   doc;
         
     | 
| 
       52 
53 
     | 
    
         
             
                void *stack_min;
         
     | 
| 
       53 
     | 
    
         
            -
            } * 
     | 
| 
      
 54 
     | 
    
         
            +
            } *ParseInfo;
         
     | 
| 
       54 
55 
     | 
    
         | 
| 
       55 
56 
     | 
    
         
             
            static void  leaf_init(Leaf leaf, int type);
         
     | 
| 
       56 
57 
     | 
    
         
             
            static Leaf  leaf_new(Doc doc, int type);
         
     | 
| 
         @@ -74,7 +75,7 @@ static char *read_quoted_value(ParseInfo pi); 
     | 
|
| 
       74 
75 
     | 
    
         
             
            static void  skip_comment(ParseInfo pi);
         
     | 
| 
       75 
76 
     | 
    
         | 
| 
       76 
77 
     | 
    
         
             
            static VALUE protect_open_proc(VALUE x);
         
     | 
| 
       77 
     | 
    
         
            -
            static VALUE parse_json(VALUE clas, char *json, bool given 
     | 
| 
      
 78 
     | 
    
         
            +
            static VALUE parse_json(VALUE clas, char *json, bool given);
         
     | 
| 
       78 
79 
     | 
    
         
             
            static void  each_leaf(Doc doc, VALUE self);
         
     | 
| 
       79 
80 
     | 
    
         
             
            static int   move_step(Doc doc, const char *path, int loc);
         
     | 
| 
       80 
81 
     | 
    
         
             
            static Leaf  get_doc_leaf(Doc doc, const char *path);
         
     | 
| 
         @@ -113,10 +114,7 @@ inline static char *ulong_fill(char *s, size_t num) { 
     | 
|
| 
       113 
114 
     | 
    
         
             
                char *b = buf + sizeof(buf) - 1;
         
     | 
| 
       114 
115 
     | 
    
         | 
| 
       115 
116 
     | 
    
         
             
                *b-- = '\0';
         
     | 
| 
       116 
     | 
    
         
            -
                 
     | 
| 
       117 
     | 
    
         
            -
                    *b = (num % 10) + '0';
         
     | 
| 
       118 
     | 
    
         
            -
                }
         
     | 
| 
       119 
     | 
    
         
            -
                b++;
         
     | 
| 
      
 117 
     | 
    
         
            +
                b    = oj_longlong_to_string((long long)num, false, b);
         
     | 
| 
       120 
118 
     | 
    
         
             
                if ('\0' == *b) {
         
     | 
| 
       121 
119 
     | 
    
         
             
                    b--;
         
     | 
| 
       122 
120 
     | 
    
         
             
                    *b = '0';
         
     | 
| 
         @@ -160,7 +158,7 @@ inline static Leaf leaf_new(Doc doc, int type) { 
     | 
|
| 
       160 
158 
     | 
    
         
             
                Leaf leaf;
         
     | 
| 
       161 
159 
     | 
    
         | 
| 
       162 
160 
     | 
    
         
             
                if (0 == doc->batches || BATCH_SIZE == doc->batches->next_avail) {
         
     | 
| 
       163 
     | 
    
         
            -
                    Batch b =  
     | 
| 
      
 161 
     | 
    
         
            +
                    Batch b = OJ_R_ALLOC(struct _batch);
         
     | 
| 
       164 
162 
     | 
    
         | 
| 
       165 
163 
     | 
    
         
             
                    // Initializes all leaves with a NO_VAL value_type
         
     | 
| 
       166 
164 
     | 
    
         
             
                    memset(b, 0, sizeof(struct _batch));
         
     | 
| 
         @@ -250,7 +248,7 @@ static void skip_comment(ParseInfo pi) { 
     | 
|
| 
       250 
248 
     | 
    
         
             
            #endif
         
     | 
| 
       251 
249 
     | 
    
         | 
| 
       252 
250 
     | 
    
         
             
            static void leaf_fixnum_value(Leaf leaf) {
         
     | 
| 
       253 
     | 
    
         
            -
                char 
     | 
| 
      
 251 
     | 
    
         
            +
                char   *s   = leaf->str;
         
     | 
| 
       254 
252 
     | 
    
         
             
                int64_t n   = 0;
         
     | 
| 
       255 
253 
     | 
    
         
             
                int     neg = 0;
         
     | 
| 
       256 
254 
     | 
    
         
             
                int     big = 0;
         
     | 
| 
         @@ -356,7 +354,7 @@ static Leaf read_next(ParseInfo pi) { 
     | 
|
| 
       356 
354 
     | 
    
         | 
| 
       357 
355 
     | 
    
         
             
            static Leaf read_obj(ParseInfo pi) {
         
     | 
| 
       358 
356 
     | 
    
         
             
                Leaf        h = leaf_new(pi->doc, T_HASH);
         
     | 
| 
       359 
     | 
    
         
            -
                char 
     | 
| 
      
 357 
     | 
    
         
            +
                char       *end;
         
     | 
| 
       360 
358 
     | 
    
         
             
                const char *key = 0;
         
     | 
| 
       361 
359 
     | 
    
         
             
                Leaf        val = 0;
         
     | 
| 
       362 
360 
     | 
    
         | 
| 
         @@ -648,10 +646,11 @@ static void doc_free(Doc doc) { 
     | 
|
| 
       648 
646 
     | 
    
         
             
                    while (0 != (b = doc->batches)) {
         
     | 
| 
       649 
647 
     | 
    
         
             
                        doc->batches = doc->batches->next;
         
     | 
| 
       650 
648 
     | 
    
         
             
                        if (&doc->batch0 != b) {
         
     | 
| 
       651 
     | 
    
         
            -
                             
     | 
| 
      
 649 
     | 
    
         
            +
                            OJ_R_FREE(b);
         
     | 
| 
       652 
650 
     | 
    
         
             
                        }
         
     | 
| 
       653 
651 
     | 
    
         
             
                    }
         
     | 
| 
       654 
     | 
    
         
            -
                     
     | 
| 
      
 652 
     | 
    
         
            +
                    OJ_R_FREE(doc->json);
         
     | 
| 
      
 653 
     | 
    
         
            +
                    OJ_R_FREE(doc);
         
     | 
| 
       655 
654 
     | 
    
         
             
                }
         
     | 
| 
       656 
655 
     | 
    
         
             
            }
         
     | 
| 
       657 
656 
     | 
    
         | 
| 
         @@ -671,7 +670,6 @@ static void free_doc_cb(void *x) { 
     | 
|
| 
       671 
670 
     | 
    
         
             
                Doc doc = (Doc)x;
         
     | 
| 
       672 
671 
     | 
    
         | 
| 
       673 
672 
     | 
    
         
             
                if (0 != doc) {
         
     | 
| 
       674 
     | 
    
         
            -
                    xfree(doc->json);
         
     | 
| 
       675 
673 
     | 
    
         
             
                    doc_free(doc);
         
     | 
| 
       676 
674 
     | 
    
         
             
                }
         
     | 
| 
       677 
675 
     | 
    
         
             
            }
         
     | 
| 
         @@ -749,20 +747,15 @@ static const rb_data_type_t oj_doc_type = { 
     | 
|
| 
       749 
747 
     | 
    
         
             
                0,
         
     | 
| 
       750 
748 
     | 
    
         
             
            };
         
     | 
| 
       751 
749 
     | 
    
         | 
| 
       752 
     | 
    
         
            -
            static VALUE parse_json(VALUE clas, char *json, bool given 
     | 
| 
      
 750 
     | 
    
         
            +
            static VALUE parse_json(VALUE clas, char *json, bool given) {
         
     | 
| 
       753 
751 
     | 
    
         
             
                struct _parseInfo pi;
         
     | 
| 
       754 
752 
     | 
    
         
             
                volatile VALUE    result = Qnil;
         
     | 
| 
       755 
753 
     | 
    
         
             
                Doc               doc;
         
     | 
| 
       756 
754 
     | 
    
         
             
                int               ex = 0;
         
     | 
| 
       757 
755 
     | 
    
         
             
                volatile VALUE    self;
         
     | 
| 
       758 
756 
     | 
    
         | 
| 
       759 
     | 
    
         
            -
                 
     | 
| 
      
 757 
     | 
    
         
            +
                doc = OJ_R_ALLOC_N(struct _doc, 1);
         
     | 
| 
       760 
758 
     | 
    
         | 
| 
       761 
     | 
    
         
            -
                if (given) {
         
     | 
| 
       762 
     | 
    
         
            -
                    doc = ALLOCA_N(struct _doc, 1);
         
     | 
| 
       763 
     | 
    
         
            -
                } else {
         
     | 
| 
       764 
     | 
    
         
            -
                    doc = ALLOC(struct _doc);
         
     | 
| 
       765 
     | 
    
         
            -
                }
         
     | 
| 
       766 
759 
     | 
    
         
             
                // skip UTF-8 BOM if present
         
     | 
| 
       767 
760 
     | 
    
         
             
                if (0xEF == (uint8_t)*json && 0xBB == (uint8_t)json[1] && 0xBF == (uint8_t)json[2]) {
         
     | 
| 
       768 
761 
     | 
    
         
             
                    pi.str = json + 3;
         
     | 
| 
         @@ -772,7 +765,7 @@ static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) { 
     | 
|
| 
       772 
765 
     | 
    
         
             
                pi.s = pi.str;
         
     | 
| 
       773 
766 
     | 
    
         
             
                doc_init(doc);
         
     | 
| 
       774 
767 
     | 
    
         
             
                pi.doc = doc;
         
     | 
| 
       775 
     | 
    
         
            -
            #if IS_WINDOWS
         
     | 
| 
      
 768 
     | 
    
         
            +
            #if IS_WINDOWS || !defined(HAVE_GETRLIMIT)
         
     | 
| 
       776 
769 
     | 
    
         
             
                // assume a 1M stack and give half to ruby
         
     | 
| 
       777 
770 
     | 
    
         
             
                pi.stack_min = (void *)((char *)&pi - (512L * 1024L));
         
     | 
| 
       778 
771 
     | 
    
         
             
            #else
         
     | 
| 
         @@ -787,18 +780,19 @@ static VALUE parse_json(VALUE clas, char *json, bool given, bool allocated) { 
     | 
|
| 
       787 
780 
     | 
    
         
             
                    }
         
     | 
| 
       788 
781 
     | 
    
         
             
                }
         
     | 
| 
       789 
782 
     | 
    
         
             
            #endif
         
     | 
| 
       790 
     | 
    
         
            -
                 
     | 
| 
       791 
     | 
    
         
            -
                 
     | 
| 
       792 
     | 
    
         
            -
                doc-> 
     | 
| 
       793 
     | 
    
         
            -
                 
     | 
| 
       794 
     | 
    
         
            -
                result              = rb_protect(protect_open_proc, (VALUE)&pi, &ex);
         
     | 
| 
      
 783 
     | 
    
         
            +
                doc->json = json;
         
     | 
| 
      
 784 
     | 
    
         
            +
                self      = TypedData_Wrap_Struct(clas, &oj_doc_type, doc);
         
     | 
| 
      
 785 
     | 
    
         
            +
                doc->self = self;
         
     | 
| 
      
 786 
     | 
    
         
            +
                result    = rb_protect(protect_open_proc, (VALUE)&pi, &ex);
         
     | 
| 
       795 
787 
     | 
    
         
             
                if (given || 0 != ex) {
         
     | 
| 
       796 
788 
     | 
    
         
             
                    DATA_PTR(doc->self) = NULL;
         
     | 
| 
      
 789 
     | 
    
         
            +
                    // TBD is this needed?
         
     | 
| 
      
 790 
     | 
    
         
            +
                    /*
         
     | 
| 
       797 
791 
     | 
    
         
             
                    doc_free(pi.doc);
         
     | 
| 
       798 
     | 
    
         
            -
                    if ( 
     | 
| 
       799 
     | 
    
         
            -
                         
     | 
| 
      
 792 
     | 
    
         
            +
                    if (0 != ex) {  // will jump so caller will not free
         
     | 
| 
      
 793 
     | 
    
         
            +
                        OJ_R_FREE(json);
         
     | 
| 
       800 
794 
     | 
    
         
             
                    }
         
     | 
| 
       801 
     | 
    
         
            -
                     
     | 
| 
      
 795 
     | 
    
         
            +
                    */
         
     | 
| 
       802 
796 
     | 
    
         
             
                } else {
         
     | 
| 
       803 
797 
     | 
    
         
             
                    result = doc->self;
         
     | 
| 
       804 
798 
     | 
    
         
             
                }
         
     | 
| 
         @@ -1088,31 +1082,23 @@ static void each_value(Doc doc, Leaf leaf) { 
     | 
|
| 
       1088 
1082 
     | 
    
         
             
             *   doc.close()
         
     | 
| 
       1089 
1083 
     | 
    
         
             
             */
         
     | 
| 
       1090 
1084 
     | 
    
         
             
            static VALUE doc_open(VALUE clas, VALUE str) {
         
     | 
| 
       1091 
     | 
    
         
            -
                char 
     | 
| 
      
 1085 
     | 
    
         
            +
                char          *json;
         
     | 
| 
       1092 
1086 
     | 
    
         
             
                size_t         len;
         
     | 
| 
       1093 
1087 
     | 
    
         
             
                volatile VALUE obj;
         
     | 
| 
       1094 
1088 
     | 
    
         
             
                int            given = rb_block_given_p();
         
     | 
| 
       1095 
     | 
    
         
            -
                int            allocate;
         
     | 
| 
       1096 
1089 
     | 
    
         | 
| 
       1097 
1090 
     | 
    
         
             
                Check_Type(str, T_STRING);
         
     | 
| 
       1098 
     | 
    
         
            -
                len 
     | 
| 
       1099 
     | 
    
         
            -
                 
     | 
| 
       1100 
     | 
    
         
            -
             
     | 
| 
       1101 
     | 
    
         
            -
                    json = ALLOC_N(char, len);
         
     | 
| 
       1102 
     | 
    
         
            -
                } else {
         
     | 
| 
       1103 
     | 
    
         
            -
                    json = ALLOCA_N(char, len);
         
     | 
| 
       1104 
     | 
    
         
            -
                }
         
     | 
| 
       1105 
     | 
    
         
            -
                // It should not be necessaary to stop GC but if it is not stopped and a
         
     | 
| 
       1106 
     | 
    
         
            -
                // large string is parsed that string is corrupted or freed during
         
     | 
| 
       1107 
     | 
    
         
            -
                // parsing. I'm not sure what is going on exactly but disabling GC avoids
         
     | 
| 
       1108 
     | 
    
         
            -
                // the issue.
         
     | 
| 
       1109 
     | 
    
         
            -
                rb_gc_disable();
         
     | 
| 
      
 1091 
     | 
    
         
            +
                len  = (int)RSTRING_LEN(str) + 1;
         
     | 
| 
      
 1092 
     | 
    
         
            +
                json = OJ_R_ALLOC_N(char, len);
         
     | 
| 
      
 1093 
     | 
    
         
            +
             
     | 
| 
       1110 
1094 
     | 
    
         
             
                memcpy(json, StringValuePtr(str), len);
         
     | 
| 
       1111 
     | 
    
         
            -
                obj = parse_json(clas, json, given 
     | 
| 
       1112 
     | 
    
         
            -
                 
     | 
| 
       1113 
     | 
    
         
            -
                 
     | 
| 
       1114 
     | 
    
         
            -
             
     | 
| 
      
 1095 
     | 
    
         
            +
                obj = parse_json(clas, json, given);
         
     | 
| 
      
 1096 
     | 
    
         
            +
                // TBD is this needed
         
     | 
| 
      
 1097 
     | 
    
         
            +
                /*
         
     | 
| 
      
 1098 
     | 
    
         
            +
                if (given) {
         
     | 
| 
      
 1099 
     | 
    
         
            +
                    OJ_R_FREE(json);
         
     | 
| 
       1115 
1100 
     | 
    
         
             
                }
         
     | 
| 
      
 1101 
     | 
    
         
            +
                */
         
     | 
| 
       1116 
1102 
     | 
    
         
             
                return obj;
         
     | 
| 
       1117 
1103 
     | 
    
         
             
            }
         
     | 
| 
       1118 
1104 
     | 
    
         | 
| 
         @@ -1136,27 +1122,21 @@ static VALUE doc_open(VALUE clas, VALUE str) { 
     | 
|
| 
       1136 
1122 
     | 
    
         
             
             *   doc.close()
         
     | 
| 
       1137 
1123 
     | 
    
         
             
             */
         
     | 
| 
       1138 
1124 
     | 
    
         
             
            static VALUE doc_open_file(VALUE clas, VALUE filename) {
         
     | 
| 
       1139 
     | 
    
         
            -
                char 
     | 
| 
       1140 
     | 
    
         
            -
                char 
     | 
| 
       1141 
     | 
    
         
            -
                FILE 
     | 
| 
      
 1125 
     | 
    
         
            +
                char          *path;
         
     | 
| 
      
 1126 
     | 
    
         
            +
                char          *json;
         
     | 
| 
      
 1127 
     | 
    
         
            +
                FILE          *f;
         
     | 
| 
       1142 
1128 
     | 
    
         
             
                size_t         len;
         
     | 
| 
       1143 
1129 
     | 
    
         
             
                volatile VALUE obj;
         
     | 
| 
       1144 
1130 
     | 
    
         
             
                int            given = rb_block_given_p();
         
     | 
| 
       1145 
     | 
    
         
            -
                int            allocate;
         
     | 
| 
       1146 
1131 
     | 
    
         | 
| 
       1147 
     | 
    
         
            -
                Check_Type(filename, T_STRING);
         
     | 
| 
       1148 
1132 
     | 
    
         
             
                path = StringValuePtr(filename);
         
     | 
| 
       1149 
1133 
     | 
    
         
             
                if (0 == (f = fopen(path, "r"))) {
         
     | 
| 
       1150 
1134 
     | 
    
         
             
                    rb_raise(rb_eIOError, "%s", strerror(errno));
         
     | 
| 
       1151 
1135 
     | 
    
         
             
                }
         
     | 
| 
       1152 
1136 
     | 
    
         
             
                fseek(f, 0, SEEK_END);
         
     | 
| 
       1153 
     | 
    
         
            -
                len 
     | 
| 
       1154 
     | 
    
         
            -
                 
     | 
| 
       1155 
     | 
    
         
            -
             
     | 
| 
       1156 
     | 
    
         
            -
                    json = ALLOC_N(char, len + 1);
         
     | 
| 
       1157 
     | 
    
         
            -
                } else {
         
     | 
| 
       1158 
     | 
    
         
            -
                    json = ALLOCA_N(char, len + 1);
         
     | 
| 
       1159 
     | 
    
         
            -
                }
         
     | 
| 
      
 1137 
     | 
    
         
            +
                len  = ftell(f);
         
     | 
| 
      
 1138 
     | 
    
         
            +
                json = OJ_R_ALLOC_N(char, len + 1);
         
     | 
| 
      
 1139 
     | 
    
         
            +
             
     | 
| 
       1160 
1140 
     | 
    
         
             
                fseek(f, 0, SEEK_SET);
         
     | 
| 
       1161 
1141 
     | 
    
         
             
                if (len != fread(json, 1, len, f)) {
         
     | 
| 
       1162 
1142 
     | 
    
         
             
                    fclose(f);
         
     | 
| 
         @@ -1167,12 +1147,13 @@ static VALUE doc_open_file(VALUE clas, VALUE filename) { 
     | 
|
| 
       1167 
1147 
     | 
    
         
             
                }
         
     | 
| 
       1168 
1148 
     | 
    
         
             
                fclose(f);
         
     | 
| 
       1169 
1149 
     | 
    
         
             
                json[len] = '\0';
         
     | 
| 
       1170 
     | 
    
         
            -
                 
     | 
| 
       1171 
     | 
    
         
            -
                 
     | 
| 
       1172 
     | 
    
         
            -
                 
     | 
| 
       1173 
     | 
    
         
            -
                if (given 
     | 
| 
       1174 
     | 
    
         
            -
                     
     | 
| 
      
 1150 
     | 
    
         
            +
                obj       = parse_json(clas, json, given);
         
     | 
| 
      
 1151 
     | 
    
         
            +
                // TBD is this needed
         
     | 
| 
      
 1152 
     | 
    
         
            +
                /*
         
     | 
| 
      
 1153 
     | 
    
         
            +
                if (given) {
         
     | 
| 
      
 1154 
     | 
    
         
            +
                    OJ_R_FREE(json);
         
     | 
| 
       1175 
1155 
     | 
    
         
             
                }
         
     | 
| 
      
 1156 
     | 
    
         
            +
                */
         
     | 
| 
       1176 
1157 
     | 
    
         
             
                return obj;
         
     | 
| 
       1177 
1158 
     | 
    
         
             
            }
         
     | 
| 
       1178 
1159 
     | 
    
         | 
| 
         @@ -1212,11 +1193,11 @@ static VALUE doc_where(VALUE self) { 
     | 
|
| 
       1212 
1193 
     | 
    
         
             
                if (0 == *doc->where_path || doc->where == doc->where_path) {
         
     | 
| 
       1213 
1194 
     | 
    
         
             
                    return oj_slash_string;
         
     | 
| 
       1214 
1195 
     | 
    
         
             
                } else {
         
     | 
| 
       1215 
     | 
    
         
            -
                    Leaf 
     | 
| 
      
 1196 
     | 
    
         
            +
                    Leaf  *lp;
         
     | 
| 
       1216 
1197 
     | 
    
         
             
                    Leaf   leaf;
         
     | 
| 
       1217 
1198 
     | 
    
         
             
                    size_t size = 3;  // leading / and terminating \0
         
     | 
| 
       1218 
     | 
    
         
            -
                    char 
     | 
| 
       1219 
     | 
    
         
            -
                    char 
     | 
| 
      
 1199 
     | 
    
         
            +
                    char  *path;
         
     | 
| 
      
 1200 
     | 
    
         
            +
                    char  *p;
         
     | 
| 
       1220 
1201 
     | 
    
         | 
| 
       1221 
1202 
     | 
    
         
             
                    for (lp = doc->where_path; lp <= doc->where; lp++) {
         
     | 
| 
       1222 
1203 
     | 
    
         
             
                        leaf = *lp;
         
     | 
| 
         @@ -1319,7 +1300,6 @@ static VALUE doc_type(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       1319 
1300 
     | 
    
         
             
                VALUE       type = Qnil;
         
     | 
| 
       1320 
1301 
     | 
    
         | 
| 
       1321 
1302 
     | 
    
         
             
                if (1 <= argc) {
         
     | 
| 
       1322 
     | 
    
         
            -
                    Check_Type(*argv, T_STRING);
         
     | 
| 
       1323 
1303 
     | 
    
         
             
                    path = StringValuePtr(*argv);
         
     | 
| 
       1324 
1304 
     | 
    
         
             
                }
         
     | 
| 
       1325 
1305 
     | 
    
         
             
                if (0 != (leaf = get_doc_leaf(doc, path))) {
         
     | 
| 
         @@ -1328,11 +1308,7 @@ static VALUE doc_type(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       1328 
1308 
     | 
    
         
             
                    case T_TRUE: type = rb_cTrueClass; break;
         
     | 
| 
       1329 
1309 
     | 
    
         
             
                    case T_FALSE: type = rb_cFalseClass; break;
         
     | 
| 
       1330 
1310 
     | 
    
         
             
                    case T_STRING: type = rb_cString; break;
         
     | 
| 
       1331 
     | 
    
         
            -
            #ifdef RUBY_INTEGER_UNIFICATION
         
     | 
| 
       1332 
1311 
     | 
    
         
             
                    case T_FIXNUM: type = rb_cInteger; break;
         
     | 
| 
       1333 
     | 
    
         
            -
            #else
         
     | 
| 
       1334 
     | 
    
         
            -
                    case T_FIXNUM: type = rb_cFixnum; break;
         
     | 
| 
       1335 
     | 
    
         
            -
            #endif
         
     | 
| 
       1336 
1312 
     | 
    
         
             
                    case T_FLOAT: type = rb_cFloat; break;
         
     | 
| 
       1337 
1313 
     | 
    
         
             
                    case T_ARRAY: type = rb_cArray; break;
         
     | 
| 
       1338 
1314 
     | 
    
         
             
                    case T_HASH: type = rb_cHash; break;
         
     | 
| 
         @@ -1359,11 +1335,10 @@ static VALUE doc_fetch(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       1359 
1335 
     | 
    
         
             
                Doc            doc;
         
     | 
| 
       1360 
1336 
     | 
    
         
             
                Leaf           leaf;
         
     | 
| 
       1361 
1337 
     | 
    
         
             
                volatile VALUE val  = Qnil;
         
     | 
| 
       1362 
     | 
    
         
            -
                const char 
     | 
| 
      
 1338 
     | 
    
         
            +
                const char    *path = 0;
         
     | 
| 
       1363 
1339 
     | 
    
         | 
| 
       1364 
1340 
     | 
    
         
             
                doc = self_doc(self);
         
     | 
| 
       1365 
1341 
     | 
    
         
             
                if (1 <= argc) {
         
     | 
| 
       1366 
     | 
    
         
            -
                    Check_Type(*argv, T_STRING);
         
     | 
| 
       1367 
1342 
     | 
    
         
             
                    path = StringValuePtr(*argv);
         
     | 
| 
       1368 
1343 
     | 
    
         
             
                    if (2 == argc) {
         
     | 
| 
       1369 
1344 
     | 
    
         
             
                        val = argv[1];
         
     | 
| 
         @@ -1388,7 +1363,6 @@ static VALUE doc_exists(VALUE self, VALUE str) { 
     | 
|
| 
       1388 
1363 
     | 
    
         
             
                Leaf leaf;
         
     | 
| 
       1389 
1364 
     | 
    
         | 
| 
       1390 
1365 
     | 
    
         
             
                doc = self_doc(self);
         
     | 
| 
       1391 
     | 
    
         
            -
                Check_Type(str, T_STRING);
         
     | 
| 
       1392 
1366 
     | 
    
         
             
                if (0 != (leaf = get_doc_leaf(doc, StringValuePtr(str)))) {
         
     | 
| 
       1393 
1367 
     | 
    
         
             
                    if (NULL != leaf) {
         
     | 
| 
       1394 
1368 
     | 
    
         
             
                        return Qtrue;
         
     | 
| 
         @@ -1425,7 +1399,6 @@ static VALUE doc_each_leaf(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       1425 
1399 
     | 
    
         
             
                        memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
         
     | 
| 
       1426 
1400 
     | 
    
         
             
                    }
         
     | 
| 
       1427 
1401 
     | 
    
         
             
                    if (1 <= argc) {
         
     | 
| 
       1428 
     | 
    
         
            -
                        Check_Type(*argv, T_STRING);
         
     | 
| 
       1429 
1402 
     | 
    
         
             
                        path = StringValuePtr(*argv);
         
     | 
| 
       1430 
1403 
     | 
    
         
             
                        if ('/' == *path) {
         
     | 
| 
       1431 
1404 
     | 
    
         
             
                            doc->where = doc->where_path;
         
     | 
| 
         @@ -1460,7 +1433,6 @@ static VALUE doc_move(VALUE self, VALUE str) { 
     | 
|
| 
       1460 
1433 
     | 
    
         
             
                const char *path;
         
     | 
| 
       1461 
1434 
     | 
    
         
             
                int         loc;
         
     | 
| 
       1462 
1435 
     | 
    
         | 
| 
       1463 
     | 
    
         
            -
                Check_Type(str, T_STRING);
         
     | 
| 
       1464 
1436 
     | 
    
         
             
                path = StringValuePtr(str);
         
     | 
| 
       1465 
1437 
     | 
    
         
             
                if ('/' == *path) {
         
     | 
| 
       1466 
1438 
     | 
    
         
             
                    doc->where = doc->where_path;
         
     | 
| 
         @@ -1495,14 +1467,13 @@ static VALUE doc_each_child(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       1495 
1467 
     | 
    
         
             
                    Doc         doc  = self_doc(self);
         
     | 
| 
       1496 
1468 
     | 
    
         
             
                    const char *path = 0;
         
     | 
| 
       1497 
1469 
     | 
    
         
             
                    size_t      wlen;
         
     | 
| 
       1498 
     | 
    
         
            -
                    Leaf 
     | 
| 
      
 1470 
     | 
    
         
            +
                    Leaf       *where_orig = doc->where;
         
     | 
| 
       1499 
1471 
     | 
    
         | 
| 
       1500 
1472 
     | 
    
         
             
                    wlen = doc->where - doc->where_path;
         
     | 
| 
       1501 
1473 
     | 
    
         
             
                    if (0 < wlen) {
         
     | 
| 
       1502 
1474 
     | 
    
         
             
                        memcpy(save_path, doc->where_path, sizeof(Leaf) * (wlen + 1));
         
     | 
| 
       1503 
1475 
     | 
    
         
             
                    }
         
     | 
| 
       1504 
1476 
     | 
    
         
             
                    if (1 <= argc) {
         
     | 
| 
       1505 
     | 
    
         
            -
                        Check_Type(*argv, T_STRING);
         
     | 
| 
       1506 
1477 
     | 
    
         
             
                        path = StringValuePtr(*argv);
         
     | 
| 
       1507 
1478 
     | 
    
         
             
                        if ('/' == *path) {
         
     | 
| 
       1508 
1479 
     | 
    
         
             
                            doc->where = doc->where_path;
         
     | 
| 
         @@ -1569,7 +1540,6 @@ static VALUE doc_each_value(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       1569 
1540 
     | 
    
         
             
                    Leaf        leaf;
         
     | 
| 
       1570 
1541 
     | 
    
         | 
| 
       1571 
1542 
     | 
    
         
             
                    if (1 <= argc) {
         
     | 
| 
       1572 
     | 
    
         
            -
                        Check_Type(*argv, T_STRING);
         
     | 
| 
       1573 
1543 
     | 
    
         
             
                        path = StringValuePtr(*argv);
         
     | 
| 
       1574 
1544 
     | 
    
         
             
                    }
         
     | 
| 
       1575 
1545 
     | 
    
         
             
                    if (0 != (leaf = get_doc_leaf(doc, path))) {
         
     | 
| 
         @@ -1601,11 +1571,9 @@ static VALUE doc_dump(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       1601 
1571 
     | 
    
         | 
| 
       1602 
1572 
     | 
    
         
             
                if (1 <= argc) {
         
     | 
| 
       1603 
1573 
     | 
    
         
             
                    if (Qnil != *argv) {
         
     | 
| 
       1604 
     | 
    
         
            -
                        Check_Type(*argv, T_STRING);
         
     | 
| 
       1605 
1574 
     | 
    
         
             
                        path = StringValuePtr(*argv);
         
     | 
| 
       1606 
1575 
     | 
    
         
             
                    }
         
     | 
| 
       1607 
1576 
     | 
    
         
             
                    if (2 <= argc) {
         
     | 
| 
       1608 
     | 
    
         
            -
                        Check_Type(argv[1], T_STRING);
         
     | 
| 
       1609 
1577 
     | 
    
         
             
                        filename = StringValuePtr(argv[1]);
         
     | 
| 
       1610 
1578 
     | 
    
         
             
                    }
         
     | 
| 
       1611 
1579 
     | 
    
         
             
                }
         
     | 
| 
         @@ -1617,7 +1585,7 @@ static VALUE doc_dump(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       1617 
1585 
     | 
    
         | 
| 
       1618 
1586 
     | 
    
         
             
                        oj_out_init(&out);
         
     | 
| 
       1619 
1587 
     | 
    
         | 
| 
       1620 
     | 
    
         
            -
                        out.omit_nil 
     | 
| 
      
 1588 
     | 
    
         
            +
                        out.omit_nil = oj_default_options.dump_opts.omit_nil;
         
     | 
| 
       1621 
1589 
     | 
    
         
             
                        oj_dump_leaf_to_json(leaf, &oj_default_options, &out);
         
     | 
| 
       1622 
1590 
     | 
    
         
             
                        rjson = rb_str_new2(out.buf);
         
     | 
| 
       1623 
1591 
     | 
    
         | 
| 
         @@ -1640,7 +1608,9 @@ static VALUE doc_dump(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       1640 
1608 
     | 
    
         
             
             *   Oj::Doc.open('[1,2,3]') { |doc| doc.size() }  #=> 4
         
     | 
| 
       1641 
1609 
     | 
    
         
             
             */
         
     | 
| 
       1642 
1610 
     | 
    
         
             
            static VALUE doc_size(VALUE self) {
         
     | 
| 
       1643 
     | 
    
         
            -
                 
     | 
| 
      
 1611 
     | 
    
         
            +
                Doc d;
         
     | 
| 
      
 1612 
     | 
    
         
            +
                TypedData_Get_Struct(self, struct _doc, &oj_doc_type, d);
         
     | 
| 
      
 1613 
     | 
    
         
            +
                return ULONG2NUM(d->size);
         
     | 
| 
       1644 
1614 
     | 
    
         
             
            }
         
     | 
| 
       1645 
1615 
     | 
    
         | 
| 
       1646 
1616 
     | 
    
         
             
            /* @overload close() => nil
         
     | 
| 
         @@ -1656,11 +1626,9 @@ static VALUE doc_close(VALUE self) { 
     | 
|
| 
       1656 
1626 
     | 
    
         
             
                Doc doc = self_doc(self);
         
     | 
| 
       1657 
1627 
     | 
    
         | 
| 
       1658 
1628 
     | 
    
         
             
                rb_gc_unregister_address(&doc->self);
         
     | 
| 
       1659 
     | 
    
         
            -
                DATA_PTR(doc->self) =  
     | 
| 
      
 1629 
     | 
    
         
            +
                DATA_PTR(doc->self) = NULL;
         
     | 
| 
       1660 
1630 
     | 
    
         
             
                if (0 != doc) {
         
     | 
| 
       1661 
     | 
    
         
            -
                    xfree(doc->json);
         
     | 
| 
       1662 
1631 
     | 
    
         
             
                    doc_free(doc);
         
     | 
| 
       1663 
     | 
    
         
            -
                    xfree(doc);
         
     | 
| 
       1664 
1632 
     | 
    
         
             
                }
         
     | 
| 
       1665 
1633 
     | 
    
         
             
                return Qnil;
         
     | 
| 
       1666 
1634 
     | 
    
         
             
            }
         
     | 
    
        data/ext/oj/intern.c
    CHANGED
    
    | 
         @@ -8,7 +8,9 @@ 
     | 
|
| 
       8 
8 
     | 
    
         
             
            #if HAVE_PTHREAD_MUTEX_INIT
         
     | 
| 
       9 
9 
     | 
    
         
             
            #include <pthread.h>
         
     | 
| 
       10 
10 
     | 
    
         
             
            #endif
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
       11 
12 
     | 
    
         
             
            #include "cache.h"
         
     | 
| 
      
 13 
     | 
    
         
            +
            #include "mem.h"
         
     | 
| 
       12 
14 
     | 
    
         
             
            #include "parse.h"
         
     | 
| 
       13 
15 
     | 
    
         | 
| 
       14 
16 
     | 
    
         
             
            // Only used for the class cache so 256 should be sufficient.
         
     | 
| 
         @@ -20,10 +22,10 @@ 
     | 
|
| 
       20 
22 
     | 
    
         | 
| 
       21 
23 
     | 
    
         
             
            typedef struct _keyVal {
         
     | 
| 
       22 
24 
     | 
    
         
             
                struct _keyVal *next;
         
     | 
| 
       23 
     | 
    
         
            -
                const char 
     | 
| 
      
 25 
     | 
    
         
            +
                const char     *key;
         
     | 
| 
       24 
26 
     | 
    
         
             
                size_t          len;
         
     | 
| 
       25 
27 
     | 
    
         
             
                VALUE           val;
         
     | 
| 
       26 
     | 
    
         
            -
            } * 
     | 
| 
      
 28 
     | 
    
         
            +
            } *KeyVal;
         
     | 
| 
       27 
29 
     | 
    
         | 
| 
       28 
30 
     | 
    
         
             
            typedef struct _hash {
         
     | 
| 
       29 
31 
     | 
    
         
             
                struct _keyVal slots[HASH_SLOT_CNT];
         
     | 
| 
         @@ -32,16 +34,16 @@ typedef struct _hash { 
     | 
|
| 
       32 
34 
     | 
    
         
             
            #else
         
     | 
| 
       33 
35 
     | 
    
         
             
                VALUE mutex;
         
     | 
| 
       34 
36 
     | 
    
         
             
            #endif
         
     | 
| 
       35 
     | 
    
         
            -
            } * 
     | 
| 
      
 37 
     | 
    
         
            +
            } *Hash;
         
     | 
| 
       36 
38 
     | 
    
         | 
| 
       37 
39 
     | 
    
         
             
            struct _hash class_hash;
         
     | 
| 
       38 
40 
     | 
    
         
             
            struct _hash attr_hash;
         
     | 
| 
       39 
41 
     | 
    
         | 
| 
       40 
     | 
    
         
            -
            static VALUE 
     | 
| 
      
 42 
     | 
    
         
            +
            static VALUE str_cache_obj;
         
     | 
| 
       41 
43 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
            static VALUE 
     | 
| 
      
 44 
     | 
    
         
            +
            static VALUE sym_cache_obj;
         
     | 
| 
       43 
45 
     | 
    
         | 
| 
       44 
     | 
    
         
            -
            static VALUE 
     | 
| 
      
 46 
     | 
    
         
            +
            static VALUE attr_cache_obj;
         
     | 
| 
       45 
47 
     | 
    
         | 
| 
       46 
48 
     | 
    
         
             
            static VALUE form_str(const char *str, size_t len) {
         
     | 
| 
       47 
49 
     | 
    
         
             
                return rb_str_freeze(rb_utf8_str_new(str, len));
         
     | 
| 
         @@ -55,51 +57,59 @@ static VALUE form_attr(const char *str, size_t len) { 
     | 
|
| 
       55 
57 
     | 
    
         
             
                char buf[256];
         
     | 
| 
       56 
58 
     | 
    
         | 
| 
       57 
59 
     | 
    
         
             
                if (sizeof(buf) - 2 <= len) {
         
     | 
| 
       58 
     | 
    
         
            -
                    char *b =  
     | 
| 
      
 60 
     | 
    
         
            +
                    char *b = OJ_R_ALLOC_N(char, len + 2);
         
     | 
| 
       59 
61 
     | 
    
         
             
                    ID    id;
         
     | 
| 
       60 
62 
     | 
    
         | 
| 
       61 
63 
     | 
    
         
             
                    if ('~' == *str) {
         
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
      
 64 
     | 
    
         
            +
                        memcpy(b, str + 1, len - 1);
         
     | 
| 
      
 65 
     | 
    
         
            +
                        b[len - 1] = '\0';
         
     | 
| 
      
 66 
     | 
    
         
            +
                        len -= 2;
         
     | 
| 
      
 67 
     | 
    
         
            +
                    } else {
         
     | 
| 
      
 68 
     | 
    
         
            +
                        *b = '@';
         
     | 
| 
      
 69 
     | 
    
         
            +
                        memcpy(b + 1, str, len);
         
     | 
| 
      
 70 
     | 
    
         
            +
                        b[len + 1] = '\0';
         
     | 
| 
      
 71 
     | 
    
         
            +
                    }
         
     | 
| 
       70 
72 
     | 
    
         
             
                    id = rb_intern3(buf, len + 1, oj_utf8_encoding);
         
     | 
| 
       71 
     | 
    
         
            -
                     
     | 
| 
      
 73 
     | 
    
         
            +
                    OJ_R_FREE(b);
         
     | 
| 
       72 
74 
     | 
    
         
             
                    return id;
         
     | 
| 
       73 
75 
     | 
    
         
             
                }
         
     | 
| 
       74 
76 
     | 
    
         
             
                if ('~' == *str) {
         
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
      
 77 
     | 
    
         
            +
                    memcpy(buf, str + 1, len - 1);
         
     | 
| 
      
 78 
     | 
    
         
            +
                    buf[len - 1] = '\0';
         
     | 
| 
      
 79 
     | 
    
         
            +
                    len -= 2;
         
     | 
| 
       78 
80 
     | 
    
         
             
                } else {
         
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
             
     | 
| 
      
 81 
     | 
    
         
            +
                    *buf = '@';
         
     | 
| 
      
 82 
     | 
    
         
            +
                    memcpy(buf + 1, str, len);
         
     | 
| 
      
 83 
     | 
    
         
            +
                    buf[len + 1] = '\0';
         
     | 
| 
       82 
84 
     | 
    
         
             
                }
         
     | 
| 
       83 
85 
     | 
    
         
             
                return (VALUE)rb_intern3(buf, len + 1, oj_utf8_encoding);
         
     | 
| 
       84 
86 
     | 
    
         
             
            }
         
     | 
| 
       85 
87 
     | 
    
         | 
| 
      
 88 
     | 
    
         
            +
            static const rb_data_type_t oj_cache_type = {
         
     | 
| 
      
 89 
     | 
    
         
            +
                "Oj/cache",
         
     | 
| 
      
 90 
     | 
    
         
            +
                {
         
     | 
| 
      
 91 
     | 
    
         
            +
                    cache_mark,
         
     | 
| 
      
 92 
     | 
    
         
            +
                    cache_free,
         
     | 
| 
      
 93 
     | 
    
         
            +
                    NULL,
         
     | 
| 
      
 94 
     | 
    
         
            +
                },
         
     | 
| 
      
 95 
     | 
    
         
            +
                0,
         
     | 
| 
      
 96 
     | 
    
         
            +
                0,
         
     | 
| 
      
 97 
     | 
    
         
            +
            };
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
       86 
99 
     | 
    
         
             
            void oj_hash_init(void) {
         
     | 
| 
       87 
100 
     | 
    
         
             
                VALUE cache_class = rb_define_class_under(Oj, "Cache", rb_cObject);
         
     | 
| 
       88 
101 
     | 
    
         
             
                rb_undef_alloc_func(cache_class);
         
     | 
| 
       89 
102 
     | 
    
         | 
| 
       90 
     | 
    
         
            -
                 
     | 
| 
       91 
     | 
    
         
            -
                 
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
                struct _cache *str_cache     = cache_create(0, form_str, true, true);
         
     | 
| 
       94 
     | 
    
         
            -
                str_cache_obj = Data_Wrap_Struct(cache_class, cache_mark, cache_free, str_cache);
         
     | 
| 
      
 103 
     | 
    
         
            +
                struct _cache *str_cache = cache_create(0, form_str, true, true);
         
     | 
| 
      
 104 
     | 
    
         
            +
                str_cache_obj            = TypedData_Wrap_Struct(cache_class, &oj_cache_type, str_cache);
         
     | 
| 
       95 
105 
     | 
    
         
             
                rb_gc_register_address(&str_cache_obj);
         
     | 
| 
       96 
106 
     | 
    
         | 
| 
       97 
     | 
    
         
            -
                struct _cache *sym_cache 
     | 
| 
       98 
     | 
    
         
            -
                sym_cache_obj 
     | 
| 
      
 107 
     | 
    
         
            +
                struct _cache *sym_cache = cache_create(0, form_sym, true, true);
         
     | 
| 
      
 108 
     | 
    
         
            +
                sym_cache_obj            = TypedData_Wrap_Struct(cache_class, &oj_cache_type, sym_cache);
         
     | 
| 
       99 
109 
     | 
    
         
             
                rb_gc_register_address(&sym_cache_obj);
         
     | 
| 
       100 
110 
     | 
    
         | 
| 
       101 
111 
     | 
    
         
             
                struct _cache *attr_cache = cache_create(0, form_attr, false, true);
         
     | 
| 
       102 
     | 
    
         
            -
                attr_cache_obj 
     | 
| 
      
 112 
     | 
    
         
            +
                attr_cache_obj            = TypedData_Wrap_Struct(cache_class, &oj_cache_type, attr_cache);
         
     | 
| 
       103 
113 
     | 
    
         
             
                rb_gc_register_address(&attr_cache_obj);
         
     | 
| 
       104 
114 
     | 
    
         | 
| 
       105 
115 
     | 
    
         
             
                memset(class_hash.slots, 0, sizeof(class_hash.slots));
         
     | 
| 
         @@ -119,18 +129,23 @@ oj_str_intern(const char *key, size_t len) { 
     | 
|
| 
       119 
129 
     | 
    
         
             
            #if HAVE_RB_ENC_INTERNED_STR && 0
         
     | 
| 
       120 
130 
     | 
    
         
             
                return rb_enc_interned_str(key, len, rb_utf8_encoding());
         
     | 
| 
       121 
131 
     | 
    
         
             
            #else
         
     | 
| 
       122 
     | 
    
         
            -
                 
     | 
| 
      
 132 
     | 
    
         
            +
                Cache c;
         
     | 
| 
      
 133 
     | 
    
         
            +
                TypedData_Get_Struct(str_cache_obj, struct _cache, &oj_cache_type, c);
         
     | 
| 
      
 134 
     | 
    
         
            +
                return cache_intern(c, key, len);
         
     | 
| 
       123 
135 
     | 
    
         
             
            #endif
         
     | 
| 
       124 
136 
     | 
    
         
             
            }
         
     | 
| 
       125 
137 
     | 
    
         | 
| 
       126 
138 
     | 
    
         
             
            VALUE
         
     | 
| 
       127 
139 
     | 
    
         
             
            oj_sym_intern(const char *key, size_t len) {
         
     | 
| 
       128 
     | 
    
         
            -
             
     | 
| 
      
 140 
     | 
    
         
            +
                Cache c;
         
     | 
| 
      
 141 
     | 
    
         
            +
                TypedData_Get_Struct(sym_cache_obj, struct _cache, &oj_cache_type, c);
         
     | 
| 
      
 142 
     | 
    
         
            +
                return cache_intern(c, key, len);
         
     | 
| 
       129 
143 
     | 
    
         
             
            }
         
     | 
| 
       130 
144 
     | 
    
         | 
| 
       131 
     | 
    
         
            -
            ID
         
     | 
| 
       132 
     | 
    
         
            -
             
     | 
| 
       133 
     | 
    
         
            -
             
     | 
| 
      
 145 
     | 
    
         
            +
            ID oj_attr_intern(const char *key, size_t len) {
         
     | 
| 
      
 146 
     | 
    
         
            +
                Cache c;
         
     | 
| 
      
 147 
     | 
    
         
            +
                TypedData_Get_Struct(attr_cache_obj, struct _cache, &oj_cache_type, c);
         
     | 
| 
      
 148 
     | 
    
         
            +
                return cache_intern(c, key, len);
         
     | 
| 
       134 
149 
     | 
    
         
             
            }
         
     | 
| 
       135 
150 
     | 
    
         | 
| 
       136 
151 
     | 
    
         
             
            static uint64_t hash_calc(const uint8_t *key, size_t len) {
         
     | 
| 
         @@ -184,10 +199,10 @@ static VALUE resolve_classname(VALUE mod, const char *classname, int auto_define 
     | 
|
| 
       184 
199 
     | 
    
         
             
            static VALUE resolve_classpath(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE error_class) {
         
     | 
| 
       185 
200 
     | 
    
         
             
                char        class_name[1024];
         
     | 
| 
       186 
201 
     | 
    
         
             
                VALUE       clas;
         
     | 
| 
       187 
     | 
    
         
            -
                char 
     | 
| 
       188 
     | 
    
         
            -
                char 
     | 
| 
       189 
     | 
    
         
            -
                const char *n 
     | 
| 
       190 
     | 
    
         
            -
                size_t 
     | 
| 
      
 202 
     | 
    
         
            +
                char       *end = class_name + sizeof(class_name) - 1;
         
     | 
| 
      
 203 
     | 
    
         
            +
                char       *s;
         
     | 
| 
      
 204 
     | 
    
         
            +
                const char *n    = name;
         
     | 
| 
      
 205 
     | 
    
         
            +
                size_t      nlen = len;
         
     | 
| 
       191 
206 
     | 
    
         | 
| 
       192 
207 
     | 
    
         
             
                clas = rb_cObject;
         
     | 
| 
       193 
208 
     | 
    
         
             
                for (s = class_name; 0 < len; n++, len--) {
         
     | 
| 
         @@ -210,11 +225,11 @@ static VALUE resolve_classpath(ParseInfo pi, const char *name, size_t len, int a 
     | 
|
| 
       210 
225 
     | 
    
         
             
                }
         
     | 
| 
       211 
226 
     | 
    
         
             
                *s = '\0';
         
     | 
| 
       212 
227 
     | 
    
         
             
                if (Qundef == (clas = resolve_classname(clas, class_name, auto_define))) {
         
     | 
| 
       213 
     | 
    
         
            -
             
     | 
| 
       214 
     | 
    
         
            -
             
     | 
| 
       215 
     | 
    
         
            -
             
     | 
| 
       216 
     | 
    
         
            -
             
     | 
| 
       217 
     | 
    
         
            -
             
     | 
| 
      
 228 
     | 
    
         
            +
                    if (sizeof(class_name) <= nlen) {
         
     | 
| 
      
 229 
     | 
    
         
            +
                        nlen = sizeof(class_name) - 1;
         
     | 
| 
      
 230 
     | 
    
         
            +
                    }
         
     | 
| 
      
 231 
     | 
    
         
            +
                    strncpy(class_name, name, nlen);
         
     | 
| 
      
 232 
     | 
    
         
            +
                    class_name[nlen] = '\0';
         
     | 
| 
       218 
233 
     | 
    
         
             
                    oj_set_error_at(pi, error_class, __FILE__, __LINE__, "class '%s' is not defined", class_name);
         
     | 
| 
       219 
234 
     | 
    
         
             
                    if (Qnil != error_class) {
         
     | 
| 
       220 
235 
     | 
    
         
             
                        pi->err_class = error_class;
         
     | 
| 
         @@ -246,7 +261,7 @@ VALUE oj_class_intern(const char *key, size_t len, bool safe, ParseInfo pi, int 
     | 
|
| 
       246 
261 
     | 
    
         
             
                            }
         
     | 
| 
       247 
262 
     | 
    
         
             
                            bucket = b;
         
     | 
| 
       248 
263 
     | 
    
         
             
                        }
         
     | 
| 
       249 
     | 
    
         
            -
                        b            =  
     | 
| 
      
 264 
     | 
    
         
            +
                        b            = OJ_R_ALLOC(struct _keyVal);
         
     | 
| 
       250 
265 
     | 
    
         
             
                        b->next      = NULL;
         
     | 
| 
       251 
266 
     | 
    
         
             
                        bucket->next = b;
         
     | 
| 
       252 
267 
     | 
    
         
             
                        bucket       = b;
         
     | 
| 
         @@ -267,7 +282,7 @@ VALUE oj_class_intern(const char *key, size_t len, bool safe, ParseInfo pi, int 
     | 
|
| 
       267 
282 
     | 
    
         
             
                            }
         
     | 
| 
       268 
283 
     | 
    
         
             
                            bucket = b;
         
     | 
| 
       269 
284 
     | 
    
         
             
                        }
         
     | 
| 
       270 
     | 
    
         
            -
                        b            =  
     | 
| 
      
 285 
     | 
    
         
            +
                        b            = OJ_R_ALLOC(struct _keyVal);
         
     | 
| 
       271 
286 
     | 
    
         
             
                        b->next      = NULL;
         
     | 
| 
       272 
287 
     | 
    
         
             
                        bucket->next = b;
         
     | 
| 
       273 
288 
     | 
    
         
             
                        bucket       = b;
         
     | 
| 
         @@ -281,7 +296,7 @@ VALUE oj_class_intern(const char *key, size_t len, bool safe, ParseInfo pi, int 
     | 
|
| 
       281 
296 
     | 
    
         
             
            }
         
     | 
| 
       282 
297 
     | 
    
         | 
| 
       283 
298 
     | 
    
         
             
            char *oj_strndup(const char *s, size_t len) {
         
     | 
| 
       284 
     | 
    
         
            -
                char *d =  
     | 
| 
      
 299 
     | 
    
         
            +
                char *d = OJ_R_ALLOC_N(char, len + 1);
         
     | 
| 
       285 
300 
     | 
    
         | 
| 
       286 
301 
     | 
    
         
             
                memcpy(d, s, len);
         
     | 
| 
       287 
302 
     | 
    
         
             
                d[len] = '\0';
         
     | 
    
        data/ext/oj/intern.h
    CHANGED
    
    | 
         @@ -4,8 +4,8 @@ 
     | 
|
| 
       4 
4 
     | 
    
         
             
            #ifndef OJ_INTERN_H
         
     | 
| 
       5 
5 
     | 
    
         
             
            #define OJ_INTERN_H
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
            #include <stdbool.h>
         
     | 
| 
       8 
7 
     | 
    
         
             
            #include <ruby.h>
         
     | 
| 
      
 8 
     | 
    
         
            +
            #include <stdbool.h>
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
            struct _parseInfo;
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
         @@ -14,12 +14,8 @@ extern void oj_hash_init(void); 
     | 
|
| 
       14 
14 
     | 
    
         
             
            extern VALUE oj_str_intern(const char *key, size_t len);
         
     | 
| 
       15 
15 
     | 
    
         
             
            extern VALUE oj_sym_intern(const char *key, size_t len);
         
     | 
| 
       16 
16 
     | 
    
         
             
            extern ID    oj_attr_intern(const char *key, size_t len);
         
     | 
| 
       17 
     | 
    
         
            -
            extern VALUE 
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
                                         bool               safe,
         
     | 
| 
       20 
     | 
    
         
            -
                                         struct _parseInfo *pi,
         
     | 
| 
       21 
     | 
    
         
            -
                                         int                auto_define,
         
     | 
| 
       22 
     | 
    
         
            -
                                         VALUE              error_class);
         
     | 
| 
      
 17 
     | 
    
         
            +
            extern VALUE
         
     | 
| 
      
 18 
     | 
    
         
            +
            oj_class_intern(const char *key, size_t len, bool safe, struct _parseInfo *pi, int auto_define, VALUE error_class);
         
     | 
| 
       23 
19 
     | 
    
         | 
| 
       24 
20 
     | 
    
         
             
            extern char *oj_strndup(const char *s, size_t len);
         
     | 
| 
       25 
21 
     | 
    
         |