oj 3.7.12
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +96 -0
- data/ext/oj/buf.h +103 -0
- data/ext/oj/cache8.c +107 -0
- data/ext/oj/cache8.h +48 -0
- data/ext/oj/circarray.c +68 -0
- data/ext/oj/circarray.h +23 -0
- data/ext/oj/code.c +235 -0
- data/ext/oj/code.h +42 -0
- data/ext/oj/compat.c +299 -0
- data/ext/oj/custom.c +1188 -0
- data/ext/oj/dump.c +1232 -0
- data/ext/oj/dump.h +94 -0
- data/ext/oj/dump_compat.c +973 -0
- data/ext/oj/dump_leaf.c +252 -0
- data/ext/oj/dump_object.c +837 -0
- data/ext/oj/dump_strict.c +433 -0
- data/ext/oj/encode.h +45 -0
- data/ext/oj/err.c +57 -0
- data/ext/oj/err.h +70 -0
- data/ext/oj/extconf.rb +47 -0
- data/ext/oj/fast.c +1771 -0
- data/ext/oj/hash.c +163 -0
- data/ext/oj/hash.h +46 -0
- data/ext/oj/hash_test.c +512 -0
- data/ext/oj/mimic_json.c +873 -0
- data/ext/oj/object.c +771 -0
- data/ext/oj/odd.c +231 -0
- data/ext/oj/odd.h +44 -0
- data/ext/oj/oj.c +1694 -0
- data/ext/oj/oj.h +381 -0
- data/ext/oj/parse.c +1085 -0
- data/ext/oj/parse.h +111 -0
- data/ext/oj/rails.c +1485 -0
- data/ext/oj/rails.h +21 -0
- data/ext/oj/reader.c +231 -0
- data/ext/oj/reader.h +151 -0
- data/ext/oj/resolve.c +102 -0
- data/ext/oj/resolve.h +14 -0
- data/ext/oj/rxclass.c +147 -0
- data/ext/oj/rxclass.h +27 -0
- data/ext/oj/saj.c +714 -0
- data/ext/oj/scp.c +224 -0
- data/ext/oj/sparse.c +910 -0
- data/ext/oj/stream_writer.c +363 -0
- data/ext/oj/strict.c +212 -0
- data/ext/oj/string_writer.c +512 -0
- data/ext/oj/trace.c +79 -0
- data/ext/oj/trace.h +28 -0
- data/ext/oj/util.c +136 -0
- data/ext/oj/util.h +19 -0
- data/ext/oj/val_stack.c +118 -0
- data/ext/oj/val_stack.h +185 -0
- data/ext/oj/wab.c +631 -0
- data/lib/oj.rb +21 -0
- data/lib/oj/active_support_helper.rb +41 -0
- data/lib/oj/bag.rb +88 -0
- data/lib/oj/easy_hash.rb +52 -0
- data/lib/oj/error.rb +22 -0
- data/lib/oj/json.rb +176 -0
- data/lib/oj/mimic.rb +267 -0
- data/lib/oj/saj.rb +66 -0
- data/lib/oj/schandler.rb +142 -0
- data/lib/oj/state.rb +131 -0
- data/lib/oj/version.rb +5 -0
- data/pages/Advanced.md +22 -0
- data/pages/Compatibility.md +25 -0
- data/pages/Custom.md +23 -0
- data/pages/Encoding.md +65 -0
- data/pages/JsonGem.md +79 -0
- data/pages/Modes.md +154 -0
- data/pages/Options.md +266 -0
- data/pages/Rails.md +116 -0
- data/pages/Security.md +20 -0
- data/pages/WAB.md +13 -0
- data/test/_test_active.rb +76 -0
- data/test/_test_active_mimic.rb +96 -0
- data/test/_test_mimic_rails.rb +126 -0
- data/test/activerecord/result_test.rb +27 -0
- data/test/activesupport4/decoding_test.rb +108 -0
- data/test/activesupport4/encoding_test.rb +531 -0
- data/test/activesupport4/test_helper.rb +41 -0
- data/test/activesupport5/decoding_test.rb +125 -0
- data/test/activesupport5/encoding_test.rb +485 -0
- data/test/activesupport5/encoding_test_cases.rb +90 -0
- data/test/activesupport5/test_helper.rb +50 -0
- data/test/activesupport5/time_zone_test_helpers.rb +24 -0
- data/test/big.rb +15 -0
- data/test/files.rb +29 -0
- data/test/foo.rb +33 -0
- data/test/helper.rb +26 -0
- data/test/isolated/shared.rb +308 -0
- data/test/isolated/test_mimic_after.rb +13 -0
- data/test/isolated/test_mimic_alone.rb +12 -0
- data/test/isolated/test_mimic_as_json.rb +45 -0
- data/test/isolated/test_mimic_before.rb +13 -0
- data/test/isolated/test_mimic_define.rb +28 -0
- data/test/isolated/test_mimic_rails_after.rb +22 -0
- data/test/isolated/test_mimic_rails_before.rb +21 -0
- data/test/isolated/test_mimic_redefine.rb +15 -0
- data/test/json_gem/json_addition_test.rb +216 -0
- data/test/json_gem/json_common_interface_test.rb +148 -0
- data/test/json_gem/json_encoding_test.rb +107 -0
- data/test/json_gem/json_ext_parser_test.rb +20 -0
- data/test/json_gem/json_fixtures_test.rb +35 -0
- data/test/json_gem/json_generator_test.rb +383 -0
- data/test/json_gem/json_generic_object_test.rb +90 -0
- data/test/json_gem/json_parser_test.rb +470 -0
- data/test/json_gem/json_string_matching_test.rb +42 -0
- data/test/json_gem/test_helper.rb +18 -0
- data/test/mem.rb +35 -0
- data/test/perf.rb +107 -0
- data/test/perf_compat.rb +130 -0
- data/test/perf_fast.rb +164 -0
- data/test/perf_file.rb +64 -0
- data/test/perf_object.rb +138 -0
- data/test/perf_saj.rb +109 -0
- data/test/perf_scp.rb +151 -0
- data/test/perf_simple.rb +287 -0
- data/test/perf_strict.rb +145 -0
- data/test/perf_wab.rb +131 -0
- data/test/sample.rb +54 -0
- data/test/sample/change.rb +14 -0
- data/test/sample/dir.rb +19 -0
- data/test/sample/doc.rb +36 -0
- data/test/sample/file.rb +48 -0
- data/test/sample/group.rb +16 -0
- data/test/sample/hasprops.rb +16 -0
- data/test/sample/layer.rb +12 -0
- data/test/sample/line.rb +20 -0
- data/test/sample/oval.rb +10 -0
- data/test/sample/rect.rb +10 -0
- data/test/sample/shape.rb +35 -0
- data/test/sample/text.rb +20 -0
- data/test/sample_json.rb +37 -0
- data/test/test_compat.rb +509 -0
- data/test/test_custom.rb +406 -0
- data/test/test_debian.rb +53 -0
- data/test/test_fast.rb +470 -0
- data/test/test_file.rb +239 -0
- data/test/test_gc.rb +49 -0
- data/test/test_hash.rb +29 -0
- data/test/test_integer_range.rb +73 -0
- data/test/test_null.rb +376 -0
- data/test/test_object.rb +1018 -0
- data/test/test_saj.rb +186 -0
- data/test/test_scp.rb +433 -0
- data/test/test_strict.rb +410 -0
- data/test/test_various.rb +739 -0
- data/test/test_wab.rb +307 -0
- data/test/test_writer.rb +380 -0
- data/test/tests.rb +24 -0
- data/test/tests_mimic.rb +14 -0
- data/test/tests_mimic_addition.rb +7 -0
- metadata +359 -0
data/ext/oj/rails.h
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/* rails.h
|
|
2
|
+
* Copyright (c) 2017, Peter Ohler
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#ifndef OJ_RAILS_H
|
|
7
|
+
#define OJ_RAILS_H
|
|
8
|
+
|
|
9
|
+
#include "dump.h"
|
|
10
|
+
|
|
11
|
+
extern void oj_mimic_rails_init();
|
|
12
|
+
extern ROpt oj_rails_get_opt(ROptTable rot, VALUE clas);
|
|
13
|
+
|
|
14
|
+
extern bool oj_rails_hash_opt;
|
|
15
|
+
extern bool oj_rails_array_opt;
|
|
16
|
+
extern bool oj_rails_float_opt;
|
|
17
|
+
|
|
18
|
+
extern VALUE oj_optimize_rails(VALUE self);
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
#endif /* OJ_RAILS_H */
|
data/ext/oj/reader.c
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/* reader.c
|
|
2
|
+
* Copyright (c) 2011, Peter Ohler
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#include <stdlib.h>
|
|
7
|
+
#include <errno.h>
|
|
8
|
+
#include <stdio.h>
|
|
9
|
+
#include <strings.h>
|
|
10
|
+
#include <sys/types.h>
|
|
11
|
+
#if NEEDS_UIO
|
|
12
|
+
#include <sys/uio.h>
|
|
13
|
+
#endif
|
|
14
|
+
#include <unistd.h>
|
|
15
|
+
#include <time.h>
|
|
16
|
+
|
|
17
|
+
#include "ruby.h"
|
|
18
|
+
#include "oj.h"
|
|
19
|
+
#include "reader.h"
|
|
20
|
+
|
|
21
|
+
#define BUF_PAD 4
|
|
22
|
+
|
|
23
|
+
static VALUE rescue_cb(VALUE rdr, VALUE err);
|
|
24
|
+
static VALUE io_cb(VALUE rdr);
|
|
25
|
+
static VALUE partial_io_cb(VALUE rdr);
|
|
26
|
+
static int read_from_io(Reader reader);
|
|
27
|
+
static int read_from_fd(Reader reader);
|
|
28
|
+
static int read_from_io_partial(Reader reader);
|
|
29
|
+
//static int read_from_str(Reader reader);
|
|
30
|
+
|
|
31
|
+
void
|
|
32
|
+
oj_reader_init(Reader reader, VALUE io, int fd, bool to_s) {
|
|
33
|
+
VALUE io_class = rb_obj_class(io);
|
|
34
|
+
VALUE stat;
|
|
35
|
+
VALUE ftype;
|
|
36
|
+
|
|
37
|
+
reader->head = reader->base;
|
|
38
|
+
*((char*)reader->head) = '\0';
|
|
39
|
+
reader->end = reader->head + sizeof(reader->base) - BUF_PAD;
|
|
40
|
+
reader->tail = reader->head;
|
|
41
|
+
reader->read_end = reader->head;
|
|
42
|
+
reader->pro = 0;
|
|
43
|
+
reader->str = 0;
|
|
44
|
+
reader->pos = 0;
|
|
45
|
+
reader->line = 1;
|
|
46
|
+
reader->col = 0;
|
|
47
|
+
reader->free_head = 0;
|
|
48
|
+
|
|
49
|
+
if (0 != fd) {
|
|
50
|
+
reader->read_func = read_from_fd;
|
|
51
|
+
reader->fd = fd;
|
|
52
|
+
} else if (rb_cString == io_class) {
|
|
53
|
+
reader->read_func = 0;
|
|
54
|
+
reader->in_str = StringValuePtr(io);
|
|
55
|
+
reader->head = (char*)reader->in_str;
|
|
56
|
+
reader->tail = reader->head;
|
|
57
|
+
reader->read_end = reader->head + RSTRING_LEN(io);
|
|
58
|
+
} else if (oj_stringio_class == io_class) {
|
|
59
|
+
VALUE s = rb_funcall2(io, oj_string_id, 0, 0);
|
|
60
|
+
|
|
61
|
+
reader->read_func = 0;
|
|
62
|
+
reader->in_str = StringValuePtr(s);
|
|
63
|
+
reader->head = (char*)reader->in_str;
|
|
64
|
+
reader->tail = reader->head;
|
|
65
|
+
reader->read_end = reader->head + RSTRING_LEN(s);
|
|
66
|
+
} else if (rb_cFile == io_class &&
|
|
67
|
+
Qnil != (stat = rb_funcall(io, oj_stat_id, 0)) &&
|
|
68
|
+
Qnil != (ftype = rb_funcall(stat, oj_ftype_id, 0)) &&
|
|
69
|
+
0 == strcmp("file", StringValuePtr(ftype)) &&
|
|
70
|
+
0 == FIX2INT(rb_funcall(io, oj_pos_id, 0))) {
|
|
71
|
+
reader->read_func = read_from_fd;
|
|
72
|
+
reader->fd = FIX2INT(rb_funcall(io, oj_fileno_id, 0));
|
|
73
|
+
} else if (rb_respond_to(io, oj_readpartial_id)) {
|
|
74
|
+
reader->read_func = read_from_io_partial;
|
|
75
|
+
reader->io = io;
|
|
76
|
+
} else if (rb_respond_to(io, oj_read_id)) {
|
|
77
|
+
reader->read_func = read_from_io;
|
|
78
|
+
reader->io = io;
|
|
79
|
+
} else if (to_s) {
|
|
80
|
+
volatile VALUE rstr = rb_funcall(io, oj_to_s_id, 0);
|
|
81
|
+
|
|
82
|
+
reader->read_func = 0;
|
|
83
|
+
reader->in_str = StringValuePtr(rstr);
|
|
84
|
+
reader->head = (char*)reader->in_str;
|
|
85
|
+
reader->tail = reader->head;
|
|
86
|
+
reader->read_end = reader->head + RSTRING_LEN(rstr);
|
|
87
|
+
} else {
|
|
88
|
+
rb_raise(rb_eArgError, "parser io argument must be a String or respond to readpartial() or read().\n");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
int
|
|
93
|
+
oj_reader_read(Reader reader) {
|
|
94
|
+
int err;
|
|
95
|
+
size_t shift = 0;
|
|
96
|
+
|
|
97
|
+
if (0 == reader->read_func) {
|
|
98
|
+
return -1;
|
|
99
|
+
}
|
|
100
|
+
// if there is not much room to read into, shift or realloc a larger buffer.
|
|
101
|
+
if (reader->head < reader->tail && 4096 > reader->end - reader->tail) {
|
|
102
|
+
if (0 == reader->pro) {
|
|
103
|
+
shift = reader->tail - reader->head;
|
|
104
|
+
} else {
|
|
105
|
+
shift = reader->pro - reader->head - 1; // leave one character so we can backup one
|
|
106
|
+
}
|
|
107
|
+
if (0 >= shift) { /* no space left so allocate more */
|
|
108
|
+
const char *old = reader->head;
|
|
109
|
+
size_t size = reader->end - reader->head + BUF_PAD;
|
|
110
|
+
|
|
111
|
+
if (reader->head == reader->base) {
|
|
112
|
+
reader->head = ALLOC_N(char, size * 2);
|
|
113
|
+
memcpy((char*)reader->head, old, size);
|
|
114
|
+
} else {
|
|
115
|
+
REALLOC_N(reader->head, char, size * 2);
|
|
116
|
+
}
|
|
117
|
+
reader->free_head = 1;
|
|
118
|
+
reader->end = reader->head + size * 2 - BUF_PAD;
|
|
119
|
+
reader->tail = reader->head + (reader->tail - old);
|
|
120
|
+
reader->read_end = reader->head + (reader->read_end - old);
|
|
121
|
+
if (0 != reader->pro) {
|
|
122
|
+
reader->pro = reader->head + (reader->pro - old);
|
|
123
|
+
}
|
|
124
|
+
if (0 != reader->str) {
|
|
125
|
+
reader->str = reader->head + (reader->str - old);
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
memmove((char*)reader->head, reader->head + shift, reader->read_end - (reader->head + shift));
|
|
129
|
+
reader->tail -= shift;
|
|
130
|
+
reader->read_end -= shift;
|
|
131
|
+
if (0 != reader->pro) {
|
|
132
|
+
reader->pro -= shift;
|
|
133
|
+
}
|
|
134
|
+
if (0 != reader->str) {
|
|
135
|
+
reader->str -= shift;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
err = reader->read_func(reader);
|
|
140
|
+
*(char*)reader->read_end = '\0';
|
|
141
|
+
|
|
142
|
+
return err;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
static VALUE
|
|
146
|
+
rescue_cb(VALUE rbuf, VALUE err) {
|
|
147
|
+
VALUE clas = rb_obj_class(err);
|
|
148
|
+
|
|
149
|
+
if (rb_eTypeError != clas && rb_eEOFError != clas) {
|
|
150
|
+
Reader reader = (Reader)rbuf;
|
|
151
|
+
|
|
152
|
+
rb_raise(clas, "at line %d, column %d\n", reader->line, reader->col);
|
|
153
|
+
}
|
|
154
|
+
return Qfalse;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
static VALUE
|
|
158
|
+
partial_io_cb(VALUE rbuf) {
|
|
159
|
+
Reader reader = (Reader)rbuf;
|
|
160
|
+
VALUE args[1];
|
|
161
|
+
VALUE rstr;
|
|
162
|
+
char *str;
|
|
163
|
+
size_t cnt;
|
|
164
|
+
|
|
165
|
+
args[0] = ULONG2NUM(reader->end - reader->tail);
|
|
166
|
+
rstr = rb_funcall2(reader->io, oj_readpartial_id, 1, args);
|
|
167
|
+
if (Qnil == rstr) {
|
|
168
|
+
return Qfalse;
|
|
169
|
+
}
|
|
170
|
+
str = StringValuePtr(rstr);
|
|
171
|
+
cnt = RSTRING_LEN(rstr);
|
|
172
|
+
//printf("*** partial read %lu bytes, str: '%s'\n", cnt, str);
|
|
173
|
+
strcpy(reader->tail, str);
|
|
174
|
+
reader->read_end = reader->tail + cnt;
|
|
175
|
+
|
|
176
|
+
return Qtrue;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
static VALUE
|
|
180
|
+
io_cb(VALUE rbuf) {
|
|
181
|
+
Reader reader = (Reader)rbuf;
|
|
182
|
+
VALUE args[1];
|
|
183
|
+
VALUE rstr;
|
|
184
|
+
char *str;
|
|
185
|
+
size_t cnt;
|
|
186
|
+
|
|
187
|
+
args[0] = ULONG2NUM(reader->end - reader->tail);
|
|
188
|
+
rstr = rb_funcall2(reader->io, oj_read_id, 1, args);
|
|
189
|
+
if (Qnil == rstr) {
|
|
190
|
+
return Qfalse;
|
|
191
|
+
}
|
|
192
|
+
str = StringValuePtr(rstr);
|
|
193
|
+
cnt = RSTRING_LEN(rstr);
|
|
194
|
+
//printf("*** read %lu bytes, str: '%s'\n", cnt, str);
|
|
195
|
+
strcpy(reader->tail, str);
|
|
196
|
+
reader->read_end = reader->tail + cnt;
|
|
197
|
+
|
|
198
|
+
return Qtrue;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
static int
|
|
202
|
+
read_from_io_partial(Reader reader) {
|
|
203
|
+
return (Qfalse == rb_rescue(partial_io_cb, (VALUE)reader, rescue_cb, (VALUE)reader));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
static int
|
|
207
|
+
read_from_io(Reader reader) {
|
|
208
|
+
return (Qfalse == rb_rescue(io_cb, (VALUE)reader, rescue_cb, (VALUE)reader));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
static int
|
|
212
|
+
read_from_fd(Reader reader) {
|
|
213
|
+
ssize_t cnt;
|
|
214
|
+
size_t max = reader->end - reader->tail;
|
|
215
|
+
|
|
216
|
+
cnt = read(reader->fd, reader->tail, max);
|
|
217
|
+
if (cnt <= 0) {
|
|
218
|
+
return -1;
|
|
219
|
+
} else if (0 != cnt) {
|
|
220
|
+
reader->read_end = reader->tail + cnt;
|
|
221
|
+
}
|
|
222
|
+
return 0;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// This is only called when the end of the string is reached so just return -1.
|
|
226
|
+
/*
|
|
227
|
+
static int
|
|
228
|
+
read_from_str(Reader reader) {
|
|
229
|
+
return -1;
|
|
230
|
+
}
|
|
231
|
+
*/
|
data/ext/oj/reader.h
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/* reader.h
|
|
2
|
+
* Copyright (c) 2011, Peter Ohler
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#ifndef OJ_READER_H
|
|
7
|
+
#define OJ_READER_H
|
|
8
|
+
|
|
9
|
+
typedef struct _reader {
|
|
10
|
+
char base[0x00001000];
|
|
11
|
+
char *head;
|
|
12
|
+
char *end;
|
|
13
|
+
char *tail;
|
|
14
|
+
char *read_end; /* one past last character read */
|
|
15
|
+
char *pro; /* protection start, buffer can not slide past this point */
|
|
16
|
+
char *str; /* start of current string being read */
|
|
17
|
+
long pos;
|
|
18
|
+
int line;
|
|
19
|
+
int col;
|
|
20
|
+
int free_head;
|
|
21
|
+
int (*read_func)(struct _reader *reader);
|
|
22
|
+
union {
|
|
23
|
+
int fd;
|
|
24
|
+
VALUE io;
|
|
25
|
+
const char *in_str;
|
|
26
|
+
};
|
|
27
|
+
} *Reader;
|
|
28
|
+
|
|
29
|
+
extern void oj_reader_init(Reader reader, VALUE io, int fd, bool to_s);
|
|
30
|
+
extern int oj_reader_read(Reader reader);
|
|
31
|
+
|
|
32
|
+
static inline char
|
|
33
|
+
reader_get(Reader reader) {
|
|
34
|
+
//printf("*** drive get from '%s' from start: %ld buf: %p from read_end: %ld\n", reader->tail, reader->tail - reader->head, reader->head, reader->read_end - reader->tail);
|
|
35
|
+
if (reader->read_end <= reader->tail) {
|
|
36
|
+
if (0 != oj_reader_read(reader)) {
|
|
37
|
+
return '\0';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if ('\n' == *reader->tail) {
|
|
41
|
+
reader->line++;
|
|
42
|
+
reader->col = 0;
|
|
43
|
+
}
|
|
44
|
+
reader->col++;
|
|
45
|
+
reader->pos++;
|
|
46
|
+
|
|
47
|
+
return *reader->tail++;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static inline void
|
|
51
|
+
reader_backup(Reader reader) {
|
|
52
|
+
reader->tail--;
|
|
53
|
+
reader->col--;
|
|
54
|
+
reader->pos--;
|
|
55
|
+
if (0 >= reader->col) {
|
|
56
|
+
reader->line--;
|
|
57
|
+
// allow col to be negative since we never backup twice in a row
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static inline void
|
|
62
|
+
reader_protect(Reader reader) {
|
|
63
|
+
reader->pro = reader->tail;
|
|
64
|
+
reader->str = reader->tail; // can't have str before pro
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static inline void
|
|
68
|
+
reader_release(Reader reader) {
|
|
69
|
+
reader->pro = 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* Starts by reading a character so it is safe to use with an empty or
|
|
73
|
+
* compacted buffer.
|
|
74
|
+
*/
|
|
75
|
+
static inline char
|
|
76
|
+
reader_next_non_white(Reader reader) {
|
|
77
|
+
char c;
|
|
78
|
+
|
|
79
|
+
while ('\0' != (c = reader_get(reader))) {
|
|
80
|
+
switch(c) {
|
|
81
|
+
case ' ':
|
|
82
|
+
case '\t':
|
|
83
|
+
case '\f':
|
|
84
|
+
case '\n':
|
|
85
|
+
case '\r':
|
|
86
|
+
break;
|
|
87
|
+
default:
|
|
88
|
+
return c;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return '\0';
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* Starts by reading a character so it is safe to use with an empty or
|
|
95
|
+
* compacted buffer.
|
|
96
|
+
*/
|
|
97
|
+
static inline char
|
|
98
|
+
reader_next_white(Reader reader) {
|
|
99
|
+
char c;
|
|
100
|
+
|
|
101
|
+
while ('\0' != (c = reader_get(reader))) {
|
|
102
|
+
switch(c) {
|
|
103
|
+
case ' ':
|
|
104
|
+
case '\t':
|
|
105
|
+
case '\f':
|
|
106
|
+
case '\n':
|
|
107
|
+
case '\r':
|
|
108
|
+
case '\0':
|
|
109
|
+
return c;
|
|
110
|
+
default:
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return '\0';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
static inline int
|
|
118
|
+
reader_expect(Reader reader, const char *s) {
|
|
119
|
+
for (; '\0' != *s; s++) {
|
|
120
|
+
if (reader_get(reader) != *s) {
|
|
121
|
+
return -1;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return 0;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
static inline void
|
|
128
|
+
reader_cleanup(Reader reader) {
|
|
129
|
+
if (reader->free_head && 0 != reader->head) {
|
|
130
|
+
xfree((char*)reader->head);
|
|
131
|
+
reader->head = 0;
|
|
132
|
+
reader->free_head = 0;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
static inline int
|
|
137
|
+
is_white(char c) {
|
|
138
|
+
switch(c) {
|
|
139
|
+
case ' ':
|
|
140
|
+
case '\t':
|
|
141
|
+
case '\f':
|
|
142
|
+
case '\n':
|
|
143
|
+
case '\r':
|
|
144
|
+
return 1;
|
|
145
|
+
default:
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
return 0;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
#endif /* OJ_READER_H */
|
data/ext/oj/resolve.c
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/* resolve.c
|
|
2
|
+
* Copyright (c) 2012, Peter Ohler
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#include <stdlib.h>
|
|
7
|
+
#include <stdio.h>
|
|
8
|
+
#include <string.h>
|
|
9
|
+
#if HAVE_LIBPTHREAD
|
|
10
|
+
#include <pthread.h>
|
|
11
|
+
#endif
|
|
12
|
+
|
|
13
|
+
#include "oj.h"
|
|
14
|
+
#include "err.h"
|
|
15
|
+
#include "parse.h"
|
|
16
|
+
#include "hash.h"
|
|
17
|
+
|
|
18
|
+
inline static VALUE
|
|
19
|
+
resolve_classname(VALUE mod, const char *classname, int auto_define) {
|
|
20
|
+
VALUE clas;
|
|
21
|
+
ID ci = rb_intern(classname);
|
|
22
|
+
|
|
23
|
+
if (rb_const_defined_at(mod, ci)) {
|
|
24
|
+
clas = rb_const_get_at(mod, ci);
|
|
25
|
+
} else if (auto_define) {
|
|
26
|
+
clas = rb_define_class_under(mod, classname, oj_bag_class);
|
|
27
|
+
} else {
|
|
28
|
+
clas = Qundef;
|
|
29
|
+
}
|
|
30
|
+
return clas;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static VALUE
|
|
34
|
+
resolve_classpath(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE error_class) {
|
|
35
|
+
char class_name[1024];
|
|
36
|
+
VALUE clas;
|
|
37
|
+
char *end = class_name + sizeof(class_name) - 1;
|
|
38
|
+
char *s;
|
|
39
|
+
const char *n = name;
|
|
40
|
+
|
|
41
|
+
clas = rb_cObject;
|
|
42
|
+
for (s = class_name; 0 < len; n++, len--) {
|
|
43
|
+
if (':' == *n) {
|
|
44
|
+
*s = '\0';
|
|
45
|
+
n++;
|
|
46
|
+
len--;
|
|
47
|
+
if (':' != *n) {
|
|
48
|
+
return Qundef;
|
|
49
|
+
}
|
|
50
|
+
if (Qundef == (clas = resolve_classname(clas, class_name, auto_define))) {
|
|
51
|
+
return Qundef;
|
|
52
|
+
}
|
|
53
|
+
s = class_name;
|
|
54
|
+
} else if (end <= s) {
|
|
55
|
+
return Qundef;
|
|
56
|
+
} else {
|
|
57
|
+
*s++ = *n;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
*s = '\0';
|
|
61
|
+
if (Qundef == (clas = resolve_classname(clas, class_name, auto_define))) {
|
|
62
|
+
oj_set_error_at(pi, error_class, __FILE__, __LINE__, "class %s is not defined", name);
|
|
63
|
+
if (Qnil != error_class) {
|
|
64
|
+
pi->err_class = error_class;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return clas;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
VALUE
|
|
71
|
+
oj_name2class(ParseInfo pi, const char *name, size_t len, int auto_define, VALUE error_class) {
|
|
72
|
+
VALUE clas;
|
|
73
|
+
VALUE *slot;
|
|
74
|
+
|
|
75
|
+
if (No == pi->options.class_cache) {
|
|
76
|
+
return resolve_classpath(pi, name, len, auto_define, error_class);
|
|
77
|
+
}
|
|
78
|
+
#if HAVE_LIBPTHREAD
|
|
79
|
+
pthread_mutex_lock(&oj_cache_mutex);
|
|
80
|
+
#else
|
|
81
|
+
rb_mutex_lock(oj_cache_mutex);
|
|
82
|
+
#endif
|
|
83
|
+
if (Qnil == (clas = oj_class_hash_get(name, len, &slot))) {
|
|
84
|
+
if (Qundef != (clas = resolve_classpath(pi, name, len, auto_define, error_class))) {
|
|
85
|
+
*slot = clas;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
#if HAVE_LIBPTHREAD
|
|
89
|
+
pthread_mutex_unlock(&oj_cache_mutex);
|
|
90
|
+
#else
|
|
91
|
+
rb_mutex_unlock(oj_cache_mutex);
|
|
92
|
+
#endif
|
|
93
|
+
return clas;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
VALUE
|
|
97
|
+
oj_name2struct(ParseInfo pi, VALUE nameVal, VALUE error_class) {
|
|
98
|
+
size_t len = RSTRING_LEN(nameVal);
|
|
99
|
+
const char *str = StringValuePtr(nameVal);
|
|
100
|
+
|
|
101
|
+
return resolve_classpath(pi, str, len, 0, error_class);
|
|
102
|
+
}
|