oj 3.7.12
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|