oj 3.10.6 → 3.12.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 +6 -1
- data/ext/oj/buf.h +36 -68
- data/ext/oj/cache8.c +59 -62
- data/ext/oj/cache8.h +9 -36
- data/ext/oj/circarray.c +36 -42
- data/ext/oj/circarray.h +12 -13
- data/ext/oj/code.c +172 -179
- data/ext/oj/code.h +22 -24
- data/ext/oj/compat.c +168 -181
- data/ext/oj/custom.c +800 -864
- data/ext/oj/dump.c +774 -776
- data/ext/oj/dump.h +50 -55
- data/ext/oj/dump_compat.c +2 -4
- data/ext/oj/dump_leaf.c +118 -162
- data/ext/oj/dump_object.c +610 -632
- data/ext/oj/dump_strict.c +319 -331
- data/ext/oj/encode.h +4 -33
- data/ext/oj/err.c +40 -29
- data/ext/oj/err.h +25 -44
- data/ext/oj/extconf.rb +2 -1
- data/ext/oj/fast.c +1054 -1081
- data/ext/oj/hash.c +78 -95
- data/ext/oj/hash.h +10 -35
- data/ext/oj/hash_test.c +451 -472
- data/ext/oj/mimic_json.c +415 -402
- data/ext/oj/object.c +588 -532
- data/ext/oj/odd.c +124 -132
- data/ext/oj/odd.h +28 -29
- data/ext/oj/oj.c +1178 -905
- data/ext/oj/oj.h +289 -298
- data/ext/oj/parse.c +946 -870
- data/ext/oj/parse.h +81 -79
- data/ext/oj/rails.c +837 -842
- data/ext/oj/rails.h +8 -11
- data/ext/oj/reader.c +139 -147
- data/ext/oj/reader.h +68 -84
- data/ext/oj/resolve.c +44 -47
- data/ext/oj/resolve.h +4 -6
- data/ext/oj/rxclass.c +69 -73
- data/ext/oj/rxclass.h +13 -14
- data/ext/oj/saj.c +453 -484
- data/ext/oj/scp.c +88 -113
- data/ext/oj/sparse.c +783 -714
- data/ext/oj/stream_writer.c +123 -157
- data/ext/oj/strict.c +133 -106
- data/ext/oj/string_writer.c +199 -247
- data/ext/oj/trace.c +34 -41
- data/ext/oj/trace.h +15 -15
- data/ext/oj/util.c +104 -104
- data/ext/oj/util.h +4 -3
- data/ext/oj/val_stack.c +48 -76
- data/ext/oj/val_stack.h +80 -115
- data/ext/oj/wab.c +317 -328
- data/lib/oj.rb +0 -8
- data/lib/oj/bag.rb +1 -0
- data/lib/oj/easy_hash.rb +5 -4
- data/lib/oj/mimic.rb +45 -13
- data/lib/oj/version.rb +1 -1
- data/pages/Modes.md +1 -0
- data/pages/Options.md +23 -11
- data/test/activerecord/result_test.rb +7 -2
- data/test/foo.rb +8 -40
- data/test/helper.rb +10 -0
- data/test/json_gem/json_common_interface_test.rb +8 -3
- data/test/json_gem/json_generator_test.rb +15 -3
- data/test/json_gem/test_helper.rb +8 -0
- data/test/perf.rb +1 -1
- data/test/perf_scp.rb +11 -10
- data/test/perf_strict.rb +17 -23
- data/test/prec.rb +23 -0
- data/test/sample_json.rb +1 -1
- data/test/test_compat.rb +16 -3
- data/test/test_custom.rb +11 -0
- data/test/test_fast.rb +32 -2
- data/test/test_generate.rb +21 -0
- data/test/test_hash.rb +10 -0
- data/test/test_rails.rb +9 -0
- data/test/test_scp.rb +1 -1
- data/test/test_various.rb +4 -2
- metadata +89 -85
data/ext/oj/val_stack.h
CHANGED
@@ -1,185 +1,150 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
* All rights reserved.
|
4
|
-
*
|
5
|
-
* Redistribution and use in source and binary forms, with or without
|
6
|
-
* modification, are permitted provided that the following conditions are met:
|
7
|
-
*
|
8
|
-
* - Redistributions of source code must retain the above copyright notice, this
|
9
|
-
* list of conditions and the following disclaimer.
|
10
|
-
*
|
11
|
-
* - Redistributions in binary form must reproduce the above copyright notice,
|
12
|
-
* this list of conditions and the following disclaimer in the documentation
|
13
|
-
* and/or other materials provided with the distribution.
|
14
|
-
*
|
15
|
-
* - Neither the name of Peter Ohler nor the names of its contributors may be
|
16
|
-
* used to endorse or promote products derived from this software without
|
17
|
-
* specific prior written permission.
|
18
|
-
*
|
19
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
-
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
-
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
22
|
-
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
23
|
-
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
-
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
25
|
-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
26
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
27
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
-
*/
|
1
|
+
// Copyright (c) 2011 Peter Ohler. All rights reserved.
|
2
|
+
// Licensed under the MIT License. See LICENSE file in the project root for license details.
|
30
3
|
|
31
4
|
#ifndef OJ_VAL_STACK_H
|
32
5
|
#define OJ_VAL_STACK_H
|
33
6
|
|
34
|
-
#include "ruby.h"
|
35
|
-
#include "odd.h"
|
36
7
|
#include <stdint.h>
|
8
|
+
|
9
|
+
#include "odd.h"
|
10
|
+
#include "ruby.h"
|
37
11
|
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
38
12
|
#include <pthread.h>
|
39
13
|
#endif
|
40
14
|
|
41
|
-
#define STACK_INC
|
15
|
+
#define STACK_INC 64
|
42
16
|
|
43
17
|
typedef enum {
|
44
|
-
NEXT_NONE
|
45
|
-
NEXT_ARRAY_NEW
|
46
|
-
NEXT_ARRAY_ELEMENT
|
47
|
-
NEXT_ARRAY_COMMA
|
48
|
-
NEXT_HASH_NEW
|
49
|
-
NEXT_HASH_KEY
|
50
|
-
NEXT_HASH_COLON
|
51
|
-
NEXT_HASH_VALUE
|
52
|
-
NEXT_HASH_COMMA
|
18
|
+
NEXT_NONE = 0,
|
19
|
+
NEXT_ARRAY_NEW = 'a',
|
20
|
+
NEXT_ARRAY_ELEMENT = 'e',
|
21
|
+
NEXT_ARRAY_COMMA = ',',
|
22
|
+
NEXT_HASH_NEW = 'h',
|
23
|
+
NEXT_HASH_KEY = 'k',
|
24
|
+
NEXT_HASH_COLON = ':',
|
25
|
+
NEXT_HASH_VALUE = 'v',
|
26
|
+
NEXT_HASH_COMMA = 'n',
|
53
27
|
} ValNext;
|
54
28
|
|
55
29
|
typedef struct _val {
|
56
|
-
volatile VALUE
|
57
|
-
const char
|
58
|
-
char
|
59
|
-
volatile VALUE
|
60
|
-
const char
|
61
|
-
VALUE
|
62
|
-
OddArgs
|
63
|
-
uint16_t
|
64
|
-
uint16_t
|
65
|
-
char
|
66
|
-
char
|
67
|
-
char
|
68
|
-
} *Val;
|
30
|
+
volatile VALUE val;
|
31
|
+
const char * key;
|
32
|
+
char karray[32];
|
33
|
+
volatile VALUE key_val;
|
34
|
+
const char * classname;
|
35
|
+
VALUE clas;
|
36
|
+
OddArgs odd_args;
|
37
|
+
uint16_t klen;
|
38
|
+
uint16_t clen;
|
39
|
+
char next; // ValNext
|
40
|
+
char k1; // first original character in the key
|
41
|
+
char kalloc;
|
42
|
+
} * Val;
|
69
43
|
|
70
44
|
typedef struct _valStack {
|
71
|
-
struct _val
|
72
|
-
Val
|
73
|
-
Val
|
74
|
-
Val
|
45
|
+
struct _val base[STACK_INC];
|
46
|
+
Val head; // current stack
|
47
|
+
Val end; // stack end
|
48
|
+
Val tail; // pointer to one past last element name on stack
|
75
49
|
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
76
|
-
pthread_mutex_t
|
50
|
+
pthread_mutex_t mutex;
|
77
51
|
#else
|
78
|
-
VALUE
|
52
|
+
VALUE mutex;
|
79
53
|
#endif
|
80
54
|
|
81
|
-
} *ValStack;
|
55
|
+
} * ValStack;
|
82
56
|
|
83
|
-
extern VALUE
|
57
|
+
extern VALUE oj_stack_init(ValStack stack);
|
84
58
|
|
85
|
-
inline static int
|
86
|
-
stack_empty(ValStack stack) {
|
59
|
+
inline static int stack_empty(ValStack stack) {
|
87
60
|
return (stack->head == stack->tail);
|
88
61
|
}
|
89
62
|
|
90
|
-
inline static void
|
91
|
-
stack_cleanup(ValStack stack) {
|
63
|
+
inline static void stack_cleanup(ValStack stack) {
|
92
64
|
if (stack->base != stack->head) {
|
93
65
|
xfree(stack->head);
|
94
|
-
|
66
|
+
stack->head = NULL;
|
95
67
|
}
|
96
68
|
}
|
97
69
|
|
98
|
-
inline static void
|
99
|
-
stack_push(ValStack stack, VALUE val, ValNext next) {
|
70
|
+
inline static void stack_push(ValStack stack, VALUE val, ValNext next) {
|
100
71
|
if (stack->end <= stack->tail) {
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
72
|
+
size_t len = stack->end - stack->head;
|
73
|
+
size_t toff = stack->tail - stack->head;
|
74
|
+
Val head = stack->head;
|
75
|
+
|
76
|
+
// A realloc can trigger a GC so make sure it happens outside the lock
|
77
|
+
// but lock before changing pointers.
|
78
|
+
if (stack->base == stack->head) {
|
79
|
+
head = ALLOC_N(struct _val, len + STACK_INC);
|
80
|
+
memcpy(head, stack->base, sizeof(struct _val) * len);
|
81
|
+
} else {
|
82
|
+
REALLOC_N(head, struct _val, len + STACK_INC);
|
83
|
+
}
|
113
84
|
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
114
|
-
|
85
|
+
pthread_mutex_lock(&stack->mutex);
|
115
86
|
#else
|
116
|
-
|
87
|
+
rb_mutex_lock(stack->mutex);
|
117
88
|
#endif
|
118
|
-
|
119
|
-
|
120
|
-
|
89
|
+
stack->head = head;
|
90
|
+
stack->tail = stack->head + toff;
|
91
|
+
stack->end = stack->head + len + STACK_INC;
|
121
92
|
#ifdef HAVE_PTHREAD_MUTEX_INIT
|
122
|
-
|
93
|
+
pthread_mutex_unlock(&stack->mutex);
|
123
94
|
#else
|
124
|
-
|
95
|
+
rb_mutex_unlock(stack->mutex);
|
125
96
|
#endif
|
126
97
|
}
|
127
|
-
stack->tail->val
|
128
|
-
stack->tail->next
|
98
|
+
stack->tail->val = val;
|
99
|
+
stack->tail->next = next;
|
129
100
|
stack->tail->classname = NULL;
|
130
|
-
stack->tail->clas
|
131
|
-
stack->tail->odd_args
|
132
|
-
stack->tail->key
|
133
|
-
stack->tail->key_val
|
134
|
-
stack->tail->clen
|
135
|
-
stack->tail->klen
|
136
|
-
stack->tail->kalloc
|
101
|
+
stack->tail->clas = Qundef;
|
102
|
+
stack->tail->odd_args = NULL;
|
103
|
+
stack->tail->key = 0;
|
104
|
+
stack->tail->key_val = Qundef;
|
105
|
+
stack->tail->clen = 0;
|
106
|
+
stack->tail->klen = 0;
|
107
|
+
stack->tail->kalloc = 0;
|
137
108
|
stack->tail++;
|
138
109
|
}
|
139
110
|
|
140
|
-
inline static size_t
|
141
|
-
stack_size(ValStack stack) {
|
111
|
+
inline static size_t stack_size(ValStack stack) {
|
142
112
|
return stack->tail - stack->head;
|
143
113
|
}
|
144
114
|
|
145
|
-
inline static Val
|
146
|
-
stack_peek(ValStack stack) {
|
115
|
+
inline static Val stack_peek(ValStack stack) {
|
147
116
|
if (stack->head < stack->tail) {
|
148
|
-
|
117
|
+
return stack->tail - 1;
|
149
118
|
}
|
150
119
|
return 0;
|
151
120
|
}
|
152
121
|
|
153
|
-
inline static Val
|
154
|
-
stack_peek_up(ValStack stack) {
|
122
|
+
inline static Val stack_peek_up(ValStack stack) {
|
155
123
|
if (stack->head < stack->tail - 1) {
|
156
|
-
|
124
|
+
return stack->tail - 2;
|
157
125
|
}
|
158
126
|
return 0;
|
159
127
|
}
|
160
128
|
|
161
|
-
inline static Val
|
162
|
-
stack_prev(ValStack stack) {
|
129
|
+
inline static Val stack_prev(ValStack stack) {
|
163
130
|
return stack->tail;
|
164
131
|
}
|
165
132
|
|
166
|
-
inline static VALUE
|
167
|
-
stack_head_val(ValStack stack) {
|
133
|
+
inline static VALUE stack_head_val(ValStack stack) {
|
168
134
|
if (Qundef != stack->head->val) {
|
169
|
-
|
135
|
+
return stack->head->val;
|
170
136
|
}
|
171
137
|
return Qnil;
|
172
138
|
}
|
173
139
|
|
174
|
-
inline static Val
|
175
|
-
stack_pop(ValStack stack) {
|
140
|
+
inline static Val stack_pop(ValStack stack) {
|
176
141
|
if (stack->head < stack->tail) {
|
177
|
-
|
178
|
-
|
142
|
+
stack->tail--;
|
143
|
+
return stack->tail;
|
179
144
|
}
|
180
145
|
return 0;
|
181
146
|
}
|
182
147
|
|
183
|
-
extern const char*
|
148
|
+
extern const char *oj_stack_next_string(ValNext n);
|
184
149
|
|
185
150
|
#endif /* OJ_VAL_STACK_H */
|
data/ext/oj/wab.c
CHANGED
@@ -1,26 +1,25 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
* All rights reserved.
|
4
|
-
*/
|
1
|
+
// Copyright (c) 2012 Peter Ohler. All rights reserved.
|
2
|
+
// Licensed under the MIT License. See LICENSE file in the project root for license details.
|
5
3
|
|
6
|
-
#include <stdlib.h>
|
7
4
|
#include <stdio.h>
|
5
|
+
#include <stdlib.h>
|
8
6
|
#include <string.h>
|
9
7
|
#include <time.h>
|
10
8
|
#include <unistd.h>
|
11
9
|
|
12
|
-
#include "
|
10
|
+
#include "dump.h"
|
11
|
+
#include "encode.h"
|
13
12
|
#include "err.h"
|
13
|
+
#include "hash.h"
|
14
|
+
#include "oj.h"
|
14
15
|
#include "parse.h"
|
15
|
-
#include "encode.h"
|
16
|
-
#include "dump.h"
|
17
16
|
#include "trace.h"
|
18
17
|
#include "util.h"
|
19
18
|
|
20
19
|
// Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
|
21
|
-
#define OJ_INFINITY (1.0/0.0)
|
20
|
+
#define OJ_INFINITY (1.0 / 0.0)
|
22
21
|
|
23
|
-
static char
|
22
|
+
static char hex_chars[256] = "\
|
24
23
|
................................\
|
25
24
|
................xxxxxxxxxx......\
|
26
25
|
.xxxxxx.........................\
|
@@ -30,132 +29,128 @@ static char hex_chars[256] = "\
|
|
30
29
|
................................\
|
31
30
|
................................";
|
32
31
|
|
33
|
-
static VALUE
|
34
|
-
static VALUE
|
35
|
-
static VALUE
|
32
|
+
static VALUE wab_uuid_clas = Qundef;
|
33
|
+
static VALUE uri_clas = Qundef;
|
34
|
+
static VALUE uri_http_clas = Qundef;
|
36
35
|
|
37
36
|
///// dump functions /////
|
38
37
|
|
39
|
-
static VALUE
|
40
|
-
resolve_wab_uuid_class() {
|
38
|
+
static VALUE resolve_wab_uuid_class() {
|
41
39
|
if (Qundef == wab_uuid_clas) {
|
42
|
-
|
40
|
+
volatile VALUE wab_module;
|
43
41
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
42
|
+
wab_uuid_clas = Qnil;
|
43
|
+
if (rb_const_defined_at(rb_cObject, rb_intern("WAB"))) {
|
44
|
+
wab_module = rb_const_get_at(rb_cObject, rb_intern("WAB"));
|
45
|
+
if (rb_const_defined_at(wab_module, rb_intern("UUID"))) {
|
46
|
+
wab_uuid_clas = rb_const_get(wab_module, rb_intern("UUID"));
|
47
|
+
}
|
48
|
+
}
|
51
49
|
}
|
52
50
|
return wab_uuid_clas;
|
53
51
|
}
|
54
52
|
|
55
|
-
static VALUE
|
56
|
-
resolve_uri_class() {
|
53
|
+
static VALUE resolve_uri_class() {
|
57
54
|
if (Qundef == uri_clas) {
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
}
|
55
|
+
uri_clas = Qnil;
|
56
|
+
if (rb_const_defined_at(rb_cObject, rb_intern("URI"))) {
|
57
|
+
uri_clas = rb_const_get_at(rb_cObject, rb_intern("URI"));
|
58
|
+
}
|
63
59
|
}
|
64
60
|
return uri_clas;
|
65
61
|
}
|
66
62
|
|
67
|
-
static VALUE
|
68
|
-
resolve_uri_http_class() {
|
63
|
+
static VALUE resolve_uri_http_class() {
|
69
64
|
if (Qundef == uri_http_clas) {
|
70
|
-
|
65
|
+
volatile VALUE uri_module;
|
71
66
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
67
|
+
uri_http_clas = Qnil;
|
68
|
+
if (rb_const_defined_at(rb_cObject, rb_intern("URI"))) {
|
69
|
+
uri_module = rb_const_get_at(rb_cObject, rb_intern("URI"));
|
70
|
+
if (rb_const_defined_at(uri_module, rb_intern("HTTP"))) {
|
71
|
+
uri_http_clas = rb_const_get(uri_module, rb_intern("HTTP"));
|
72
|
+
}
|
73
|
+
}
|
79
74
|
}
|
80
75
|
return uri_http_clas;
|
81
76
|
}
|
82
77
|
|
83
|
-
static void
|
84
|
-
|
85
|
-
|
78
|
+
static void raise_wab(VALUE obj) {
|
79
|
+
rb_raise(rb_eTypeError,
|
80
|
+
"Failed to dump %s Object to JSON in wab mode.\n",
|
81
|
+
rb_class2name(rb_obj_class(obj)));
|
86
82
|
}
|
87
83
|
|
88
84
|
// Removed dependencies on math due to problems with CentOS 5.4.
|
89
|
-
static void
|
90
|
-
|
91
|
-
char
|
92
|
-
|
93
|
-
|
94
|
-
int cnt = 0;
|
85
|
+
static void dump_float(VALUE obj, int depth, Out out, bool as_ok) {
|
86
|
+
char buf[64];
|
87
|
+
char * b;
|
88
|
+
double d = rb_num2dbl(obj);
|
89
|
+
int cnt = 0;
|
95
90
|
|
96
91
|
if (0.0 == d) {
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
92
|
+
b = buf;
|
93
|
+
*b++ = '0';
|
94
|
+
*b++ = '.';
|
95
|
+
*b++ = '0';
|
96
|
+
*b++ = '\0';
|
97
|
+
cnt = 3;
|
103
98
|
} else {
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
99
|
+
if (OJ_INFINITY == d || -OJ_INFINITY == d || isnan(d)) {
|
100
|
+
raise_wab(obj);
|
101
|
+
} else if (d == (double)(long long int)d) {
|
102
|
+
cnt = snprintf(buf, sizeof(buf), "%.1f", d);
|
103
|
+
} else {
|
104
|
+
cnt = snprintf(buf, sizeof(buf), "%0.16g", d);
|
105
|
+
}
|
111
106
|
}
|
112
107
|
assure_size(out, cnt);
|
113
108
|
for (b = buf; '\0' != *b; b++) {
|
114
|
-
|
109
|
+
*out->cur++ = *b;
|
115
110
|
}
|
116
111
|
*out->cur = '\0';
|
117
112
|
}
|
118
113
|
|
119
|
-
static void
|
120
|
-
|
121
|
-
|
122
|
-
int
|
123
|
-
int d2 = depth + 1;
|
114
|
+
static void dump_array(VALUE a, int depth, Out out, bool as_ok) {
|
115
|
+
size_t size;
|
116
|
+
int i, cnt;
|
117
|
+
int d2 = depth + 1;
|
124
118
|
|
125
|
-
cnt
|
119
|
+
cnt = (int)RARRAY_LEN(a);
|
126
120
|
*out->cur++ = '[';
|
127
|
-
size
|
121
|
+
size = 2;
|
128
122
|
assure_size(out, size);
|
129
123
|
if (0 == cnt) {
|
130
|
-
|
124
|
+
*out->cur++ = ']';
|
131
125
|
} else {
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
126
|
+
size = d2 * out->indent + 2;
|
127
|
+
cnt--;
|
128
|
+
for (i = 0; i <= cnt; i++) {
|
129
|
+
assure_size(out, size);
|
130
|
+
fill_indent(out, d2);
|
131
|
+
oj_dump_wab_val(rb_ary_entry(a, i), d2, out);
|
132
|
+
if (i < cnt) {
|
133
|
+
*out->cur++ = ',';
|
134
|
+
}
|
135
|
+
}
|
136
|
+
size = depth * out->indent + 1;
|
137
|
+
assure_size(out, size);
|
138
|
+
fill_indent(out, depth);
|
139
|
+
*out->cur++ = ']';
|
146
140
|
}
|
147
141
|
*out->cur = '\0';
|
148
142
|
}
|
149
143
|
|
150
|
-
static int
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
int rtype = rb_type(key);
|
144
|
+
static int hash_cb(VALUE key, VALUE value, VALUE ov) {
|
145
|
+
Out out = (Out)ov;
|
146
|
+
int depth = out->depth;
|
147
|
+
long size;
|
148
|
+
int rtype = rb_type(key);
|
156
149
|
|
157
150
|
if (rtype != T_SYMBOL) {
|
158
|
-
|
151
|
+
rb_raise(rb_eTypeError,
|
152
|
+
"In :wab mode all Hash keys must be Symbols, not %s.\n",
|
153
|
+
rb_class2name(rb_obj_class(key)));
|
159
154
|
}
|
160
155
|
size = depth * out->indent + 1;
|
161
156
|
assure_size(out, size);
|
@@ -163,56 +158,54 @@ hash_cb(VALUE key, VALUE value, VALUE ov) {
|
|
163
158
|
oj_dump_sym(key, 0, out, false);
|
164
159
|
*out->cur++ = ':';
|
165
160
|
oj_dump_wab_val(value, depth, out);
|
166
|
-
out->depth
|
161
|
+
out->depth = depth;
|
167
162
|
*out->cur++ = ',';
|
168
163
|
|
169
164
|
return ST_CONTINUE;
|
170
165
|
}
|
171
166
|
|
172
|
-
static void
|
173
|
-
|
174
|
-
|
175
|
-
size_t size;
|
167
|
+
static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
|
168
|
+
int cnt;
|
169
|
+
size_t size;
|
176
170
|
|
177
|
-
cnt
|
171
|
+
cnt = (int)RHASH_SIZE(obj);
|
178
172
|
size = depth * out->indent + 2;
|
179
173
|
assure_size(out, 2);
|
180
174
|
*out->cur++ = '{';
|
181
175
|
if (0 == cnt) {
|
182
|
-
|
176
|
+
*out->cur++ = '}';
|
183
177
|
} else {
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
178
|
+
out->depth = depth + 1;
|
179
|
+
rb_hash_foreach(obj, hash_cb, (VALUE)out);
|
180
|
+
if (',' == *(out->cur - 1)) {
|
181
|
+
out->cur--; // backup to overwrite last comma
|
182
|
+
}
|
183
|
+
assure_size(out, size);
|
184
|
+
fill_indent(out, depth);
|
185
|
+
*out->cur++ = '}';
|
192
186
|
}
|
193
187
|
*out->cur = '\0';
|
194
188
|
}
|
195
189
|
|
196
|
-
static void
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
long long nsec;
|
190
|
+
static void dump_time(VALUE obj, Out out) {
|
191
|
+
char buf[64];
|
192
|
+
struct _timeInfo ti;
|
193
|
+
int len;
|
194
|
+
time_t sec;
|
195
|
+
long long nsec;
|
203
196
|
|
204
197
|
#ifdef HAVE_RB_TIME_TIMESPEC
|
205
198
|
if (16 <= sizeof(struct timespec)) {
|
206
|
-
|
199
|
+
struct timespec ts = rb_time_timespec(obj);
|
207
200
|
|
208
|
-
|
209
|
-
|
201
|
+
sec = ts.tv_sec;
|
202
|
+
nsec = ts.tv_nsec;
|
210
203
|
} else {
|
211
|
-
|
212
|
-
|
204
|
+
sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
205
|
+
nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
213
206
|
}
|
214
207
|
#else
|
215
|
-
sec
|
208
|
+
sec = rb_num2ll(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
|
216
209
|
nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
|
217
210
|
#endif
|
218
211
|
|
@@ -220,210 +213,230 @@ dump_time(VALUE obj, Out out) {
|
|
220
213
|
// 2012-01-05T23:58:07.123456000Z
|
221
214
|
sec_as_time(sec, &ti);
|
222
215
|
|
223
|
-
len = sprintf(buf,
|
216
|
+
len = sprintf(buf,
|
217
|
+
"%04d-%02d-%02dT%02d:%02d:%02d.%09ldZ",
|
218
|
+
ti.year,
|
219
|
+
ti.mon,
|
220
|
+
ti.day,
|
221
|
+
ti.hour,
|
222
|
+
ti.min,
|
223
|
+
ti.sec,
|
224
|
+
(long)nsec);
|
224
225
|
oj_dump_cstr(buf, len, 0, 0, out);
|
225
226
|
}
|
226
227
|
|
227
|
-
static void
|
228
|
-
|
229
|
-
volatile VALUE clas = rb_obj_class(obj);
|
228
|
+
static void dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
|
229
|
+
volatile VALUE clas = rb_obj_class(obj);
|
230
230
|
|
231
231
|
if (rb_cTime == clas) {
|
232
|
-
|
232
|
+
dump_time(obj, out);
|
233
233
|
} else if (oj_bigdecimal_class == clas) {
|
234
|
-
|
234
|
+
volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
|
235
235
|
|
236
|
-
|
236
|
+
oj_dump_raw(rb_string_value_ptr((VALUE *)&rstr), (int)RSTRING_LEN(rstr), out);
|
237
237
|
} else if (resolve_wab_uuid_class() == clas) {
|
238
|
-
|
238
|
+
oj_dump_str(rb_funcall(obj, oj_to_s_id, 0), depth, out, false);
|
239
239
|
} else if (resolve_uri_http_class() == clas) {
|
240
|
-
|
240
|
+
oj_dump_str(rb_funcall(obj, oj_to_s_id, 0), depth, out, false);
|
241
241
|
} else {
|
242
|
-
|
243
|
-
}
|
244
|
-
}
|
245
|
-
|
246
|
-
static DumpFunc
|
247
|
-
NULL,
|
248
|
-
dump_obj,
|
249
|
-
NULL,
|
250
|
-
NULL,
|
251
|
-
dump_float,
|
252
|
-
oj_dump_str,
|
253
|
-
NULL,
|
254
|
-
dump_array,
|
255
|
-
dump_hash,
|
256
|
-
NULL,
|
257
|
-
oj_dump_bignum,
|
258
|
-
NULL,
|
259
|
-
dump_obj,
|
260
|
-
NULL,
|
261
|
-
NULL,
|
262
|
-
NULL,
|
263
|
-
NULL,
|
264
|
-
oj_dump_nil,
|
265
|
-
oj_dump_true,
|
266
|
-
oj_dump_false,
|
267
|
-
oj_dump_sym,
|
268
|
-
oj_dump_fixnum,
|
242
|
+
raise_wab(obj);
|
243
|
+
}
|
244
|
+
}
|
245
|
+
|
246
|
+
static DumpFunc wab_funcs[] = {
|
247
|
+
NULL, // RUBY_T_NONE = 0x00,
|
248
|
+
dump_obj, // RUBY_T_OBJECT = 0x01,
|
249
|
+
NULL, // RUBY_T_CLASS = 0x02,
|
250
|
+
NULL, // RUBY_T_MODULE = 0x03,
|
251
|
+
dump_float, // RUBY_T_FLOAT = 0x04,
|
252
|
+
oj_dump_str, // RUBY_T_STRING = 0x05,
|
253
|
+
NULL, // RUBY_T_REGEXP = 0x06,
|
254
|
+
dump_array, // RUBY_T_ARRAY = 0x07,
|
255
|
+
dump_hash, // RUBY_T_HASH = 0x08,
|
256
|
+
NULL, // RUBY_T_STRUCT = 0x09,
|
257
|
+
oj_dump_bignum, // RUBY_T_BIGNUM = 0x0a,
|
258
|
+
NULL, // RUBY_T_FILE = 0x0b,
|
259
|
+
dump_obj, // RUBY_T_DATA = 0x0c,
|
260
|
+
NULL, // RUBY_T_MATCH = 0x0d,
|
261
|
+
NULL, // RUBY_T_COMPLEX = 0x0e,
|
262
|
+
NULL, // RUBY_T_RATIONAL = 0x0f,
|
263
|
+
NULL, // 0x10
|
264
|
+
oj_dump_nil, // RUBY_T_NIL = 0x11,
|
265
|
+
oj_dump_true, // RUBY_T_TRUE = 0x12,
|
266
|
+
oj_dump_false, // RUBY_T_FALSE = 0x13,
|
267
|
+
oj_dump_sym, // RUBY_T_SYMBOL = 0x14,
|
268
|
+
oj_dump_fixnum, // RUBY_T_FIXNUM = 0x15,
|
269
269
|
};
|
270
270
|
|
271
|
-
void
|
272
|
-
|
273
|
-
int type = rb_type(obj);
|
271
|
+
void oj_dump_wab_val(VALUE obj, int depth, Out out) {
|
272
|
+
int type = rb_type(obj);
|
274
273
|
|
275
274
|
if (Yes == out->opts->trace) {
|
276
|
-
|
275
|
+
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceIn);
|
277
276
|
}
|
278
277
|
if (MAX_DEPTH < depth) {
|
279
|
-
|
278
|
+
rb_raise(rb_eNoMemError, "Too deeply nested.\n");
|
280
279
|
}
|
281
280
|
if (0 < type && type <= RUBY_T_FIXNUM) {
|
282
|
-
|
281
|
+
DumpFunc f = wab_funcs[type];
|
283
282
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
283
|
+
if (NULL != f) {
|
284
|
+
f(obj, depth, out, false);
|
285
|
+
if (Yes == out->opts->trace) {
|
286
|
+
oj_trace("dump", obj, __FILE__, __LINE__, depth, TraceOut);
|
287
|
+
}
|
288
|
+
return;
|
289
|
+
}
|
291
290
|
}
|
292
291
|
raise_wab(obj);
|
293
292
|
}
|
294
293
|
|
295
294
|
///// load functions /////
|
296
295
|
|
297
|
-
static
|
298
|
-
|
296
|
+
static VALUE oj_hash_key(Val parent) {
|
297
|
+
volatile VALUE rkey = parent->key_val;
|
298
|
+
|
299
|
+
if (Qundef != rkey) {
|
300
|
+
rkey = oj_encode(rkey);
|
301
|
+
rkey = rb_str_intern(rkey);
|
302
|
+
|
303
|
+
return rkey;
|
304
|
+
}
|
305
|
+
VALUE *slot;
|
306
|
+
|
307
|
+
if (Qnil == (rkey = oj_sym_hash_get(parent->key, parent->klen, &slot))) {
|
308
|
+
rkey = rb_str_new(parent->key, parent->klen);
|
309
|
+
rkey = oj_encode(rkey);
|
310
|
+
rkey = rb_str_intern(rkey);
|
311
|
+
*slot = rkey;
|
312
|
+
rb_gc_register_address(slot);
|
313
|
+
}
|
314
|
+
return rkey;
|
315
|
+
}
|
316
|
+
|
317
|
+
static void hash_end(ParseInfo pi) {
|
299
318
|
if (Yes == pi->options.trace) {
|
300
|
-
|
319
|
+
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
301
320
|
}
|
302
321
|
}
|
303
322
|
|
304
|
-
static void
|
305
|
-
array_end(ParseInfo pi) {
|
323
|
+
static void array_end(ParseInfo pi) {
|
306
324
|
if (Yes == pi->options.trace) {
|
307
|
-
|
325
|
+
oj_trace_parse_array_end(pi, __FILE__, __LINE__);
|
308
326
|
}
|
309
327
|
}
|
310
328
|
|
311
|
-
static VALUE
|
312
|
-
noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
|
329
|
+
static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
|
313
330
|
return Qundef;
|
314
331
|
}
|
315
332
|
|
316
|
-
static void
|
317
|
-
add_value(ParseInfo pi, VALUE val) {
|
333
|
+
static void add_value(ParseInfo pi, VALUE val) {
|
318
334
|
if (Yes == pi->options.trace) {
|
319
|
-
|
335
|
+
oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, val);
|
320
336
|
}
|
321
337
|
pi->stack.head->val = val;
|
322
338
|
}
|
323
339
|
|
324
340
|
// 123e4567-e89b-12d3-a456-426655440000
|
325
|
-
static bool
|
326
|
-
|
327
|
-
int i;
|
341
|
+
static bool uuid_check(const char *str, int len) {
|
342
|
+
int i;
|
328
343
|
|
329
344
|
for (i = 0; i < 8; i++, str++) {
|
330
|
-
|
331
|
-
|
332
|
-
|
345
|
+
if ('x' != hex_chars[*(uint8_t *)str]) {
|
346
|
+
return false;
|
347
|
+
}
|
333
348
|
}
|
334
349
|
str++;
|
335
350
|
for (i = 0; i < 4; i++, str++) {
|
336
|
-
|
337
|
-
|
338
|
-
|
351
|
+
if ('x' != hex_chars[*(uint8_t *)str]) {
|
352
|
+
return false;
|
353
|
+
}
|
339
354
|
}
|
340
355
|
str++;
|
341
356
|
for (i = 0; i < 4; i++, str++) {
|
342
|
-
|
343
|
-
|
344
|
-
|
357
|
+
if ('x' != hex_chars[*(uint8_t *)str]) {
|
358
|
+
return false;
|
359
|
+
}
|
345
360
|
}
|
346
361
|
str++;
|
347
362
|
for (i = 0; i < 4; i++, str++) {
|
348
|
-
|
349
|
-
|
350
|
-
|
363
|
+
if ('x' != hex_chars[*(uint8_t *)str]) {
|
364
|
+
return false;
|
365
|
+
}
|
351
366
|
}
|
352
367
|
str++;
|
353
368
|
for (i = 0; i < 12; i++, str++) {
|
354
|
-
|
355
|
-
|
356
|
-
|
369
|
+
if ('x' != hex_chars[*(uint8_t *)str]) {
|
370
|
+
return false;
|
371
|
+
}
|
357
372
|
}
|
358
373
|
return true;
|
359
374
|
}
|
360
375
|
|
361
|
-
static const char*
|
362
|
-
|
363
|
-
uint32_t v = 0;
|
376
|
+
static const char *read_num(const char *s, int len, int *vp) {
|
377
|
+
uint32_t v = 0;
|
364
378
|
|
365
379
|
for (; 0 < len; len--, s++) {
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
380
|
+
if ('0' <= *s && *s <= '9') {
|
381
|
+
v = v * 10 + *s - '0';
|
382
|
+
} else {
|
383
|
+
return NULL;
|
384
|
+
}
|
371
385
|
}
|
372
386
|
*vp = (int)v;
|
373
387
|
|
374
388
|
return s;
|
375
389
|
}
|
376
390
|
|
377
|
-
static VALUE
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
time_t secs;
|
391
|
+
static VALUE time_parse(const char *s, int len) {
|
392
|
+
struct tm tm;
|
393
|
+
bool neg = false;
|
394
|
+
long nsecs = 0;
|
395
|
+
int i;
|
396
|
+
time_t secs;
|
384
397
|
|
385
398
|
memset(&tm, 0, sizeof(tm));
|
386
399
|
if ('-' == *s) {
|
387
|
-
|
388
|
-
|
400
|
+
s++;
|
401
|
+
neg = true;
|
389
402
|
}
|
390
403
|
if (NULL == (s = read_num(s, 4, &tm.tm_year))) {
|
391
|
-
|
404
|
+
return Qnil;
|
392
405
|
}
|
393
406
|
if (neg) {
|
394
|
-
|
395
|
-
|
407
|
+
tm.tm_year = -tm.tm_year;
|
408
|
+
neg = false;
|
396
409
|
}
|
397
410
|
tm.tm_year -= 1900;
|
398
411
|
s++;
|
399
412
|
if (NULL == (s = read_num(s, 2, &tm.tm_mon))) {
|
400
|
-
|
413
|
+
return Qnil;
|
401
414
|
}
|
402
415
|
tm.tm_mon--;
|
403
416
|
s++;
|
404
417
|
if (NULL == (s = read_num(s, 2, &tm.tm_mday))) {
|
405
|
-
|
418
|
+
return Qnil;
|
406
419
|
}
|
407
420
|
s++;
|
408
421
|
if (NULL == (s = read_num(s, 2, &tm.tm_hour))) {
|
409
|
-
|
422
|
+
return Qnil;
|
410
423
|
}
|
411
424
|
s++;
|
412
425
|
if (NULL == (s = read_num(s, 2, &tm.tm_min))) {
|
413
|
-
|
426
|
+
return Qnil;
|
414
427
|
}
|
415
428
|
s++;
|
416
429
|
if (NULL == (s = read_num(s, 2, &tm.tm_sec))) {
|
417
|
-
|
430
|
+
return Qnil;
|
418
431
|
}
|
419
432
|
s++;
|
420
433
|
|
421
434
|
for (i = 9; 0 < i; i--, s++) {
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
435
|
+
if ('0' <= *s && *s <= '9') {
|
436
|
+
nsecs = nsecs * 10 + *s - '0';
|
437
|
+
} else {
|
438
|
+
return Qnil;
|
439
|
+
}
|
427
440
|
}
|
428
441
|
#if IS_WINDOWS
|
429
442
|
secs = (time_t)mktime(&tm);
|
@@ -437,193 +450,169 @@ time_parse(const char *s, int len) {
|
|
437
450
|
return rb_funcall(rb_time_nano_new(secs, nsecs), oj_utc_id, 0);
|
438
451
|
}
|
439
452
|
|
440
|
-
static VALUE
|
441
|
-
protect_uri(VALUE rstr) {
|
453
|
+
static VALUE protect_uri(VALUE rstr) {
|
442
454
|
return rb_funcall(resolve_uri_class(), oj_parse_id, 1, rstr);
|
443
455
|
}
|
444
456
|
|
445
|
-
static VALUE
|
446
|
-
|
447
|
-
volatile VALUE v = Qnil;
|
457
|
+
static VALUE cstr_to_rstr(ParseInfo pi, const char *str, size_t len) {
|
458
|
+
volatile VALUE v = Qnil;
|
448
459
|
|
449
|
-
if (30 == len && '-' == str[4] && '-' == str[7] && 'T' == str[10] && ':' == str[13] &&
|
450
|
-
|
451
|
-
|
452
|
-
|
460
|
+
if (30 == len && '-' == str[4] && '-' == str[7] && 'T' == str[10] && ':' == str[13] &&
|
461
|
+
':' == str[16] && '.' == str[19] && 'Z' == str[29]) {
|
462
|
+
if (Qnil != (v = time_parse(str, (int)len))) {
|
463
|
+
return v;
|
464
|
+
}
|
453
465
|
}
|
454
|
-
if (36 == len && '-' == str[8] && '-' == str[13] && '-' == str[18] && '-' == str[23] &&
|
455
|
-
|
466
|
+
if (36 == len && '-' == str[8] && '-' == str[13] && '-' == str[18] && '-' == str[23] &&
|
467
|
+
uuid_check(str, (int)len) && Qnil != resolve_wab_uuid_class()) {
|
468
|
+
return rb_funcall(wab_uuid_clas, oj_new_id, 1, rb_str_new(str, len));
|
456
469
|
}
|
457
|
-
v = rb_str_new(str, len);
|
458
470
|
if (7 < len && 0 == strncasecmp("http://", str, 7)) {
|
459
|
-
|
460
|
-
|
471
|
+
int err = 0;
|
472
|
+
v = rb_str_new(str, len);
|
473
|
+
volatile VALUE uri = rb_protect(protect_uri, v, &err);
|
461
474
|
|
462
|
-
|
463
|
-
|
464
|
-
|
475
|
+
if (0 == err) {
|
476
|
+
return uri;
|
477
|
+
}
|
465
478
|
}
|
466
|
-
return
|
479
|
+
return oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
|
467
480
|
}
|
468
481
|
|
469
|
-
static void
|
470
|
-
|
471
|
-
pi->stack.head->val = cstr_to_rstr(str, len);
|
482
|
+
static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
483
|
+
pi->stack.head->val = cstr_to_rstr(pi, str, len);
|
472
484
|
if (Yes == pi->options.trace) {
|
473
|
-
|
485
|
+
oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
|
474
486
|
}
|
475
487
|
}
|
476
488
|
|
477
|
-
static void
|
478
|
-
add_num(ParseInfo pi, NumInfo ni) {
|
489
|
+
static void add_num(ParseInfo pi, NumInfo ni) {
|
479
490
|
if (ni->infinity || ni->nan) {
|
480
|
-
|
491
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
481
492
|
}
|
482
493
|
pi->stack.head->val = oj_num_as_value(ni);
|
483
494
|
if (Yes == pi->options.trace) {
|
484
|
-
|
495
|
+
oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
|
485
496
|
}
|
486
497
|
}
|
487
498
|
|
488
|
-
static VALUE
|
489
|
-
start_hash(ParseInfo pi) {
|
499
|
+
static VALUE start_hash(ParseInfo pi) {
|
490
500
|
if (Yes == pi->options.trace) {
|
491
|
-
|
501
|
+
oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
|
492
502
|
}
|
493
503
|
if (Qnil != pi->options.hash_class) {
|
494
|
-
|
504
|
+
return rb_class_new_instance(0, NULL, pi->options.hash_class);
|
495
505
|
}
|
496
506
|
return rb_hash_new();
|
497
507
|
}
|
498
508
|
|
499
|
-
static
|
500
|
-
|
501
|
-
volatile VALUE rkey = parent->key_val;
|
509
|
+
static void hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
|
510
|
+
volatile VALUE rval = cstr_to_rstr(pi, str, len);
|
502
511
|
|
503
|
-
|
504
|
-
rkey = rb_str_new(parent->key, parent->klen);
|
505
|
-
}
|
506
|
-
rkey = oj_encode(rkey);
|
507
|
-
rkey = rb_str_intern(rkey);
|
508
|
-
|
509
|
-
return rkey;
|
510
|
-
}
|
511
|
-
|
512
|
-
static void
|
513
|
-
hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
|
514
|
-
volatile VALUE rval = cstr_to_rstr(str, len);
|
515
|
-
|
516
|
-
rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rval);
|
512
|
+
rb_hash_aset(stack_peek(&pi->stack)->val, oj_hash_key(parent), rval);
|
517
513
|
if (Yes == pi->options.trace) {
|
518
|
-
|
514
|
+
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
|
519
515
|
}
|
520
516
|
}
|
521
517
|
|
522
|
-
static void
|
523
|
-
|
524
|
-
volatile VALUE rval = Qnil;
|
518
|
+
static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
|
519
|
+
volatile VALUE rval = Qnil;
|
525
520
|
|
526
521
|
if (ni->infinity || ni->nan) {
|
527
|
-
|
522
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
528
523
|
}
|
529
524
|
rval = oj_num_as_value(ni);
|
530
|
-
rb_hash_aset(stack_peek(&pi->stack)->val,
|
525
|
+
rb_hash_aset(stack_peek(&pi->stack)->val, oj_hash_key(parent), rval);
|
531
526
|
if (Yes == pi->options.trace) {
|
532
|
-
|
527
|
+
oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, rval);
|
533
528
|
}
|
534
529
|
}
|
535
530
|
|
536
|
-
static void
|
537
|
-
|
538
|
-
rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), value);
|
531
|
+
static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
|
532
|
+
rb_hash_aset(stack_peek(&pi->stack)->val, oj_hash_key(parent), value);
|
539
533
|
if (Yes == pi->options.trace) {
|
540
|
-
|
534
|
+
oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
|
541
535
|
}
|
542
536
|
}
|
543
537
|
|
544
|
-
static VALUE
|
545
|
-
start_array(ParseInfo pi) {
|
538
|
+
static VALUE start_array(ParseInfo pi) {
|
546
539
|
if (Yes == pi->options.trace) {
|
547
|
-
|
540
|
+
oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
|
548
541
|
}
|
549
542
|
return rb_ary_new();
|
550
543
|
}
|
551
544
|
|
552
|
-
static void
|
553
|
-
|
554
|
-
volatile VALUE rval = cstr_to_rstr(str, len);
|
545
|
+
static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
546
|
+
volatile VALUE rval = cstr_to_rstr(pi, str, len);
|
555
547
|
|
556
548
|
rb_ary_push(stack_peek(&pi->stack)->val, rval);
|
557
549
|
if (Yes == pi->options.trace) {
|
558
|
-
|
550
|
+
oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, rval);
|
559
551
|
}
|
560
552
|
}
|
561
553
|
|
562
|
-
static void
|
563
|
-
|
564
|
-
volatile VALUE rval = Qnil;
|
554
|
+
static void array_append_num(ParseInfo pi, NumInfo ni) {
|
555
|
+
volatile VALUE rval = Qnil;
|
565
556
|
|
566
557
|
if (ni->infinity || ni->nan) {
|
567
|
-
|
558
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
568
559
|
}
|
569
560
|
rval = oj_num_as_value(ni);
|
570
561
|
rb_ary_push(stack_peek(&pi->stack)->val, rval);
|
571
562
|
if (Yes == pi->options.trace) {
|
572
|
-
|
563
|
+
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
|
573
564
|
}
|
574
565
|
}
|
575
566
|
|
576
|
-
static void
|
577
|
-
array_append_value(ParseInfo pi, VALUE value) {
|
567
|
+
static void array_append_value(ParseInfo pi, VALUE value) {
|
578
568
|
rb_ary_push(stack_peek(&pi->stack)->val, value);
|
579
569
|
if (Yes == pi->options.trace) {
|
580
|
-
|
581
|
-
}
|
582
|
-
}
|
583
|
-
|
584
|
-
void
|
585
|
-
|
586
|
-
pi->
|
587
|
-
pi->
|
588
|
-
pi->
|
589
|
-
pi->
|
590
|
-
pi->
|
591
|
-
pi->
|
592
|
-
pi->
|
593
|
-
pi->
|
594
|
-
pi->
|
595
|
-
pi->array_append_num = array_append_num;
|
570
|
+
oj_trace_parse_call("append_value", pi, __FILE__, __LINE__, value);
|
571
|
+
}
|
572
|
+
}
|
573
|
+
|
574
|
+
void oj_set_wab_callbacks(ParseInfo pi) {
|
575
|
+
pi->start_hash = start_hash;
|
576
|
+
pi->end_hash = hash_end;
|
577
|
+
pi->hash_key = noop_hash_key;
|
578
|
+
pi->hash_set_cstr = hash_set_cstr;
|
579
|
+
pi->hash_set_num = hash_set_num;
|
580
|
+
pi->hash_set_value = hash_set_value;
|
581
|
+
pi->start_array = start_array;
|
582
|
+
pi->end_array = array_end;
|
583
|
+
pi->array_append_cstr = array_append_cstr;
|
584
|
+
pi->array_append_num = array_append_num;
|
596
585
|
pi->array_append_value = array_append_value;
|
597
|
-
pi->add_cstr
|
598
|
-
pi->add_num
|
599
|
-
pi->add_value
|
600
|
-
pi->expect_value
|
586
|
+
pi->add_cstr = add_cstr;
|
587
|
+
pi->add_num = add_num;
|
588
|
+
pi->add_value = add_value;
|
589
|
+
pi->expect_value = 1;
|
601
590
|
}
|
602
591
|
|
603
592
|
VALUE
|
604
593
|
oj_wab_parse(int argc, VALUE *argv, VALUE self) {
|
605
|
-
struct _parseInfo
|
594
|
+
struct _parseInfo pi;
|
606
595
|
|
607
596
|
parse_info_init(&pi);
|
608
|
-
pi.options
|
609
|
-
pi.handler
|
597
|
+
pi.options = oj_default_options;
|
598
|
+
pi.handler = Qnil;
|
610
599
|
pi.err_class = Qnil;
|
611
600
|
oj_set_wab_callbacks(&pi);
|
612
601
|
|
613
602
|
if (T_STRING == rb_type(*argv)) {
|
614
|
-
|
603
|
+
return oj_pi_parse(argc, argv, &pi, 0, 0, true);
|
615
604
|
} else {
|
616
|
-
|
605
|
+
return oj_pi_sparse(argc, argv, &pi, 0);
|
617
606
|
}
|
618
607
|
}
|
619
608
|
|
620
609
|
VALUE
|
621
610
|
oj_wab_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
|
622
|
-
struct _parseInfo
|
611
|
+
struct _parseInfo pi;
|
623
612
|
|
624
613
|
parse_info_init(&pi);
|
625
|
-
pi.options
|
626
|
-
pi.handler
|
614
|
+
pi.options = oj_default_options;
|
615
|
+
pi.handler = Qnil;
|
627
616
|
pi.err_class = Qnil;
|
628
617
|
oj_set_wab_callbacks(&pi);
|
629
618
|
|