oj 3.10.6 → 3.12.1
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 +176 -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 +102 -97
- 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 +1186 -906
- 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 +321 -325
- 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 +47 -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,237 @@ 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 calc_hash_key(ParseInfo pi, 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
|
+
if (Yes != pi->options.cache_keys) {
|
306
|
+
rkey = rb_str_new(parent->key, parent->klen);
|
307
|
+
rkey = oj_encode(rkey);
|
308
|
+
rkey = rb_str_intern(rkey);
|
309
|
+
|
310
|
+
return rkey;
|
311
|
+
}
|
312
|
+
VALUE *slot;
|
313
|
+
|
314
|
+
if (Qnil == (rkey = oj_sym_hash_get(parent->key, parent->klen, &slot))) {
|
315
|
+
rkey = rb_str_new(parent->key, parent->klen);
|
316
|
+
rkey = oj_encode(rkey);
|
317
|
+
rkey = rb_str_intern(rkey);
|
318
|
+
*slot = rkey;
|
319
|
+
rb_gc_register_address(slot);
|
320
|
+
}
|
321
|
+
return rkey;
|
322
|
+
}
|
323
|
+
|
324
|
+
static void hash_end(ParseInfo pi) {
|
299
325
|
if (Yes == pi->options.trace) {
|
300
|
-
|
326
|
+
oj_trace_parse_hash_end(pi, __FILE__, __LINE__);
|
301
327
|
}
|
302
328
|
}
|
303
329
|
|
304
|
-
static void
|
305
|
-
array_end(ParseInfo pi) {
|
330
|
+
static void array_end(ParseInfo pi) {
|
306
331
|
if (Yes == pi->options.trace) {
|
307
|
-
|
332
|
+
oj_trace_parse_array_end(pi, __FILE__, __LINE__);
|
308
333
|
}
|
309
334
|
}
|
310
335
|
|
311
|
-
static VALUE
|
312
|
-
noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
|
336
|
+
static VALUE noop_hash_key(ParseInfo pi, const char *key, size_t klen) {
|
313
337
|
return Qundef;
|
314
338
|
}
|
315
339
|
|
316
|
-
static void
|
317
|
-
add_value(ParseInfo pi, VALUE val) {
|
340
|
+
static void add_value(ParseInfo pi, VALUE val) {
|
318
341
|
if (Yes == pi->options.trace) {
|
319
|
-
|
342
|
+
oj_trace_parse_call("add_value", pi, __FILE__, __LINE__, val);
|
320
343
|
}
|
321
344
|
pi->stack.head->val = val;
|
322
345
|
}
|
323
346
|
|
324
347
|
// 123e4567-e89b-12d3-a456-426655440000
|
325
|
-
static bool
|
326
|
-
|
327
|
-
int i;
|
348
|
+
static bool uuid_check(const char *str, int len) {
|
349
|
+
int i;
|
328
350
|
|
329
351
|
for (i = 0; i < 8; i++, str++) {
|
330
|
-
|
331
|
-
|
332
|
-
|
352
|
+
if ('x' != hex_chars[*(uint8_t *)str]) {
|
353
|
+
return false;
|
354
|
+
}
|
333
355
|
}
|
334
356
|
str++;
|
335
357
|
for (i = 0; i < 4; i++, str++) {
|
336
|
-
|
337
|
-
|
338
|
-
|
358
|
+
if ('x' != hex_chars[*(uint8_t *)str]) {
|
359
|
+
return false;
|
360
|
+
}
|
339
361
|
}
|
340
362
|
str++;
|
341
363
|
for (i = 0; i < 4; i++, str++) {
|
342
|
-
|
343
|
-
|
344
|
-
|
364
|
+
if ('x' != hex_chars[*(uint8_t *)str]) {
|
365
|
+
return false;
|
366
|
+
}
|
345
367
|
}
|
346
368
|
str++;
|
347
369
|
for (i = 0; i < 4; i++, str++) {
|
348
|
-
|
349
|
-
|
350
|
-
|
370
|
+
if ('x' != hex_chars[*(uint8_t *)str]) {
|
371
|
+
return false;
|
372
|
+
}
|
351
373
|
}
|
352
374
|
str++;
|
353
375
|
for (i = 0; i < 12; i++, str++) {
|
354
|
-
|
355
|
-
|
356
|
-
|
376
|
+
if ('x' != hex_chars[*(uint8_t *)str]) {
|
377
|
+
return false;
|
378
|
+
}
|
357
379
|
}
|
358
380
|
return true;
|
359
381
|
}
|
360
382
|
|
361
|
-
static const char*
|
362
|
-
|
363
|
-
uint32_t v = 0;
|
383
|
+
static const char *read_num(const char *s, int len, int *vp) {
|
384
|
+
uint32_t v = 0;
|
364
385
|
|
365
386
|
for (; 0 < len; len--, s++) {
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
387
|
+
if ('0' <= *s && *s <= '9') {
|
388
|
+
v = v * 10 + *s - '0';
|
389
|
+
} else {
|
390
|
+
return NULL;
|
391
|
+
}
|
371
392
|
}
|
372
393
|
*vp = (int)v;
|
373
394
|
|
374
395
|
return s;
|
375
396
|
}
|
376
397
|
|
377
|
-
static VALUE
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
time_t secs;
|
398
|
+
static VALUE time_parse(const char *s, int len) {
|
399
|
+
struct tm tm;
|
400
|
+
bool neg = false;
|
401
|
+
long nsecs = 0;
|
402
|
+
int i;
|
403
|
+
time_t secs;
|
384
404
|
|
385
405
|
memset(&tm, 0, sizeof(tm));
|
386
406
|
if ('-' == *s) {
|
387
|
-
|
388
|
-
|
407
|
+
s++;
|
408
|
+
neg = true;
|
389
409
|
}
|
390
410
|
if (NULL == (s = read_num(s, 4, &tm.tm_year))) {
|
391
|
-
|
411
|
+
return Qnil;
|
392
412
|
}
|
393
413
|
if (neg) {
|
394
|
-
|
395
|
-
|
414
|
+
tm.tm_year = -tm.tm_year;
|
415
|
+
neg = false;
|
396
416
|
}
|
397
417
|
tm.tm_year -= 1900;
|
398
418
|
s++;
|
399
419
|
if (NULL == (s = read_num(s, 2, &tm.tm_mon))) {
|
400
|
-
|
420
|
+
return Qnil;
|
401
421
|
}
|
402
422
|
tm.tm_mon--;
|
403
423
|
s++;
|
404
424
|
if (NULL == (s = read_num(s, 2, &tm.tm_mday))) {
|
405
|
-
|
425
|
+
return Qnil;
|
406
426
|
}
|
407
427
|
s++;
|
408
428
|
if (NULL == (s = read_num(s, 2, &tm.tm_hour))) {
|
409
|
-
|
429
|
+
return Qnil;
|
410
430
|
}
|
411
431
|
s++;
|
412
432
|
if (NULL == (s = read_num(s, 2, &tm.tm_min))) {
|
413
|
-
|
433
|
+
return Qnil;
|
414
434
|
}
|
415
435
|
s++;
|
416
436
|
if (NULL == (s = read_num(s, 2, &tm.tm_sec))) {
|
417
|
-
|
437
|
+
return Qnil;
|
418
438
|
}
|
419
439
|
s++;
|
420
440
|
|
421
441
|
for (i = 9; 0 < i; i--, s++) {
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
442
|
+
if ('0' <= *s && *s <= '9') {
|
443
|
+
nsecs = nsecs * 10 + *s - '0';
|
444
|
+
} else {
|
445
|
+
return Qnil;
|
446
|
+
}
|
427
447
|
}
|
428
448
|
#if IS_WINDOWS
|
429
449
|
secs = (time_t)mktime(&tm);
|
@@ -437,193 +457,169 @@ time_parse(const char *s, int len) {
|
|
437
457
|
return rb_funcall(rb_time_nano_new(secs, nsecs), oj_utc_id, 0);
|
438
458
|
}
|
439
459
|
|
440
|
-
static VALUE
|
441
|
-
protect_uri(VALUE rstr) {
|
460
|
+
static VALUE protect_uri(VALUE rstr) {
|
442
461
|
return rb_funcall(resolve_uri_class(), oj_parse_id, 1, rstr);
|
443
462
|
}
|
444
463
|
|
445
|
-
static VALUE
|
446
|
-
|
447
|
-
volatile VALUE v = Qnil;
|
464
|
+
static VALUE cstr_to_rstr(ParseInfo pi, const char *str, size_t len) {
|
465
|
+
volatile VALUE v = Qnil;
|
448
466
|
|
449
|
-
if (30 == len && '-' == str[4] && '-' == str[7] && 'T' == str[10] && ':' == str[13] &&
|
450
|
-
|
451
|
-
|
452
|
-
|
467
|
+
if (30 == len && '-' == str[4] && '-' == str[7] && 'T' == str[10] && ':' == str[13] &&
|
468
|
+
':' == str[16] && '.' == str[19] && 'Z' == str[29]) {
|
469
|
+
if (Qnil != (v = time_parse(str, (int)len))) {
|
470
|
+
return v;
|
471
|
+
}
|
453
472
|
}
|
454
|
-
if (36 == len && '-' == str[8] && '-' == str[13] && '-' == str[18] && '-' == str[23] &&
|
455
|
-
|
473
|
+
if (36 == len && '-' == str[8] && '-' == str[13] && '-' == str[18] && '-' == str[23] &&
|
474
|
+
uuid_check(str, (int)len) && Qnil != resolve_wab_uuid_class()) {
|
475
|
+
return rb_funcall(wab_uuid_clas, oj_new_id, 1, rb_str_new(str, len));
|
456
476
|
}
|
457
|
-
v = rb_str_new(str, len);
|
458
477
|
if (7 < len && 0 == strncasecmp("http://", str, 7)) {
|
459
|
-
|
460
|
-
|
478
|
+
int err = 0;
|
479
|
+
v = rb_str_new(str, len);
|
480
|
+
volatile VALUE uri = rb_protect(protect_uri, v, &err);
|
461
481
|
|
462
|
-
|
463
|
-
|
464
|
-
|
482
|
+
if (0 == err) {
|
483
|
+
return uri;
|
484
|
+
}
|
465
485
|
}
|
466
|
-
return
|
486
|
+
return oj_cstr_to_value(str, len, (size_t)pi->options.cache_str);
|
467
487
|
}
|
468
488
|
|
469
|
-
static void
|
470
|
-
|
471
|
-
pi->stack.head->val = cstr_to_rstr(str, len);
|
489
|
+
static void add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
490
|
+
pi->stack.head->val = cstr_to_rstr(pi, str, len);
|
472
491
|
if (Yes == pi->options.trace) {
|
473
|
-
|
492
|
+
oj_trace_parse_call("add_string", pi, __FILE__, __LINE__, pi->stack.head->val);
|
474
493
|
}
|
475
494
|
}
|
476
495
|
|
477
|
-
static void
|
478
|
-
add_num(ParseInfo pi, NumInfo ni) {
|
496
|
+
static void add_num(ParseInfo pi, NumInfo ni) {
|
479
497
|
if (ni->infinity || ni->nan) {
|
480
|
-
|
498
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
481
499
|
}
|
482
500
|
pi->stack.head->val = oj_num_as_value(ni);
|
483
501
|
if (Yes == pi->options.trace) {
|
484
|
-
|
502
|
+
oj_trace_parse_call("add_number", pi, __FILE__, __LINE__, pi->stack.head->val);
|
485
503
|
}
|
486
504
|
}
|
487
505
|
|
488
|
-
static VALUE
|
489
|
-
start_hash(ParseInfo pi) {
|
506
|
+
static VALUE start_hash(ParseInfo pi) {
|
490
507
|
if (Yes == pi->options.trace) {
|
491
|
-
|
508
|
+
oj_trace_parse_in("start_hash", pi, __FILE__, __LINE__);
|
492
509
|
}
|
493
510
|
if (Qnil != pi->options.hash_class) {
|
494
|
-
|
511
|
+
return rb_class_new_instance(0, NULL, pi->options.hash_class);
|
495
512
|
}
|
496
513
|
return rb_hash_new();
|
497
514
|
}
|
498
515
|
|
499
|
-
static
|
500
|
-
|
501
|
-
volatile VALUE rkey = parent->key_val;
|
502
|
-
|
503
|
-
if (Qundef == rkey) {
|
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);
|
516
|
+
static void hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
|
517
|
+
volatile VALUE rval = cstr_to_rstr(pi, str, len);
|
515
518
|
|
516
519
|
rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rval);
|
517
520
|
if (Yes == pi->options.trace) {
|
518
|
-
|
521
|
+
oj_trace_parse_call("set_string", pi, __FILE__, __LINE__, rval);
|
519
522
|
}
|
520
523
|
}
|
521
524
|
|
522
|
-
static void
|
523
|
-
|
524
|
-
volatile VALUE rval = Qnil;
|
525
|
+
static void hash_set_num(ParseInfo pi, Val parent, NumInfo ni) {
|
526
|
+
volatile VALUE rval = Qnil;
|
525
527
|
|
526
528
|
if (ni->infinity || ni->nan) {
|
527
|
-
|
529
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
528
530
|
}
|
529
531
|
rval = oj_num_as_value(ni);
|
530
532
|
rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), rval);
|
531
533
|
if (Yes == pi->options.trace) {
|
532
|
-
|
534
|
+
oj_trace_parse_call("set_number", pi, __FILE__, __LINE__, rval);
|
533
535
|
}
|
534
536
|
}
|
535
537
|
|
536
|
-
static void
|
537
|
-
hash_set_value(ParseInfo pi, Val parent, VALUE value) {
|
538
|
+
static void hash_set_value(ParseInfo pi, Val parent, VALUE value) {
|
538
539
|
rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), value);
|
539
540
|
if (Yes == pi->options.trace) {
|
540
|
-
|
541
|
+
oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, value);
|
541
542
|
}
|
542
543
|
}
|
543
544
|
|
544
|
-
static VALUE
|
545
|
-
start_array(ParseInfo pi) {
|
545
|
+
static VALUE start_array(ParseInfo pi) {
|
546
546
|
if (Yes == pi->options.trace) {
|
547
|
-
|
547
|
+
oj_trace_parse_in("start_array", pi, __FILE__, __LINE__);
|
548
548
|
}
|
549
549
|
return rb_ary_new();
|
550
550
|
}
|
551
551
|
|
552
|
-
static void
|
553
|
-
|
554
|
-
volatile VALUE rval = cstr_to_rstr(str, len);
|
552
|
+
static void array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
|
553
|
+
volatile VALUE rval = cstr_to_rstr(pi, str, len);
|
555
554
|
|
556
555
|
rb_ary_push(stack_peek(&pi->stack)->val, rval);
|
557
556
|
if (Yes == pi->options.trace) {
|
558
|
-
|
557
|
+
oj_trace_parse_call("set_value", pi, __FILE__, __LINE__, rval);
|
559
558
|
}
|
560
559
|
}
|
561
560
|
|
562
|
-
static void
|
563
|
-
|
564
|
-
volatile VALUE rval = Qnil;
|
561
|
+
static void array_append_num(ParseInfo pi, NumInfo ni) {
|
562
|
+
volatile VALUE rval = Qnil;
|
565
563
|
|
566
564
|
if (ni->infinity || ni->nan) {
|
567
|
-
|
565
|
+
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
|
568
566
|
}
|
569
567
|
rval = oj_num_as_value(ni);
|
570
568
|
rb_ary_push(stack_peek(&pi->stack)->val, rval);
|
571
569
|
if (Yes == pi->options.trace) {
|
572
|
-
|
570
|
+
oj_trace_parse_call("append_number", pi, __FILE__, __LINE__, rval);
|
573
571
|
}
|
574
572
|
}
|
575
573
|
|
576
|
-
static void
|
577
|
-
array_append_value(ParseInfo pi, VALUE value) {
|
574
|
+
static void array_append_value(ParseInfo pi, VALUE value) {
|
578
575
|
rb_ary_push(stack_peek(&pi->stack)->val, value);
|
579
576
|
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;
|
577
|
+
oj_trace_parse_call("append_value", pi, __FILE__, __LINE__, value);
|
578
|
+
}
|
579
|
+
}
|
580
|
+
|
581
|
+
void oj_set_wab_callbacks(ParseInfo pi) {
|
582
|
+
pi->start_hash = start_hash;
|
583
|
+
pi->end_hash = hash_end;
|
584
|
+
pi->hash_key = noop_hash_key;
|
585
|
+
pi->hash_set_cstr = hash_set_cstr;
|
586
|
+
pi->hash_set_num = hash_set_num;
|
587
|
+
pi->hash_set_value = hash_set_value;
|
588
|
+
pi->start_array = start_array;
|
589
|
+
pi->end_array = array_end;
|
590
|
+
pi->array_append_cstr = array_append_cstr;
|
591
|
+
pi->array_append_num = array_append_num;
|
596
592
|
pi->array_append_value = array_append_value;
|
597
|
-
pi->add_cstr
|
598
|
-
pi->add_num
|
599
|
-
pi->add_value
|
600
|
-
pi->expect_value
|
593
|
+
pi->add_cstr = add_cstr;
|
594
|
+
pi->add_num = add_num;
|
595
|
+
pi->add_value = add_value;
|
596
|
+
pi->expect_value = 1;
|
601
597
|
}
|
602
598
|
|
603
599
|
VALUE
|
604
600
|
oj_wab_parse(int argc, VALUE *argv, VALUE self) {
|
605
|
-
struct _parseInfo
|
601
|
+
struct _parseInfo pi;
|
606
602
|
|
607
603
|
parse_info_init(&pi);
|
608
|
-
pi.options
|
609
|
-
pi.handler
|
604
|
+
pi.options = oj_default_options;
|
605
|
+
pi.handler = Qnil;
|
610
606
|
pi.err_class = Qnil;
|
611
607
|
oj_set_wab_callbacks(&pi);
|
612
608
|
|
613
609
|
if (T_STRING == rb_type(*argv)) {
|
614
|
-
|
610
|
+
return oj_pi_parse(argc, argv, &pi, 0, 0, true);
|
615
611
|
} else {
|
616
|
-
|
612
|
+
return oj_pi_sparse(argc, argv, &pi, 0);
|
617
613
|
}
|
618
614
|
}
|
619
615
|
|
620
616
|
VALUE
|
621
617
|
oj_wab_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
|
622
|
-
struct _parseInfo
|
618
|
+
struct _parseInfo pi;
|
623
619
|
|
624
620
|
parse_info_init(&pi);
|
625
|
-
pi.options
|
626
|
-
pi.handler
|
621
|
+
pi.options = oj_default_options;
|
622
|
+
pi.handler = Qnil;
|
627
623
|
pi.err_class = Qnil;
|
628
624
|
oj_set_wab_callbacks(&pi);
|
629
625
|
|