oj 3.12.0 → 3.13.0
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/README.md +1 -2
- data/ext/oj/buf.h +9 -0
- data/ext/oj/cache.c +187 -0
- data/ext/oj/cache.h +20 -0
- data/ext/oj/compat.c +10 -16
- data/ext/oj/custom.c +13 -12
- data/ext/oj/debug.c +131 -0
- data/ext/oj/dump.c +49 -52
- data/ext/oj/dump_compat.c +3 -3
- data/ext/oj/dump_object.c +7 -7
- data/ext/oj/dump_strict.c +3 -3
- data/ext/oj/err.h +19 -0
- data/ext/oj/extconf.rb +4 -0
- data/ext/oj/hash_test.c +3 -30
- data/ext/oj/intern.c +398 -0
- data/ext/oj/intern.h +27 -0
- data/ext/oj/mimic_json.c +9 -9
- data/ext/oj/object.c +10 -58
- data/ext/oj/odd.c +1 -1
- data/ext/oj/oj.c +172 -107
- data/ext/oj/oj.h +2 -2
- data/ext/oj/parse.c +4 -4
- data/ext/oj/parser.c +1527 -0
- data/ext/oj/parser.h +90 -0
- data/ext/oj/rails.c +4 -4
- data/ext/oj/resolve.c +2 -20
- data/ext/oj/saj2.c +346 -0
- data/ext/oj/scp.c +1 -1
- data/ext/oj/sparse.c +1 -1
- data/ext/oj/stream_writer.c +3 -3
- data/ext/oj/strict.c +10 -27
- data/ext/oj/usual.c +1222 -0
- data/ext/oj/validate.c +50 -0
- data/ext/oj/wab.c +15 -16
- data/lib/oj/mimic.rb +2 -0
- data/lib/oj/version.rb +1 -1
- data/pages/Modes.md +2 -0
- data/pages/Options.md +23 -5
- data/pages/Parser.md +309 -0
- data/test/foo.rb +2 -9
- data/test/json_gem/json_common_interface_test.rb +1 -1
- data/test/perf_parser.rb +184 -0
- data/test/test_parser.rb +27 -0
- data/test/test_parser_saj.rb +245 -0
- data/test/test_parser_usual.rb +213 -0
- metadata +23 -5
- data/ext/oj/hash.c +0 -146
- data/ext/oj/hash.h +0 -21
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 659a7b0d5dc0fd786f01d8879cf94549d7ba1c7b893048222579b77455dc1654
         | 
| 4 | 
            +
              data.tar.gz: 3413e8022bb3b6972a0c91acd63ca1d292bccebb9531fc8fb1f86aecfe675471
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 41123b593024773a786bdb12982820387da83a7dc6e385e2cd40f3a4a8b1779bbc3d2a15b8e9f52e4a69b54c4b086c453e745a33bcf21d7d237e22f1fd9e6b04
         | 
| 7 | 
            +
              data.tar.gz: 4daa8aadb603184ab90b91dd91a81a74fc1c8bfcb85d77b342ffb8054bd48bda34b94d46990ace8eb07784e4e2221f4a836d304b3a1057bcf6fdb844b89997e5
         | 
    
        data/README.md
    CHANGED
    
    | @@ -8,8 +8,7 @@ | |
| 8 8 |  | 
| 9 9 | 
             
            A *fast* JSON parser and Object marshaller as a Ruby gem.
         | 
| 10 10 |  | 
| 11 | 
            -
            Version 3. | 
| 12 | 
            -
            also provides additional optimization options.
         | 
| 11 | 
            +
            Version 3.13 is out with a much faster parser (`Oj::Parser`) and option isolation.
         | 
| 13 12 |  | 
| 14 13 | 
             
            ## Using
         | 
| 15 14 |  | 
    
        data/ext/oj/buf.h
    CHANGED
    
    | @@ -19,6 +19,10 @@ inline static void buf_init(Buf buf) { | |
| 19 19 | 
             
                buf->tail = buf->head;
         | 
| 20 20 | 
             
            }
         | 
| 21 21 |  | 
| 22 | 
            +
            inline static void buf_reset(Buf buf) {
         | 
| 23 | 
            +
                buf->tail = buf->head;
         | 
| 24 | 
            +
            }
         | 
| 25 | 
            +
             | 
| 22 26 | 
             
            inline static void buf_cleanup(Buf buf) {
         | 
| 23 27 | 
             
                if (buf->base != buf->head) {
         | 
| 24 28 | 
             
                    xfree(buf->head);
         | 
| @@ -29,6 +33,11 @@ inline static size_t buf_len(Buf buf) { | |
| 29 33 | 
             
                return buf->tail - buf->head;
         | 
| 30 34 | 
             
            }
         | 
| 31 35 |  | 
| 36 | 
            +
            inline static const char *buf_str(Buf buf) {
         | 
| 37 | 
            +
                *buf->tail = '\0';
         | 
| 38 | 
            +
                return buf->head;
         | 
| 39 | 
            +
            }
         | 
| 40 | 
            +
             | 
| 32 41 | 
             
            inline static void buf_append_string(Buf buf, const char *s, size_t slen) {
         | 
| 33 42 | 
             
                if (buf->end <= buf->tail + slen) {
         | 
| 34 43 | 
             
                    size_t len     = buf->end - buf->head;
         | 
    
        data/ext/oj/cache.c
    ADDED
    
    | @@ -0,0 +1,187 @@ | |
| 1 | 
            +
            // Copyright (c) 2011, 2021 Peter Ohler. All rights reserved.
         | 
| 2 | 
            +
            // Licensed under the MIT License. See LICENSE file in the project root for license details.
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            #include "cache.h"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            #define REHASH_LIMIT 64
         | 
| 7 | 
            +
            #define MIN_SHIFT 8
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            typedef struct _slot {
         | 
| 10 | 
            +
                struct _slot *next;
         | 
| 11 | 
            +
                VALUE         val;
         | 
| 12 | 
            +
                uint32_t      hash;
         | 
| 13 | 
            +
                uint8_t       klen;
         | 
| 14 | 
            +
                char          key[CACHE_MAX_KEY];
         | 
| 15 | 
            +
            } * Slot;
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            typedef struct _cache {
         | 
| 18 | 
            +
                Slot * slots;
         | 
| 19 | 
            +
                size_t cnt;
         | 
| 20 | 
            +
                VALUE (*form)(const char *str, size_t len);
         | 
| 21 | 
            +
                uint32_t size;
         | 
| 22 | 
            +
                uint32_t mask;
         | 
| 23 | 
            +
                bool     mark;
         | 
| 24 | 
            +
            } * Cache;
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            // almost the Murmur hash algorithm
         | 
| 27 | 
            +
            #define M 0x5bd1e995
         | 
| 28 | 
            +
            #define C1 0xCC9E2D51
         | 
| 29 | 
            +
            #define C2 0x1B873593
         | 
| 30 | 
            +
            #define N 0xE6546B64
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            void cache_set_form(Cache c, VALUE (*form)(const char *str, size_t len)) {
         | 
| 33 | 
            +
                c->form = form;
         | 
| 34 | 
            +
            }
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            #if 0
         | 
| 37 | 
            +
            // For debugging only.
         | 
| 38 | 
            +
            static void cache_print(Cache c) {
         | 
| 39 | 
            +
                for (uint32_t i = 0; i < c->size; i++) {
         | 
| 40 | 
            +
                    printf("%4d:", i);
         | 
| 41 | 
            +
                    for (Slot s = c->slots[i]; NULL != s; s = s->next) {
         | 
| 42 | 
            +
                        char buf[40];
         | 
| 43 | 
            +
                        strncpy(buf, s->key, s->klen);
         | 
| 44 | 
            +
                        buf[s->klen] = '\0';
         | 
| 45 | 
            +
                        printf(" %s", buf);
         | 
| 46 | 
            +
                    }
         | 
| 47 | 
            +
                    printf("\n");
         | 
| 48 | 
            +
                }
         | 
| 49 | 
            +
            }
         | 
| 50 | 
            +
            #endif
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            static uint32_t hash_calc(const uint8_t *key, size_t len) {
         | 
| 53 | 
            +
                const uint8_t *end     = key + len;
         | 
| 54 | 
            +
                const uint8_t *endless = key + (len & 0xFFFFFFFC);
         | 
| 55 | 
            +
                uint32_t       h       = (uint32_t)len;
         | 
| 56 | 
            +
                uint32_t       k;
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                while (key < endless) {
         | 
| 59 | 
            +
                    k = (uint32_t)*key++;
         | 
| 60 | 
            +
                    k |= (uint32_t)*key++ << 8;
         | 
| 61 | 
            +
                    k |= (uint32_t)*key++ << 16;
         | 
| 62 | 
            +
                    k |= (uint32_t)*key++ << 24;
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                    k *= M;
         | 
| 65 | 
            +
                    k ^= k >> 24;
         | 
| 66 | 
            +
                    h *= M;
         | 
| 67 | 
            +
                    h ^= k * M;
         | 
| 68 | 
            +
                }
         | 
| 69 | 
            +
                if (1 < end - key) {
         | 
| 70 | 
            +
                    uint16_t k16 = (uint16_t)*key++;
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                    k16 |= (uint16_t)*key++ << 8;
         | 
| 73 | 
            +
                    h ^= k16 << 8;
         | 
| 74 | 
            +
                }
         | 
| 75 | 
            +
                if (key < end) {
         | 
| 76 | 
            +
                    h ^= *key;
         | 
| 77 | 
            +
                }
         | 
| 78 | 
            +
                h *= M;
         | 
| 79 | 
            +
                h ^= h >> 13;
         | 
| 80 | 
            +
                h *= M;
         | 
| 81 | 
            +
                h ^= h >> 15;
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                return h;
         | 
| 84 | 
            +
            }
         | 
| 85 | 
            +
             | 
| 86 | 
            +
            Cache cache_create(size_t size, VALUE (*form)(const char *str, size_t len), bool mark) {
         | 
| 87 | 
            +
                Cache c     = ALLOC(struct _cache);
         | 
| 88 | 
            +
                int   shift = 0;
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                for (; REHASH_LIMIT < size; size /= 2, shift++) {
         | 
| 91 | 
            +
                }
         | 
| 92 | 
            +
                if (shift < MIN_SHIFT) {
         | 
| 93 | 
            +
                    shift = MIN_SHIFT;
         | 
| 94 | 
            +
                }
         | 
| 95 | 
            +
                c->size  = 1 << shift;
         | 
| 96 | 
            +
                c->mask  = c->size - 1;
         | 
| 97 | 
            +
                c->slots = ALLOC_N(Slot, c->size);
         | 
| 98 | 
            +
                memset(c->slots, 0, sizeof(Slot) * c->size);
         | 
| 99 | 
            +
                c->form = form;
         | 
| 100 | 
            +
                c->cnt  = 0;
         | 
| 101 | 
            +
                c->mark  = mark;
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                return c;
         | 
| 104 | 
            +
            }
         | 
| 105 | 
            +
             | 
| 106 | 
            +
            static void rehash(Cache c) {
         | 
| 107 | 
            +
                uint32_t osize = c->size;
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                c->size = osize * 4;
         | 
| 110 | 
            +
                c->mask = c->size - 1;
         | 
| 111 | 
            +
                REALLOC_N(c->slots, Slot, c->size);
         | 
| 112 | 
            +
                memset(c->slots + osize, 0, sizeof(Slot) * osize * 3);
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                Slot *end = c->slots + osize;
         | 
| 115 | 
            +
                for (Slot *sp = c->slots; sp < end; sp++) {
         | 
| 116 | 
            +
                    Slot s    = *sp;
         | 
| 117 | 
            +
                    Slot next = NULL;
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                    *sp = NULL;
         | 
| 120 | 
            +
                    for (; NULL != s; s = next) {
         | 
| 121 | 
            +
                        next = s->next;
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                        uint32_t h      = s->hash & c->mask;
         | 
| 124 | 
            +
                        Slot *   bucket = c->slots + h;
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                        s->next = *bucket;
         | 
| 127 | 
            +
                        *bucket = s;
         | 
| 128 | 
            +
                    }
         | 
| 129 | 
            +
                }
         | 
| 130 | 
            +
            }
         | 
| 131 | 
            +
             | 
| 132 | 
            +
            void cache_free(Cache c) {
         | 
| 133 | 
            +
                for (uint32_t i = 0; i < c->size; i++) {
         | 
| 134 | 
            +
                    Slot next;
         | 
| 135 | 
            +
                    for (Slot s = c->slots[i]; NULL != s; s = next) {
         | 
| 136 | 
            +
                        next = s->next;
         | 
| 137 | 
            +
                        xfree(s);
         | 
| 138 | 
            +
                    }
         | 
| 139 | 
            +
                }
         | 
| 140 | 
            +
                xfree(c->slots);
         | 
| 141 | 
            +
                xfree(c);
         | 
| 142 | 
            +
            }
         | 
| 143 | 
            +
             | 
| 144 | 
            +
            void cache_mark(Cache c) {
         | 
| 145 | 
            +
                if (c->mark) {
         | 
| 146 | 
            +
                    for (uint32_t i = 0; i < c->size; i++) {
         | 
| 147 | 
            +
                        for (Slot s = c->slots[i]; NULL != s; s = s->next) {
         | 
| 148 | 
            +
            		rb_gc_mark(s->val);
         | 
| 149 | 
            +
                        }
         | 
| 150 | 
            +
                    }
         | 
| 151 | 
            +
                }
         | 
| 152 | 
            +
            }
         | 
| 153 | 
            +
             | 
| 154 | 
            +
            VALUE
         | 
| 155 | 
            +
            cache_intern(Cache c, const char *key, size_t len) {
         | 
| 156 | 
            +
                if (CACHE_MAX_KEY < len) {
         | 
| 157 | 
            +
                    return c->form(key, len);
         | 
| 158 | 
            +
                }
         | 
| 159 | 
            +
                uint32_t h      = hash_calc((const uint8_t *)key, len);
         | 
| 160 | 
            +
                Slot *   bucket = c->slots + (h & c->mask);
         | 
| 161 | 
            +
                Slot     b;
         | 
| 162 | 
            +
                Slot     tail = NULL;
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                for (b = *bucket; NULL != b; b = b->next) {
         | 
| 165 | 
            +
                    if ((uint8_t)len == b->klen && 0 == strncmp(b->key, key, len)) {
         | 
| 166 | 
            +
                        return b->val;
         | 
| 167 | 
            +
                    }
         | 
| 168 | 
            +
                    tail = b;
         | 
| 169 | 
            +
                }
         | 
| 170 | 
            +
                b       = ALLOC(struct _slot);
         | 
| 171 | 
            +
                b->hash = h;
         | 
| 172 | 
            +
                b->next = NULL;
         | 
| 173 | 
            +
                memcpy(b->key, key, len);
         | 
| 174 | 
            +
                b->klen     = (uint8_t)len;
         | 
| 175 | 
            +
                b->key[len] = '\0';
         | 
| 176 | 
            +
                b->val      = c->form(key, len);
         | 
| 177 | 
            +
                if (NULL == tail) {
         | 
| 178 | 
            +
                    *bucket = b;
         | 
| 179 | 
            +
                } else {
         | 
| 180 | 
            +
                    tail->next = b;
         | 
| 181 | 
            +
                }
         | 
| 182 | 
            +
                c->cnt++;
         | 
| 183 | 
            +
                if (REHASH_LIMIT < c->cnt / c->size) {
         | 
| 184 | 
            +
                    rehash(c);
         | 
| 185 | 
            +
                }
         | 
| 186 | 
            +
                return b->val;
         | 
| 187 | 
            +
            }
         | 
    
        data/ext/oj/cache.h
    ADDED
    
    | @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            // Copyright (c) 2021 Peter Ohler. All rights reserved.
         | 
| 2 | 
            +
            // Licensed under the MIT License. See LICENSE file in the project root for license details.
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            #ifndef CACHE_H
         | 
| 5 | 
            +
            #define CACHE_H
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            #include <ruby.h>
         | 
| 8 | 
            +
            #include <stdbool.h>
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            #define CACHE_MAX_KEY 35
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            struct _cache;
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            extern struct _cache *cache_create(size_t size, VALUE (*form)(const char *str, size_t len), bool mark);
         | 
| 15 | 
            +
            extern void           cache_free(struct _cache *c);
         | 
| 16 | 
            +
            extern void           cache_mark(struct _cache *c);
         | 
| 17 | 
            +
            extern void           cache_set_form(struct _cache *c, VALUE (*form)(const char *str, size_t len));
         | 
| 18 | 
            +
            extern VALUE          cache_intern(struct _cache *c, const char *key, size_t len);
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            #endif /* CACHE_H */
         | 
    
        data/ext/oj/compat.c
    CHANGED
    
    | @@ -5,7 +5,7 @@ | |
| 5 5 |  | 
| 6 6 | 
             
            #include "encode.h"
         | 
| 7 7 | 
             
            #include "err.h"
         | 
| 8 | 
            -
            #include " | 
| 8 | 
            +
            #include "intern.h"
         | 
| 9 9 | 
             
            #include "oj.h"
         | 
| 10 10 | 
             
            #include "parse.h"
         | 
| 11 11 | 
             
            #include "resolve.h"
         | 
| @@ -26,23 +26,17 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c | |
| 26 26 | 
             
                    volatile VALUE rstr = oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
         | 
| 27 27 |  | 
| 28 28 | 
             
                    if (Qundef == rkey) {
         | 
| 29 | 
            -
                         | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
                             | 
| 33 | 
            -
                                rkey | 
| 34 | 
            -
                                rkey | 
| 35 | 
            -
                                rkey  = rb_str_intern(rkey);
         | 
| 36 | 
            -
                                *slot = rkey;
         | 
| 37 | 
            -
                                rb_gc_register_address(slot);
         | 
| 29 | 
            +
                        if (Yes != pi->options.cache_keys) {
         | 
| 30 | 
            +
                            if (Yes == pi->options.sym_key) {
         | 
| 31 | 
            +
                                rkey = ID2SYM(rb_intern3(key, klen, oj_utf8_encoding));
         | 
| 32 | 
            +
                            } else {
         | 
| 33 | 
            +
                                rkey = rb_str_new(key, klen);
         | 
| 34 | 
            +
                                rkey = oj_encode(rkey);
         | 
| 38 35 | 
             
                            }
         | 
| 36 | 
            +
                        } else if (Yes == pi->options.sym_key) {
         | 
| 37 | 
            +
                            rkey = oj_sym_intern(key, klen);
         | 
| 39 38 | 
             
                        } else {
         | 
| 40 | 
            -
                             | 
| 41 | 
            -
                                rkey  = rb_str_new(key, klen);
         | 
| 42 | 
            -
                                rkey  = oj_encode(rkey);
         | 
| 43 | 
            -
                                *slot = rkey;
         | 
| 44 | 
            -
                                rb_gc_register_address(slot);
         | 
| 45 | 
            -
                            }
         | 
| 39 | 
            +
                            rkey = oj_str_intern(key, klen);
         | 
| 46 40 | 
             
                        }
         | 
| 47 41 | 
             
                    }
         | 
| 48 42 | 
             
                    if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
         | 
    
        data/ext/oj/custom.c
    CHANGED
    
    | @@ -8,7 +8,7 @@ | |
| 8 8 | 
             
            #include "dump.h"
         | 
| 9 9 | 
             
            #include "encode.h"
         | 
| 10 10 | 
             
            #include "err.h"
         | 
| 11 | 
            -
            #include " | 
| 11 | 
            +
            #include "intern.h"
         | 
| 12 12 | 
             
            #include "odd.h"
         | 
| 13 13 | 
             
            #include "oj.h"
         | 
| 14 14 | 
             
            #include "parse.h"
         | 
| @@ -31,14 +31,14 @@ static void dump_obj_str(VALUE obj, int depth, Out out) { | |
| 31 31 |  | 
| 32 32 | 
             
            static void dump_obj_as_str(VALUE obj, int depth, Out out) {
         | 
| 33 33 | 
             
                volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
         | 
| 34 | 
            -
                const char *   str  =  | 
| 34 | 
            +
                const char *   str  = RSTRING_PTR(rstr);
         | 
| 35 35 |  | 
| 36 36 | 
             
                oj_dump_cstr(str, RSTRING_LEN(rstr), 0, 0, out);
         | 
| 37 37 | 
             
            }
         | 
| 38 38 |  | 
| 39 39 | 
             
            static void bigdecimal_dump(VALUE obj, int depth, Out out) {
         | 
| 40 40 | 
             
                volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
         | 
| 41 | 
            -
                const char *   str  =  | 
| 41 | 
            +
                const char *   str  = RSTRING_PTR(rstr);
         | 
| 42 42 | 
             
                int            len  = (int)RSTRING_LEN(rstr);
         | 
| 43 43 |  | 
| 44 44 | 
             
                if (0 == strcasecmp("Infinity", str)) {
         | 
| @@ -123,7 +123,7 @@ static void date_dump(VALUE obj, int depth, Out out) { | |
| 123 123 | 
             
                    case RubyTime:
         | 
| 124 124 | 
             
                    case XmlTime:
         | 
| 125 125 | 
             
                        v = rb_funcall(obj, rb_intern("iso8601"), 0);
         | 
| 126 | 
            -
                        oj_dump_cstr( | 
| 126 | 
            +
                        oj_dump_cstr(RSTRING_PTR(v), (int)RSTRING_LEN(v), 0, 0, out);
         | 
| 127 127 | 
             
                        break;
         | 
| 128 128 | 
             
                    case UnixZTime:
         | 
| 129 129 | 
             
                        v = rb_funcall(obj, rb_intern("to_time"), 0);
         | 
| @@ -420,7 +420,7 @@ static void dump_odd(VALUE obj, Odd odd, VALUE clas, int depth, Out out) { | |
| 420 420 | 
             
                    if (Qundef == v || T_STRING != rb_type(v)) {
         | 
| 421 421 | 
             
                        rb_raise(rb_eEncodingError, "Invalid type for raw JSON.\n");
         | 
| 422 422 | 
             
                    } else {
         | 
| 423 | 
            -
                        const char *s    =  | 
| 423 | 
            +
                        const char *s    = RSTRING_PTR(v);
         | 
| 424 424 | 
             
                        int         len  = (int)RSTRING_LEN(v);
         | 
| 425 425 | 
             
                        const char *name = rb_id2name(*odd->attrs);
         | 
| 426 426 | 
             
                        size_t      nlen = strlen(name);
         | 
| @@ -510,7 +510,7 @@ static VALUE dump_common(VALUE obj, int depth, Out out) { | |
| 510 510 | 
             
                    if (Yes == out->opts->trace) {
         | 
| 511 511 | 
             
                        oj_trace("to_json", obj, __FILE__, __LINE__, depth + 1, TraceRubyOut);
         | 
| 512 512 | 
             
                    }
         | 
| 513 | 
            -
                    s   =  | 
| 513 | 
            +
                    s   = RSTRING_PTR(rs);
         | 
| 514 514 | 
             
                    len = (int)RSTRING_LEN(rs);
         | 
| 515 515 |  | 
| 516 516 | 
             
                    assure_size(out, len + 1);
         | 
| @@ -537,7 +537,7 @@ static VALUE dump_common(VALUE obj, int depth, Out out) { | |
| 537 537 | 
             
                    if (aj == obj) {
         | 
| 538 538 | 
             
                        volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
         | 
| 539 539 |  | 
| 540 | 
            -
                        oj_dump_cstr( | 
| 540 | 
            +
                        oj_dump_cstr(RSTRING_PTR(rstr),
         | 
| 541 541 | 
             
                                     (int)RSTRING_LEN(rstr),
         | 
| 542 542 | 
             
                                     false,
         | 
| 543 543 | 
             
                                     false,
         | 
| @@ -835,7 +835,7 @@ static void dump_struct(VALUE obj, int depth, Out out, bool as_ok) { | |
| 835 835 | 
             
                        if (ma != Qnil) {
         | 
| 836 836 | 
             
                            volatile VALUE s = rb_sym_to_s(rb_ary_entry(ma, i));
         | 
| 837 837 |  | 
| 838 | 
            -
                            name =  | 
| 838 | 
            +
                            name = RSTRING_PTR(s);
         | 
| 839 839 | 
             
                            len  = (int)RSTRING_LEN(s);
         | 
| 840 840 | 
             
                        } else {
         | 
| 841 841 | 
             
                            len  = snprintf(num_id, sizeof(num_id), "%d", i);
         | 
| @@ -959,12 +959,13 @@ static void hash_set_cstr(ParseInfo pi, Val kval, const char *str, size_t len, c | |
| 959 959 | 
             
                    volatile VALUE rstr = rb_str_new(str, len);
         | 
| 960 960 |  | 
| 961 961 | 
             
                    if (Qundef == rkey) {
         | 
| 962 | 
            -
                        rkey = rb_str_new(key, klen);
         | 
| 963 | 
            -
                        rstr = oj_encode(rstr);
         | 
| 964 | 
            -
                        rkey = oj_encode(rkey);
         | 
| 965 962 | 
             
                        if (Yes == pi->options.sym_key) {
         | 
| 966 | 
            -
                            rkey =  | 
| 963 | 
            +
                            rkey = ID2SYM(rb_intern3(key, klen, oj_utf8_encoding));
         | 
| 964 | 
            +
                        } else {
         | 
| 965 | 
            +
                            rkey = rb_str_new(key, klen);
         | 
| 966 | 
            +
                            rkey = oj_encode(rkey);
         | 
| 967 967 | 
             
                        }
         | 
| 968 | 
            +
                        rstr = oj_encode(rstr);
         | 
| 968 969 | 
             
                    }
         | 
| 969 970 | 
             
                    if (Yes == pi->options.create_ok && NULL != pi->options.str_rx.head) {
         | 
| 970 971 | 
             
                        VALUE clas = oj_rxclass_match(&pi->options.str_rx, str, (int)len);
         | 
    
        data/ext/oj/debug.c
    ADDED
    
    | @@ -0,0 +1,131 @@ | |
| 1 | 
            +
            // Copyright (c) 2021, Peter Ohler, All rights reserved.
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            #include "parser.h"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            static void add_null(struct _ojParser *p) {
         | 
| 6 | 
            +
                switch (p->stack[p->depth]) {
         | 
| 7 | 
            +
                case TOP_FUN: printf("*** add_null at top\n"); break;
         | 
| 8 | 
            +
                case ARRAY_FUN: printf("*** add_null to array\n"); break;
         | 
| 9 | 
            +
                case OBJECT_FUN: printf("*** add_null with '%s'\n", buf_str(&p->key)); break;
         | 
| 10 | 
            +
                }
         | 
| 11 | 
            +
            }
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            static void add_true(struct _ojParser *p) {
         | 
| 14 | 
            +
                switch (p->stack[p->depth]) {
         | 
| 15 | 
            +
                case TOP_FUN: printf("*** add_true at top\n"); break;
         | 
| 16 | 
            +
                case ARRAY_FUN: printf("*** add_true to array\n"); break;
         | 
| 17 | 
            +
                case OBJECT_FUN: printf("*** add_true with '%s'\n", buf_str(&p->key)); break;
         | 
| 18 | 
            +
                }
         | 
| 19 | 
            +
            }
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            static void add_false(struct _ojParser *p) {
         | 
| 22 | 
            +
                switch (p->stack[p->depth]) {
         | 
| 23 | 
            +
                case TOP_FUN: printf("*** add_false at top\n"); break;
         | 
| 24 | 
            +
                case ARRAY_FUN: printf("*** add_false to array\n"); break;
         | 
| 25 | 
            +
                case OBJECT_FUN: printf("*** add_false with '%s'\n", buf_str(&p->key)); break;
         | 
| 26 | 
            +
                }
         | 
| 27 | 
            +
            }
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            static void add_int(struct _ojParser *p) {
         | 
| 30 | 
            +
                switch (p->stack[p->depth]) {
         | 
| 31 | 
            +
                case TOP_FUN: printf("*** add_int %lld at top\n", (long long)p->num.fixnum); break;
         | 
| 32 | 
            +
                case ARRAY_FUN: printf("*** add_int %lld to array\n", (long long)p->num.fixnum); break;
         | 
| 33 | 
            +
                case OBJECT_FUN:
         | 
| 34 | 
            +
                    printf("*** add_int %lld with '%s'\n", (long long)p->num.fixnum, buf_str(&p->key));
         | 
| 35 | 
            +
                    break;
         | 
| 36 | 
            +
                }
         | 
| 37 | 
            +
            }
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            static void add_float(struct _ojParser *p) {
         | 
| 40 | 
            +
                switch (p->stack[p->depth]) {
         | 
| 41 | 
            +
                case TOP_FUN: printf("*** add_float %Lf at top\n", p->num.dub); break;
         | 
| 42 | 
            +
                case ARRAY_FUN: printf("*** add_float %Lf to array\n", p->num.dub); break;
         | 
| 43 | 
            +
                case OBJECT_FUN: printf("*** add_float %Lf with '%s'\n", p->num.dub, buf_str(&p->key)); break;
         | 
| 44 | 
            +
                }
         | 
| 45 | 
            +
            }
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            static void add_big(struct _ojParser *p) {
         | 
| 48 | 
            +
                switch (p->stack[p->depth]) {
         | 
| 49 | 
            +
                case TOP_FUN: printf("*** add_big %s at top\n", buf_str(&p->buf)); break;
         | 
| 50 | 
            +
                case ARRAY_FUN: printf("*** add_big %s to array\n", buf_str(&p->buf)); break;
         | 
| 51 | 
            +
                case OBJECT_FUN:
         | 
| 52 | 
            +
                    printf("*** add_big %s with '%s'\n", buf_str(&p->buf), buf_str(&p->key));
         | 
| 53 | 
            +
                    break;
         | 
| 54 | 
            +
                }
         | 
| 55 | 
            +
            }
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            static void add_str(struct _ojParser *p) {
         | 
| 58 | 
            +
                switch (p->stack[p->depth]) {
         | 
| 59 | 
            +
                case TOP_FUN: printf("*** add_str '%s' at top\n", buf_str(&p->buf)); break;
         | 
| 60 | 
            +
                case ARRAY_FUN: printf("*** add_str '%s' to array\n", buf_str(&p->buf)); break;
         | 
| 61 | 
            +
                case OBJECT_FUN:
         | 
| 62 | 
            +
                    printf("*** add_str '%s' with '%s'\n", buf_str(&p->buf), buf_str(&p->key));
         | 
| 63 | 
            +
                    break;
         | 
| 64 | 
            +
                }
         | 
| 65 | 
            +
            }
         | 
| 66 | 
            +
             | 
| 67 | 
            +
            static void open_array(struct _ojParser *p) {
         | 
| 68 | 
            +
                switch (p->stack[p->depth]) {
         | 
| 69 | 
            +
                case TOP_FUN: printf("*** open_array at top\n"); break;
         | 
| 70 | 
            +
                case ARRAY_FUN: printf("*** open_array to array\n"); break;
         | 
| 71 | 
            +
                case OBJECT_FUN: printf("*** open_array with '%s'\n", buf_str(&p->key)); break;
         | 
| 72 | 
            +
                }
         | 
| 73 | 
            +
            }
         | 
| 74 | 
            +
             | 
| 75 | 
            +
            static void close_array(struct _ojParser *p) {
         | 
| 76 | 
            +
                printf("*** close_array\n");
         | 
| 77 | 
            +
            }
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            static void open_object(struct _ojParser *p) {
         | 
| 80 | 
            +
                switch (p->stack[p->depth]) {
         | 
| 81 | 
            +
                case TOP_FUN: printf("*** open_object at top\n"); break;
         | 
| 82 | 
            +
                case ARRAY_FUN: printf("*** open_object to array\n"); break;
         | 
| 83 | 
            +
                case OBJECT_FUN: printf("*** open_object with '%s'\n", buf_str(&p->key)); break;
         | 
| 84 | 
            +
                }
         | 
| 85 | 
            +
            }
         | 
| 86 | 
            +
             | 
| 87 | 
            +
            static void close_object(struct _ojParser *p) {
         | 
| 88 | 
            +
                printf("*** close_object\n");
         | 
| 89 | 
            +
            }
         | 
| 90 | 
            +
             | 
| 91 | 
            +
            static VALUE option(ojParser p, const char *key, VALUE value) {
         | 
| 92 | 
            +
                rb_raise(rb_eArgError, "%s is not an option for the debug delegate", key);
         | 
| 93 | 
            +
                return Qnil;
         | 
| 94 | 
            +
            }
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            static VALUE result(struct _ojParser *p) {
         | 
| 97 | 
            +
                return Qnil;
         | 
| 98 | 
            +
            }
         | 
| 99 | 
            +
             | 
| 100 | 
            +
            static void start(struct _ojParser *p) {
         | 
| 101 | 
            +
                printf("*** start\n");
         | 
| 102 | 
            +
            }
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            static void dfree(struct _ojParser *p) {
         | 
| 105 | 
            +
            }
         | 
| 106 | 
            +
             | 
| 107 | 
            +
            static void mark(struct _ojParser *p) {
         | 
| 108 | 
            +
            }
         | 
| 109 | 
            +
             | 
| 110 | 
            +
            void oj_set_parser_debug(ojParser p) {
         | 
| 111 | 
            +
                Funcs end = p->funcs + 3;
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                for (Funcs f = p->funcs; f < end; f++) {
         | 
| 114 | 
            +
                    f->add_null     = add_null;
         | 
| 115 | 
            +
                    f->add_true     = add_true;
         | 
| 116 | 
            +
                    f->add_false    = add_false;
         | 
| 117 | 
            +
                    f->add_int      = add_int;
         | 
| 118 | 
            +
                    f->add_float    = add_float;
         | 
| 119 | 
            +
                    f->add_big      = add_big;
         | 
| 120 | 
            +
                    f->add_str      = add_str;
         | 
| 121 | 
            +
                    f->open_array   = open_array;
         | 
| 122 | 
            +
                    f->close_array  = close_array;
         | 
| 123 | 
            +
                    f->open_object  = open_object;
         | 
| 124 | 
            +
                    f->close_object = close_object;
         | 
| 125 | 
            +
                }
         | 
| 126 | 
            +
                p->option = option;
         | 
| 127 | 
            +
                p->result = result;
         | 
| 128 | 
            +
                p->free   = dfree;
         | 
| 129 | 
            +
                p->mark   = mark;
         | 
| 130 | 
            +
                p->start  = start;
         | 
| 131 | 
            +
            }
         |