json_pure 1.4.0 → 1.4.6
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.
- data/CHANGES +32 -0
- data/README +5 -7
- data/Rakefile +21 -17
- data/VERSION +1 -1
- data/benchmarks/parser2_benchmark.rb +5 -5
- data/ext/json/ext/{extconf_generator.rb → generator/extconf.rb} +7 -3
- data/ext/json/ext/{generator.c → generator/generator.c} +306 -223
- data/ext/json/ext/{generator.h → generator/generator.h} +31 -4
- data/ext/json/ext/{extconf_parser.rb → parser/extconf.rb} +1 -1
- data/ext/json/ext/{parser.c → parser/parser.c} +2 -1
- data/ext/json/ext/{parser.rl → parser/parser.rl} +2 -1
- data/lib/json/common.rb +11 -17
- data/lib/json/pure/generator.rb +63 -76
- data/lib/json/pure/parser.rb +29 -27
- data/lib/json/version.rb +1 -1
- data/tests/test_json.rb +70 -3
- data/tests/test_json_addition.rb +6 -6
- data/tests/test_json_generate.rb +59 -0
- metadata +9 -9
- /data/ext/json/ext/{parser.h → parser/parser.h} +0 -0
|
@@ -70,9 +70,10 @@ static void fbuffer_free(FBuffer *fb);
|
|
|
70
70
|
static void fbuffer_free_only_buffer(FBuffer *fb);
|
|
71
71
|
static void fbuffer_clear(FBuffer *fb);
|
|
72
72
|
static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned int len);
|
|
73
|
-
static void
|
|
73
|
+
static void fbuffer_append_long(FBuffer *fb, long number);
|
|
74
74
|
static void fbuffer_append_char(FBuffer *fb, char newchr);
|
|
75
75
|
static FBuffer *fbuffer_dup(FBuffer *fb);
|
|
76
|
+
static VALUE fbuffer_to_s(FBuffer *fb);
|
|
76
77
|
|
|
77
78
|
/* unicode defintions */
|
|
78
79
|
|
|
@@ -123,15 +124,29 @@ typedef struct JSON_Generator_StateStruct {
|
|
|
123
124
|
long max_nesting;
|
|
124
125
|
char allow_nan;
|
|
125
126
|
char ascii_only;
|
|
127
|
+
long depth;
|
|
126
128
|
} JSON_Generator_State;
|
|
127
129
|
|
|
128
130
|
#define GET_STATE(self) \
|
|
129
131
|
JSON_Generator_State *state; \
|
|
130
132
|
Data_Get_Struct(self, JSON_Generator_State, state)
|
|
131
133
|
|
|
134
|
+
#define GENERATE_JSON(type) \
|
|
135
|
+
FBuffer *buffer; \
|
|
136
|
+
VALUE Vstate; \
|
|
137
|
+
JSON_Generator_State *state; \
|
|
138
|
+
\
|
|
139
|
+
rb_scan_args(argc, argv, "01", &Vstate); \
|
|
140
|
+
Vstate = cState_from_state_s(cState, Vstate); \
|
|
141
|
+
Data_Get_Struct(Vstate, JSON_Generator_State, state); \
|
|
142
|
+
buffer = cState_prepare_buffer(Vstate); \
|
|
143
|
+
generate_json_##type(buffer, Vstate, state, self); \
|
|
144
|
+
return fbuffer_to_s(buffer)
|
|
145
|
+
|
|
132
146
|
static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self);
|
|
133
147
|
static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self);
|
|
134
|
-
static VALUE
|
|
148
|
+
static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self);
|
|
149
|
+
static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self);
|
|
135
150
|
static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self);
|
|
136
151
|
static VALUE mString_included_s(VALUE self, VALUE modul);
|
|
137
152
|
static VALUE mString_to_json(int argc, VALUE *argv, VALUE self);
|
|
@@ -147,8 +162,17 @@ static JSON_Generator_State *State_allocate();
|
|
|
147
162
|
static VALUE cState_s_allocate(VALUE klass);
|
|
148
163
|
static VALUE cState_configure(VALUE self, VALUE opts);
|
|
149
164
|
static VALUE cState_to_h(VALUE self);
|
|
150
|
-
static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj
|
|
151
|
-
static
|
|
165
|
+
static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
|
166
|
+
static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
|
167
|
+
static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
|
168
|
+
static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
|
169
|
+
static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
|
170
|
+
static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
|
171
|
+
static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
|
172
|
+
static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
|
173
|
+
static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
|
174
|
+
static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
|
175
|
+
static VALUE cState_partial_generate(VALUE self, VALUE obj);
|
|
152
176
|
static VALUE cState_generate(VALUE self, VALUE obj);
|
|
153
177
|
static VALUE cState_initialize(int argc, VALUE *argv, VALUE self);
|
|
154
178
|
static VALUE cState_from_state_s(VALUE self, VALUE opts);
|
|
@@ -166,5 +190,8 @@ static VALUE cState_max_nesting(VALUE self);
|
|
|
166
190
|
static VALUE cState_max_nesting_set(VALUE self, VALUE depth);
|
|
167
191
|
static VALUE cState_allow_nan_p(VALUE self);
|
|
168
192
|
static VALUE cState_ascii_only_p(VALUE self);
|
|
193
|
+
static VALUE cState_depth(VALUE self);
|
|
194
|
+
static VALUE cState_depth_set(VALUE self, VALUE depth);
|
|
195
|
+
static FBuffer *cState_prepare_buffer(VALUE self);
|
|
169
196
|
|
|
170
197
|
#endif
|
|
@@ -147,8 +147,9 @@ case 2:
|
|
|
147
147
|
tr2:
|
|
148
148
|
#line 127 "parser.rl"
|
|
149
149
|
{
|
|
150
|
+
char *np;
|
|
150
151
|
json->parsing_name = 1;
|
|
151
|
-
|
|
152
|
+
np = JSON_parse_string(json, p, pe, &last_name);
|
|
152
153
|
json->parsing_name = 0;
|
|
153
154
|
if (np == NULL) { p--; {p++; cs = 3; goto _out;} } else {p = (( np))-1;}
|
|
154
155
|
}
|
|
@@ -125,8 +125,9 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
|
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
action parse_name {
|
|
128
|
+
char *np;
|
|
128
129
|
json->parsing_name = 1;
|
|
129
|
-
|
|
130
|
+
np = JSON_parse_string(json, fpc, pe, &last_name);
|
|
130
131
|
json->parsing_name = 0;
|
|
131
132
|
if (np == NULL) { fhold; fbreak; } else fexec np;
|
|
132
133
|
}
|
data/lib/json/common.rb
CHANGED
|
@@ -11,9 +11,9 @@ module JSON
|
|
|
11
11
|
# generate and parse for their documentation.
|
|
12
12
|
def [](object, opts = {})
|
|
13
13
|
if object.respond_to? :to_str
|
|
14
|
-
JSON.parse(object.to_str, opts
|
|
14
|
+
JSON.parse(object.to_str, opts)
|
|
15
15
|
else
|
|
16
|
-
JSON.generate(object, opts
|
|
16
|
+
JSON.generate(object, opts)
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
@@ -63,20 +63,20 @@ module JSON
|
|
|
63
63
|
end
|
|
64
64
|
self.state = generator::State
|
|
65
65
|
const_set :State, self.state
|
|
66
|
-
const_set :SAFE_STATE_PROTOTYPE, State.new
|
|
66
|
+
const_set :SAFE_STATE_PROTOTYPE, State.new
|
|
67
67
|
const_set :FAST_STATE_PROTOTYPE, State.new(
|
|
68
68
|
:indent => '',
|
|
69
69
|
:space => '',
|
|
70
70
|
:object_nl => "",
|
|
71
71
|
:array_nl => "",
|
|
72
72
|
:max_nesting => false
|
|
73
|
-
)
|
|
73
|
+
)
|
|
74
74
|
const_set :PRETTY_STATE_PROTOTYPE, State.new(
|
|
75
75
|
:indent => ' ',
|
|
76
76
|
:space => ' ',
|
|
77
77
|
:object_nl => "\n",
|
|
78
78
|
:array_nl => "\n"
|
|
79
|
-
)
|
|
79
|
+
)
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
# Returns the JSON generator modul, that is used by JSON. This might be
|
|
@@ -196,6 +196,7 @@ module JSON
|
|
|
196
196
|
# amount of sanity checks, and the pretty_generate method for some
|
|
197
197
|
# defaults for a pretty output.
|
|
198
198
|
def generate(obj, opts = nil)
|
|
199
|
+
state = SAFE_STATE_PROTOTYPE.dup
|
|
199
200
|
if opts
|
|
200
201
|
if opts.respond_to? :to_hash
|
|
201
202
|
opts = opts.to_hash
|
|
@@ -204,10 +205,7 @@ module JSON
|
|
|
204
205
|
else
|
|
205
206
|
raise TypeError, "can't convert #{opts.class} into Hash"
|
|
206
207
|
end
|
|
207
|
-
state = SAFE_STATE_PROTOTYPE.dup
|
|
208
208
|
state = state.configure(opts)
|
|
209
|
-
else
|
|
210
|
-
state = SAFE_STATE_PROTOTYPE
|
|
211
209
|
end
|
|
212
210
|
state.generate(obj)
|
|
213
211
|
end
|
|
@@ -225,6 +223,7 @@ module JSON
|
|
|
225
223
|
# *WARNING*: Be careful not to pass any Ruby data structures with circles as
|
|
226
224
|
# _obj_ argument, because this will cause JSON to go into an infinite loop.
|
|
227
225
|
def fast_generate(obj, opts = nil)
|
|
226
|
+
state = FAST_STATE_PROTOTYPE.dup
|
|
228
227
|
if opts
|
|
229
228
|
if opts.respond_to? :to_hash
|
|
230
229
|
opts = opts.to_hash
|
|
@@ -233,10 +232,7 @@ module JSON
|
|
|
233
232
|
else
|
|
234
233
|
raise TypeError, "can't convert #{opts.class} into Hash"
|
|
235
234
|
end
|
|
236
|
-
state = FAST_STATE_PROTOTYPE.dup
|
|
237
235
|
state.configure(opts)
|
|
238
|
-
else
|
|
239
|
-
state = FAST_STATE_PROTOTYPE
|
|
240
236
|
end
|
|
241
237
|
state.generate(obj)
|
|
242
238
|
end
|
|
@@ -254,6 +250,7 @@ module JSON
|
|
|
254
250
|
# The _opts_ argument can be used to configure the generator, see the
|
|
255
251
|
# generate method for a more detailed explanation.
|
|
256
252
|
def pretty_generate(obj, opts = nil)
|
|
253
|
+
state = PRETTY_STATE_PROTOTYPE.dup
|
|
257
254
|
if opts
|
|
258
255
|
if opts.respond_to? :to_hash
|
|
259
256
|
opts = opts.to_hash
|
|
@@ -262,10 +259,7 @@ module JSON
|
|
|
262
259
|
else
|
|
263
260
|
raise TypeError, "can't convert #{opts.class} into Hash"
|
|
264
261
|
end
|
|
265
|
-
state = PRETTY_STATE_PROTOTYPE.dup
|
|
266
262
|
state.configure(opts)
|
|
267
|
-
else
|
|
268
|
-
state = PRETTY_STATE_PROTOTYPE
|
|
269
263
|
end
|
|
270
264
|
state.generate(obj)
|
|
271
265
|
end
|
|
@@ -377,11 +371,11 @@ module ::Kernel
|
|
|
377
371
|
#
|
|
378
372
|
# The _opts_ argument is passed through to generate/parse respectively, see
|
|
379
373
|
# generate and parse for their documentation.
|
|
380
|
-
def JSON(object,
|
|
374
|
+
def JSON(object, *args)
|
|
381
375
|
if object.respond_to? :to_str
|
|
382
|
-
JSON.parse(object.to_str,
|
|
376
|
+
JSON.parse(object.to_str, args.first)
|
|
383
377
|
else
|
|
384
|
-
JSON.generate(object,
|
|
378
|
+
JSON.generate(object, args.first)
|
|
385
379
|
end
|
|
386
380
|
end
|
|
387
381
|
end
|
data/lib/json/pure/generator.rb
CHANGED
|
@@ -112,7 +112,7 @@ module JSON
|
|
|
112
112
|
when Hash
|
|
113
113
|
new(opts)
|
|
114
114
|
else
|
|
115
|
-
SAFE_STATE_PROTOTYPE
|
|
115
|
+
SAFE_STATE_PROTOTYPE.dup
|
|
116
116
|
end
|
|
117
117
|
end
|
|
118
118
|
|
|
@@ -163,7 +163,11 @@ module JSON
|
|
|
163
163
|
# the generated JSON, max_nesting = 0 if no maximum is checked.
|
|
164
164
|
attr_accessor :max_nesting
|
|
165
165
|
|
|
166
|
-
|
|
166
|
+
# This integer returns the current depth data structure nesting in the
|
|
167
|
+
# generated JSON.
|
|
168
|
+
attr_accessor :depth
|
|
169
|
+
|
|
170
|
+
def check_max_nesting # :nodoc:
|
|
167
171
|
return if @max_nesting.zero?
|
|
168
172
|
current_nesting = depth + 1
|
|
169
173
|
current_nesting > @max_nesting and
|
|
@@ -196,6 +200,7 @@ module JSON
|
|
|
196
200
|
@array_nl = opts[:array_nl] if opts.key?(:array_nl)
|
|
197
201
|
@allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
|
|
198
202
|
@ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
|
|
203
|
+
@depth = opts[:depth] || 0
|
|
199
204
|
if !opts.key?(:max_nesting) # defaults to 19
|
|
200
205
|
@max_nesting = 19
|
|
201
206
|
elsif opts[:max_nesting]
|
|
@@ -210,7 +215,7 @@ module JSON
|
|
|
210
215
|
# passed to the configure method.
|
|
211
216
|
def to_h
|
|
212
217
|
result = {}
|
|
213
|
-
for iv in %w[indent space space_before object_nl array_nl allow_nan max_nesting]
|
|
218
|
+
for iv in %w[indent space space_before object_nl array_nl allow_nan max_nesting ascii_only depth]
|
|
214
219
|
result[iv.intern] = instance_variable_get("@#{iv}")
|
|
215
220
|
end
|
|
216
221
|
result
|
|
@@ -247,51 +252,41 @@ module JSON
|
|
|
247
252
|
# _state_ is a JSON::State object, that can also be used to configure the
|
|
248
253
|
# produced JSON string output further.
|
|
249
254
|
# _depth_ is used to find out nesting depth, to indent accordingly.
|
|
250
|
-
def to_json(state = nil,
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
end
|
|
255
|
-
json_transform(state, depth)
|
|
255
|
+
def to_json(state = nil, *)
|
|
256
|
+
state = State.from_state(state)
|
|
257
|
+
state.check_max_nesting
|
|
258
|
+
json_transform(state)
|
|
256
259
|
end
|
|
257
260
|
|
|
258
261
|
private
|
|
259
262
|
|
|
260
|
-
def json_shift(state
|
|
261
|
-
state
|
|
262
|
-
state.indent * depth
|
|
263
|
+
def json_shift(state)
|
|
264
|
+
state.object_nl.empty? or return ''
|
|
265
|
+
state.indent * state.depth
|
|
263
266
|
end
|
|
264
267
|
|
|
265
|
-
def json_transform(state
|
|
268
|
+
def json_transform(state)
|
|
266
269
|
delim = ','
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
result << '}'
|
|
288
|
-
else
|
|
289
|
-
result = '{'
|
|
290
|
-
result << map { |key,value|
|
|
291
|
-
key.to_s.to_json << ':' << value.to_json
|
|
292
|
-
}.join(delim)
|
|
293
|
-
result << '}'
|
|
294
|
-
end
|
|
270
|
+
delim << state.object_nl
|
|
271
|
+
result = '{'
|
|
272
|
+
result << state.object_nl
|
|
273
|
+
depth = state.depth += 1
|
|
274
|
+
first = true
|
|
275
|
+
indent = !state.object_nl.empty?
|
|
276
|
+
each { |key,value|
|
|
277
|
+
result << delim unless first
|
|
278
|
+
result << state.indent * depth if indent
|
|
279
|
+
result << key.to_s.to_json(state)
|
|
280
|
+
result << state.space_before
|
|
281
|
+
result << ':'
|
|
282
|
+
result << state.space
|
|
283
|
+
result << value.to_json(state)
|
|
284
|
+
first = false
|
|
285
|
+
}
|
|
286
|
+
depth = state.depth -= 1
|
|
287
|
+
result << state.object_nl
|
|
288
|
+
result << state.indent * depth if indent if indent
|
|
289
|
+
result << '}'
|
|
295
290
|
result
|
|
296
291
|
end
|
|
297
292
|
end
|
|
@@ -301,39 +296,32 @@ module JSON
|
|
|
301
296
|
# this Array instance.
|
|
302
297
|
# _state_ is a JSON::State object, that can also be used to configure the
|
|
303
298
|
# produced JSON string output further.
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
state.check_max_nesting(depth)
|
|
309
|
-
end
|
|
310
|
-
json_transform(state, depth)
|
|
299
|
+
def to_json(state = nil, *)
|
|
300
|
+
state = State.from_state(state)
|
|
301
|
+
state.check_max_nesting
|
|
302
|
+
json_transform(state)
|
|
311
303
|
end
|
|
312
304
|
|
|
313
305
|
private
|
|
314
306
|
|
|
315
|
-
def json_transform(state
|
|
307
|
+
def json_transform(state)
|
|
316
308
|
delim = ','
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
result << delim unless first
|
|
326
|
-
result << state.indent * depth if indent
|
|
327
|
-
result << value.to_json(state, depth)
|
|
328
|
-
first = false
|
|
329
|
-
}
|
|
330
|
-
depth -= 1
|
|
331
|
-
result << state.array_nl
|
|
309
|
+
delim << state.array_nl
|
|
310
|
+
result = '['
|
|
311
|
+
result << state.array_nl
|
|
312
|
+
depth = state.depth += 1
|
|
313
|
+
first = true
|
|
314
|
+
indent = !state.array_nl.empty?
|
|
315
|
+
each { |value|
|
|
316
|
+
result << delim unless first
|
|
332
317
|
result << state.indent * depth if indent
|
|
333
|
-
result <<
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
318
|
+
result << value.to_json(state)
|
|
319
|
+
first = false
|
|
320
|
+
}
|
|
321
|
+
depth = state.depth -= 1
|
|
322
|
+
result << state.array_nl
|
|
323
|
+
result << state.indent * depth if indent
|
|
324
|
+
result << ']'
|
|
337
325
|
end
|
|
338
326
|
end
|
|
339
327
|
|
|
@@ -345,15 +333,16 @@ module JSON
|
|
|
345
333
|
module Float
|
|
346
334
|
# Returns a JSON string representation for this Float number.
|
|
347
335
|
def to_json(state = nil, *)
|
|
336
|
+
state = State.from_state(state)
|
|
348
337
|
case
|
|
349
338
|
when infinite?
|
|
350
|
-
if state
|
|
339
|
+
if state.allow_nan?
|
|
351
340
|
to_s
|
|
352
341
|
else
|
|
353
342
|
raise GeneratorError, "#{self} not allowed in JSON"
|
|
354
343
|
end
|
|
355
344
|
when nan?
|
|
356
|
-
if state
|
|
345
|
+
if state.allow_nan?
|
|
357
346
|
to_s
|
|
358
347
|
else
|
|
359
348
|
raise GeneratorError, "#{self} not allowed in JSON"
|
|
@@ -369,9 +358,8 @@ module JSON
|
|
|
369
358
|
# This string should be encoded with UTF-8 A call to this method
|
|
370
359
|
# returns a JSON string encoded with UTF16 big endian characters as
|
|
371
360
|
# \u????.
|
|
372
|
-
def to_json(*args)
|
|
373
|
-
state
|
|
374
|
-
state ||= State.from_state(state)
|
|
361
|
+
def to_json(state = nil, *args)
|
|
362
|
+
state = State.from_state(state)
|
|
375
363
|
if encoding == ::Encoding::UTF_8
|
|
376
364
|
string = self
|
|
377
365
|
else
|
|
@@ -387,9 +375,8 @@ module JSON
|
|
|
387
375
|
# This string should be encoded with UTF-8 A call to this method
|
|
388
376
|
# returns a JSON string encoded with UTF16 big endian characters as
|
|
389
377
|
# \u????.
|
|
390
|
-
def to_json(*args)
|
|
391
|
-
state
|
|
392
|
-
state ||= State.from_state(state)
|
|
378
|
+
def to_json(state = nil, *args)
|
|
379
|
+
state = State.from_state(state)
|
|
393
380
|
if state.ascii_only?
|
|
394
381
|
'"' << JSON.utf8_to_json_ascii(self) << '"'
|
|
395
382
|
else
|
data/lib/json/pure/parser.rb
CHANGED
|
@@ -69,40 +69,42 @@ module JSON
|
|
|
69
69
|
# * *object_class*: Defaults to Hash
|
|
70
70
|
# * *array_class*: Defaults to Array
|
|
71
71
|
def initialize(source, opts = {})
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
|
|
77
|
-
source.dup.force_encoding(Encoding::UTF_32BE).encode!(Encoding::UTF_8)
|
|
78
|
-
when b.size >= 4 && b[0] == 0 && b[2] == 0
|
|
79
|
-
source.dup.force_encoding(Encoding::UTF_16BE).encode!(Encoding::UTF_8)
|
|
80
|
-
when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
|
|
81
|
-
source.dup.force_encoding(Encoding::UTF_32LE).encode!(Encoding::UTF_8)
|
|
82
|
-
when b.size >= 4 && b[1] == 0 && b[3] == 0
|
|
83
|
-
source.dup.force_encoding(Encoding::UTF_16LE).encode!(Encoding::UTF_8)
|
|
84
|
-
else
|
|
85
|
-
source.dup
|
|
86
|
-
end
|
|
87
|
-
else
|
|
88
|
-
source = source.encode(Encoding::UTF_8)
|
|
89
|
-
end
|
|
90
|
-
source.force_encoding(Encoding::ASCII_8BIT)
|
|
91
|
-
else
|
|
92
|
-
b = source
|
|
72
|
+
opts ||= {}
|
|
73
|
+
if defined?(::Encoding)
|
|
74
|
+
if source.encoding == ::Encoding::ASCII_8BIT
|
|
75
|
+
b = source[0, 4].bytes.to_a
|
|
93
76
|
source = case
|
|
94
77
|
when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
|
|
95
|
-
|
|
78
|
+
source.dup.force_encoding(::Encoding::UTF_32BE).encode!(::Encoding::UTF_8)
|
|
96
79
|
when b.size >= 4 && b[0] == 0 && b[2] == 0
|
|
97
|
-
|
|
80
|
+
source.dup.force_encoding(::Encoding::UTF_16BE).encode!(::Encoding::UTF_8)
|
|
98
81
|
when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
|
|
99
|
-
|
|
82
|
+
source.dup.force_encoding(::Encoding::UTF_32LE).encode!(::Encoding::UTF_8)
|
|
83
|
+
|
|
100
84
|
when b.size >= 4 && b[1] == 0 && b[3] == 0
|
|
101
|
-
|
|
85
|
+
source.dup.force_encoding(::Encoding::UTF_16LE).encode!(::Encoding::UTF_8)
|
|
102
86
|
else
|
|
103
|
-
|
|
87
|
+
source.dup
|
|
104
88
|
end
|
|
89
|
+
else
|
|
90
|
+
source = source.encode(::Encoding::UTF_8)
|
|
105
91
|
end
|
|
92
|
+
source.force_encoding(::Encoding::ASCII_8BIT)
|
|
93
|
+
else
|
|
94
|
+
b = source
|
|
95
|
+
source = case
|
|
96
|
+
when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
|
|
97
|
+
JSON.iconv('utf-8', 'utf-32be', b)
|
|
98
|
+
when b.size >= 4 && b[0] == 0 && b[2] == 0
|
|
99
|
+
JSON.iconv('utf-8', 'utf-16be', b)
|
|
100
|
+
when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
|
|
101
|
+
JSON.iconv('utf-8', 'utf-32le', b)
|
|
102
|
+
when b.size >= 4 && b[1] == 0 && b[3] == 0
|
|
103
|
+
JSON.iconv('utf-8', 'utf-16le', b)
|
|
104
|
+
else
|
|
105
|
+
b
|
|
106
|
+
end
|
|
107
|
+
end
|
|
106
108
|
super source
|
|
107
109
|
if !opts.key?(:max_nesting) # defaults to 19
|
|
108
110
|
@max_nesting = 19
|
|
@@ -180,7 +182,7 @@ module JSON
|
|
|
180
182
|
end
|
|
181
183
|
end
|
|
182
184
|
if string.respond_to?(:force_encoding)
|
|
183
|
-
string.force_encoding(Encoding::UTF_8)
|
|
185
|
+
string.force_encoding(::Encoding::UTF_8)
|
|
184
186
|
end
|
|
185
187
|
string
|
|
186
188
|
else
|
data/lib/json/version.rb
CHANGED
data/tests/test_json.rb
CHANGED
|
@@ -160,6 +160,20 @@ class TC_JSON < Test::Unit::TestCase
|
|
|
160
160
|
|
|
161
161
|
class SubArray < Array; end
|
|
162
162
|
|
|
163
|
+
class SubArray2 < Array
|
|
164
|
+
def to_json(*a)
|
|
165
|
+
{
|
|
166
|
+
JSON.create_id => self.class.name,
|
|
167
|
+
'ary' => to_a,
|
|
168
|
+
}.to_json(*a)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def self.json_create(o)
|
|
172
|
+
o.delete JSON.create_id
|
|
173
|
+
o['ary']
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
163
177
|
def test_parse_array_custom_class
|
|
164
178
|
res = parse('[]', :array_class => SubArray)
|
|
165
179
|
assert_equal([], res)
|
|
@@ -173,12 +187,52 @@ class TC_JSON < Test::Unit::TestCase
|
|
|
173
187
|
assert_equal({'foo'=>'bar'}, parse(' { "foo" : "bar" } '))
|
|
174
188
|
end
|
|
175
189
|
|
|
176
|
-
class SubHash < Hash
|
|
190
|
+
class SubHash < Hash
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
class SubHash2 < Hash
|
|
194
|
+
def to_json(*a)
|
|
195
|
+
{
|
|
196
|
+
JSON.create_id => self.class.name,
|
|
197
|
+
}.merge(self).to_json(*a)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def self.json_create(o)
|
|
201
|
+
o.delete JSON.create_id
|
|
202
|
+
self[o]
|
|
203
|
+
end
|
|
204
|
+
end
|
|
177
205
|
|
|
178
206
|
def test_parse_object_custom_class
|
|
179
|
-
res = parse('{}', :object_class =>
|
|
207
|
+
res = parse('{}', :object_class => SubHash2)
|
|
180
208
|
assert_equal({}, res)
|
|
181
|
-
assert_equal(
|
|
209
|
+
assert_equal(SubHash2, res.class)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def test_generation_of_core_subclasses_with_new_to_json
|
|
213
|
+
obj = SubHash2["foo" => SubHash2["bar" => true]]
|
|
214
|
+
obj_json = JSON(obj)
|
|
215
|
+
obj_again = JSON(obj_json)
|
|
216
|
+
assert_kind_of SubHash2, obj_again
|
|
217
|
+
assert_kind_of SubHash2, obj_again['foo']
|
|
218
|
+
assert obj_again['foo']['bar']
|
|
219
|
+
assert_equal obj, obj_again
|
|
220
|
+
assert_equal ["foo"], JSON(JSON(SubArray2["foo"]))
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def test_generation_of_core_subclasses_with_default_to_json
|
|
224
|
+
assert_equal '{"foo":"bar"}', JSON(SubHash["foo" => "bar"])
|
|
225
|
+
assert_equal '["foo"]', JSON(SubArray["foo"])
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def test_generation_of_core_subclasses
|
|
229
|
+
obj = SubHash["foo" => SubHash["bar" => true]]
|
|
230
|
+
obj_json = JSON(obj)
|
|
231
|
+
obj_again = JSON(obj_json)
|
|
232
|
+
assert_kind_of Hash, obj_again
|
|
233
|
+
assert_kind_of Hash, obj_again['foo']
|
|
234
|
+
assert obj_again['foo']['bar']
|
|
235
|
+
assert_equal obj, obj_again
|
|
182
236
|
end
|
|
183
237
|
|
|
184
238
|
def test_parser_reset
|
|
@@ -324,4 +378,17 @@ EOT
|
|
|
324
378
|
JSON.dump(eval(too_deep), output, 20)
|
|
325
379
|
assert_equal too_deep, output.string
|
|
326
380
|
end
|
|
381
|
+
|
|
382
|
+
def test_big_integers
|
|
383
|
+
json1 = JSON([orig = (1 << 31) - 1])
|
|
384
|
+
assert_equal orig, JSON[json1][0]
|
|
385
|
+
json2 = JSON([orig = 1 << 31])
|
|
386
|
+
assert_equal orig, JSON[json2][0]
|
|
387
|
+
json3 = JSON([orig = (1 << 62) - 1])
|
|
388
|
+
assert_equal orig, JSON[json3][0]
|
|
389
|
+
json4 = JSON([orig = 1 << 62])
|
|
390
|
+
assert_equal orig, JSON[json4][0]
|
|
391
|
+
json5 = JSON([orig = 1 << 64])
|
|
392
|
+
assert_equal orig, JSON[json5][0]
|
|
393
|
+
end
|
|
327
394
|
end
|
data/tests/test_json_addition.rb
CHANGED
|
@@ -151,12 +151,12 @@ class TC_JSONAddition < Test::Unit::TestCase
|
|
|
151
151
|
def test_utc_datetime
|
|
152
152
|
now = Time.now
|
|
153
153
|
d = DateTime.parse(now.to_s) # usual case
|
|
154
|
-
|
|
154
|
+
assert_equal d, JSON.parse(d.to_json)
|
|
155
155
|
d = DateTime.parse(now.utc.to_s) # of = 0
|
|
156
|
-
|
|
157
|
-
d = DateTime.civil(2008, 6, 17, 11, 48, 32, 1)
|
|
158
|
-
|
|
159
|
-
d = DateTime.civil(2008, 6, 17, 11, 48, 32, 12)
|
|
160
|
-
|
|
156
|
+
assert_equal d, JSON.parse(d.to_json)
|
|
157
|
+
d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(1,24))
|
|
158
|
+
assert_equal d, JSON.parse(d.to_json)
|
|
159
|
+
d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(12,24))
|
|
160
|
+
assert_equal d, JSON.parse(d.to_json)
|
|
161
161
|
end
|
|
162
162
|
end
|