oj 2.13.1 → 2.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +177 -104
- data/ext/oj/dump.c +60 -60
- data/ext/oj/oj.c +319 -343
- data/ext/oj/oj.h +27 -25
- data/ext/oj/parse.c +19 -9
- data/lib/oj/version.rb +1 -1
- data/test/test_various.rb +47 -32
- metadata +2 -4
- data/test/zip.rb +0 -34
data/ext/oj/oj.c
CHANGED
@@ -90,6 +90,8 @@ ID oj_utc_offset_id;
|
|
90
90
|
ID oj_utcq_id;
|
91
91
|
ID oj_write_id;
|
92
92
|
|
93
|
+
static ID has_key_id;
|
94
|
+
|
93
95
|
VALUE oj_bag_class;
|
94
96
|
VALUE oj_bigdecimal_class;
|
95
97
|
VALUE oj_cstack_class;
|
@@ -160,26 +162,38 @@ VALUE oj_cache_mutex = Qnil;
|
|
160
162
|
static const char json_class[] = "json_class";
|
161
163
|
|
162
164
|
struct _Options oj_default_options = {
|
163
|
-
0,
|
164
|
-
No,
|
165
|
-
No,
|
166
|
-
No,
|
167
|
-
JSONEsc,
|
168
|
-
ObjectMode,
|
169
|
-
Yes,
|
170
|
-
UnixZTime,
|
171
|
-
Yes,
|
172
|
-
AutoDec,
|
173
|
-
Yes,
|
174
|
-
No,
|
175
|
-
Yes,
|
176
|
-
Yes,
|
177
|
-
json_class,
|
178
|
-
10,
|
179
|
-
9,
|
180
|
-
|
181
|
-
|
182
|
-
|
165
|
+
0, // indent
|
166
|
+
No, // circular
|
167
|
+
No, // auto_define
|
168
|
+
No, // sym_key
|
169
|
+
JSONEsc, // escape_mode
|
170
|
+
ObjectMode, // mode
|
171
|
+
Yes, // class_cache
|
172
|
+
UnixZTime, // time_format
|
173
|
+
Yes, // bigdec_as_num
|
174
|
+
AutoDec, // bigdec_load
|
175
|
+
Yes, // to_json
|
176
|
+
No, // nilnil
|
177
|
+
Yes, // allow_gc
|
178
|
+
Yes, // quirks_mode
|
179
|
+
json_class, // create_id
|
180
|
+
10, // create_id_len
|
181
|
+
9, // sec_prec
|
182
|
+
15, // float_prec
|
183
|
+
"%0.15g", // float_fmt
|
184
|
+
{ // dump_opts
|
185
|
+
false, //use
|
186
|
+
"", // indent
|
187
|
+
"", // before_sep
|
188
|
+
"", // after_sep
|
189
|
+
"", // hash_nl
|
190
|
+
"", // array_nl
|
191
|
+
0, // indent_size
|
192
|
+
0, // before_size
|
193
|
+
0, // after_size
|
194
|
+
0, // hash_size
|
195
|
+
0, // array_size
|
196
|
+
}
|
183
197
|
};
|
184
198
|
|
185
199
|
static VALUE define_mimic_json(int argc, VALUE *argv, VALUE self);
|
@@ -187,7 +201,7 @@ static VALUE define_mimic_json(int argc, VALUE *argv, VALUE self);
|
|
187
201
|
/* call-seq: default_options() => Hash
|
188
202
|
*
|
189
203
|
* Returns the default load and dump options as a Hash. The options are
|
190
|
-
* - indent: [Fixnum] number of spaces to indent each element in an JSON document, zero is no newline between JSON elements, negative indicates no newline between top level JSON elements in a stream
|
204
|
+
* - indent: [Fixnum|String|nil] number of spaces to indent each element in an JSON document, zero or nil is no newline between JSON elements, negative indicates no newline between top level JSON elements in a stream, a String indicates the string should be used for indentation
|
191
205
|
* - circular: [true|false|nil] support circular references while dumping
|
192
206
|
* - auto_define: [true|false|nil] automatically define classes if they do not exist
|
193
207
|
* - symbol_keys: [true|false|nil] use symbols instead of strings for hash keys
|
@@ -204,13 +218,22 @@ static VALUE define_mimic_json(int argc, VALUE *argv, VALUE self);
|
|
204
218
|
* - nilnil: [true|false|nil] if true a nil input to load will return nil and not raise an Exception
|
205
219
|
* - allow_gc: [true|false|nil] allow or prohibit GC during parsing, default is true (allow)
|
206
220
|
* - quirks_mode: [true,|false|nil] Allow single JSON values instead of documents, default is true (allow)
|
221
|
+
* - indent_str: [String|nil] String to use for indentation, overriding the indent option is not nil
|
222
|
+
* - space: [String|nil] String to use for the space after the colon in JSON object fields
|
223
|
+
* - space_before: [String|nil] String to use before the colon separator in JSON object fields
|
224
|
+
* - object_nl: [String|nil] String to use after a JSON object field value
|
225
|
+
* - array_nl: [String|nil] String to use after a JSON array value
|
207
226
|
* @return [Hash] all current option settings.
|
208
227
|
*/
|
209
228
|
static VALUE
|
210
229
|
get_def_opts(VALUE self) {
|
211
230
|
VALUE opts = rb_hash_new();
|
212
|
-
|
213
|
-
|
231
|
+
|
232
|
+
if (0 == oj_default_options.dump_opts.indent_size) {
|
233
|
+
rb_hash_aset(opts, indent_sym, INT2FIX(oj_default_options.indent));
|
234
|
+
} else {
|
235
|
+
rb_hash_aset(opts, indent_sym, rb_str_new2(oj_default_options.dump_opts.indent_str));
|
236
|
+
}
|
214
237
|
rb_hash_aset(opts, sec_prec_sym, INT2FIX(oj_default_options.sec_prec));
|
215
238
|
rb_hash_aset(opts, circular_sym, (Yes == oj_default_options.circular) ? Qtrue : ((No == oj_default_options.circular) ? Qfalse : Qnil));
|
216
239
|
rb_hash_aset(opts, class_cache_sym, (Yes == oj_default_options.class_cache) ? Qtrue : ((No == oj_default_options.class_cache) ? Qfalse : Qnil));
|
@@ -250,6 +273,10 @@ get_def_opts(VALUE self) {
|
|
250
273
|
default: rb_hash_aset(opts, bigdecimal_load_sym, auto_sym); break;
|
251
274
|
}
|
252
275
|
rb_hash_aset(opts, create_id_sym, (0 == oj_default_options.create_id) ? Qnil : rb_str_new2(oj_default_options.create_id));
|
276
|
+
rb_hash_aset(opts, space_sym, (0 == oj_default_options.dump_opts.after_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.after_sep));
|
277
|
+
rb_hash_aset(opts, space_before_sym, (0 == oj_default_options.dump_opts.before_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.before_sep));
|
278
|
+
rb_hash_aset(opts, object_nl_sym, (0 == oj_default_options.dump_opts.hash_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.hash_nl));
|
279
|
+
rb_hash_aset(opts, array_nl_sym, (0 == oj_default_options.dump_opts.array_size) ? Qnil : rb_str_new2(oj_default_options.dump_opts.array_nl));
|
253
280
|
|
254
281
|
return opts;
|
255
282
|
}
|
@@ -258,7 +285,7 @@ get_def_opts(VALUE self) {
|
|
258
285
|
*
|
259
286
|
* Sets the default options for load and dump.
|
260
287
|
* @param [Hash] opts options to change
|
261
|
-
* @param [Fixnum] :indent number of spaces to indent each element in
|
288
|
+
* @param [Fixnum|String|nil] :indent number of spaces to indent each element in a JSON document or the String to use for identation.
|
262
289
|
* @param [true|false|nil] :circular support circular references while dumping
|
263
290
|
* @param [true|false|nil] :auto_define automatically define classes if they do not exist
|
264
291
|
* @param [true|false|nil] :symbol_keys convert hash keys to symbols
|
@@ -289,314 +316,247 @@ get_def_opts(VALUE self) {
|
|
289
316
|
* @param [true|false|nil] :nilnil if true a nil input to load will return nil and not raise an Exception
|
290
317
|
* @param [true|false|nil] :allow_gc allow or prohibit GC during parsing, default is true (allow)
|
291
318
|
* @param [true|false|nil] :quirks_mode allow single JSON values instead of documents, default is true (allow)
|
319
|
+
* @param [String|nil] :space String to use for the space after the colon in JSON object fields
|
320
|
+
* @param [String|nil] :space_before String to use before the colon separator in JSON object fields
|
321
|
+
* @param [String|nil] :object_nl String to use after a JSON object field value
|
322
|
+
* @param [String|nil] :array_nl String to use after a JSON array value
|
292
323
|
* @return [nil]
|
293
324
|
*/
|
294
325
|
static VALUE
|
295
326
|
set_def_opts(VALUE self, VALUE opts) {
|
327
|
+
Check_Type(opts, T_HASH);
|
328
|
+
oj_parse_options(opts, &oj_default_options);
|
329
|
+
|
330
|
+
return Qnil;
|
331
|
+
}
|
332
|
+
|
333
|
+
void
|
334
|
+
oj_parse_options(VALUE ropts, Options copts) {
|
296
335
|
struct _YesNoOpt ynos[] = {
|
297
|
-
{ circular_sym, &
|
298
|
-
{ auto_define_sym, &
|
299
|
-
{ symbol_keys_sym, &
|
300
|
-
{ class_cache_sym, &
|
301
|
-
{ bigdecimal_as_decimal_sym, &
|
302
|
-
{ use_to_json_sym, &
|
303
|
-
{ nilnil_sym, &
|
304
|
-
{ allow_gc_sym, &
|
305
|
-
{ quirks_mode_sym, &
|
336
|
+
{ circular_sym, &copts->circular },
|
337
|
+
{ auto_define_sym, &copts->auto_define },
|
338
|
+
{ symbol_keys_sym, &copts->sym_key },
|
339
|
+
{ class_cache_sym, &copts->class_cache },
|
340
|
+
{ bigdecimal_as_decimal_sym, &copts->bigdec_as_num },
|
341
|
+
{ use_to_json_sym, &copts->to_json },
|
342
|
+
{ nilnil_sym, &copts->nilnil },
|
343
|
+
{ allow_gc_sym, &copts->allow_gc },
|
344
|
+
{ quirks_mode_sym, &copts->quirks_mode },
|
306
345
|
{ Qnil, 0 }
|
307
346
|
};
|
308
|
-
YesNoOpt
|
309
|
-
VALUE v;
|
347
|
+
YesNoOpt o;
|
348
|
+
volatile VALUE v;
|
349
|
+
size_t len;
|
310
350
|
|
311
|
-
|
312
|
-
|
313
|
-
if (Qnil != v) {
|
314
|
-
Check_Type(v, T_FIXNUM);
|
315
|
-
oj_default_options.indent = FIX2INT(v);
|
351
|
+
if (T_HASH != rb_type(ropts)) {
|
352
|
+
return;
|
316
353
|
}
|
317
|
-
|
318
|
-
|
354
|
+
if (Qtrue == rb_funcall(ropts, has_key_id, 1, indent_sym)) {
|
355
|
+
v = rb_hash_lookup(ropts, indent_sym);
|
356
|
+
switch (rb_type(v)) {
|
357
|
+
case T_NIL:
|
358
|
+
copts->dump_opts.indent_size = 0;
|
359
|
+
*copts->dump_opts.indent_str = '\0';
|
360
|
+
copts->indent = 0;
|
361
|
+
break;
|
362
|
+
case T_FIXNUM:
|
363
|
+
copts->dump_opts.indent_size = 0;
|
364
|
+
*copts->dump_opts.indent_str = '\0';
|
365
|
+
copts->indent = FIX2INT(v);
|
366
|
+
break;
|
367
|
+
case T_STRING:
|
368
|
+
if (sizeof(copts->dump_opts.indent_str) <= (len = RSTRING_LEN(v))) {
|
369
|
+
rb_raise(rb_eArgError, "indent string is limited to %lu characters.", sizeof(copts->dump_opts.indent_str));
|
370
|
+
}
|
371
|
+
strcpy(copts->dump_opts.indent_str, StringValuePtr(v));
|
372
|
+
copts->dump_opts.indent_size = (uint8_t)len;
|
373
|
+
copts->indent = 0;
|
374
|
+
break;
|
375
|
+
default:
|
376
|
+
rb_raise(rb_eTypeError, "indent must be a Fixnum, String, or nil.");
|
377
|
+
break;
|
378
|
+
}
|
379
|
+
}
|
380
|
+
if (Qnil != (v = rb_hash_lookup(ropts, float_prec_sym))) {
|
319
381
|
int n;
|
320
382
|
|
383
|
+
if (rb_cFixnum != rb_obj_class(v)) {
|
384
|
+
rb_raise(rb_eArgError, ":float_precision must be a Fixnum.");
|
385
|
+
}
|
321
386
|
Check_Type(v, T_FIXNUM);
|
322
387
|
n = FIX2INT(v);
|
323
388
|
if (0 >= n) {
|
324
|
-
*
|
325
|
-
|
389
|
+
*copts->float_fmt = '\0';
|
390
|
+
copts->float_prec = 0;
|
326
391
|
} else {
|
327
392
|
if (20 < n) {
|
328
393
|
n = 20;
|
329
394
|
}
|
330
|
-
sprintf(
|
331
|
-
|
395
|
+
sprintf(copts->float_fmt, "%%0.%dg", n);
|
396
|
+
copts->float_prec = n;
|
332
397
|
}
|
333
398
|
}
|
334
|
-
v =
|
335
|
-
if (Qnil != v) {
|
399
|
+
if (Qnil != (v = rb_hash_lookup(ropts, sec_prec_sym))) {
|
336
400
|
int n;
|
337
401
|
|
338
|
-
|
339
|
-
|
402
|
+
if (rb_cFixnum != rb_obj_class(v)) {
|
403
|
+
rb_raise(rb_eArgError, ":second_precision must be a Fixnum.");
|
404
|
+
}
|
405
|
+
n = NUM2INT(v);
|
340
406
|
if (0 > n) {
|
341
407
|
n = 0;
|
342
408
|
} else if (9 < n) {
|
343
409
|
n = 9;
|
344
410
|
}
|
345
|
-
|
346
|
-
}
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
} else {
|
360
|
-
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null.");
|
361
|
-
}
|
362
|
-
|
363
|
-
v = rb_hash_lookup(opts, time_format_sym);
|
364
|
-
if (Qnil == v) {
|
365
|
-
// ignore
|
366
|
-
} else if (unix_sym == v) {
|
367
|
-
oj_default_options.time_format = UnixTime;
|
368
|
-
} else if (unix_zone_sym == v) {
|
369
|
-
oj_default_options.time_format = UnixZTime;
|
370
|
-
} else if (xmlschema_sym == v) {
|
371
|
-
oj_default_options.time_format = XmlTime;
|
372
|
-
} else if (ruby_sym == v) {
|
373
|
-
oj_default_options.time_format = RubyTime;
|
374
|
-
} else {
|
375
|
-
rb_raise(rb_eArgError, ":time_format must be :unix, :unix_zone, :xmlschema, or :ruby.");
|
376
|
-
}
|
377
|
-
|
378
|
-
v = rb_hash_lookup(opts, escape_mode_sym);
|
379
|
-
if (Qnil == v) {
|
380
|
-
// ignore
|
381
|
-
} else if (newline_sym == v) {
|
382
|
-
oj_default_options.escape_mode = NLEsc;
|
383
|
-
} else if (json_sym == v) {
|
384
|
-
oj_default_options.escape_mode = JSONEsc;
|
385
|
-
} else if (xss_safe_sym == v) {
|
386
|
-
oj_default_options.escape_mode = XSSEsc;
|
387
|
-
} else if (ascii_sym == v) {
|
388
|
-
oj_default_options.escape_mode = ASCIIEsc;
|
389
|
-
} else {
|
390
|
-
rb_raise(rb_eArgError, ":escape_mode must be :newline, :json, :xss_safe, or :ascii.");
|
391
|
-
}
|
392
|
-
|
393
|
-
v = rb_hash_lookup(opts, bigdecimal_load_sym);
|
394
|
-
if (Qnil == v) {
|
395
|
-
// ignore
|
396
|
-
} else if (bigdecimal_sym == v || Qtrue == v) {
|
397
|
-
oj_default_options.bigdec_load = BigDec;
|
398
|
-
} else if (float_sym == v) {
|
399
|
-
oj_default_options.bigdec_load = FloatDec;
|
400
|
-
} else if (auto_sym == v || Qfalse == v) {
|
401
|
-
oj_default_options.bigdec_load = AutoDec;
|
402
|
-
} else {
|
403
|
-
rb_raise(rb_eArgError, ":bigdecimal_load must be :bigdecimal, :float, or :auto.");
|
411
|
+
copts->sec_prec = n;
|
412
|
+
}
|
413
|
+
if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
|
414
|
+
if (object_sym == v) {
|
415
|
+
copts->mode = ObjectMode;
|
416
|
+
} else if (strict_sym == v) {
|
417
|
+
copts->mode = StrictMode;
|
418
|
+
} else if (compat_sym == v) {
|
419
|
+
copts->mode = CompatMode;
|
420
|
+
} else if (null_sym == v) {
|
421
|
+
copts->mode = NullMode;
|
422
|
+
} else {
|
423
|
+
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null.");
|
424
|
+
}
|
404
425
|
}
|
405
|
-
|
406
|
-
|
407
|
-
|
426
|
+
if (Qnil != (v = rb_hash_lookup(ropts, time_format_sym))) {
|
427
|
+
if (unix_sym == v) {
|
428
|
+
copts->time_format = UnixTime;
|
429
|
+
} else if (unix_zone_sym == v) {
|
430
|
+
copts->time_format = UnixZTime;
|
431
|
+
} else if (xmlschema_sym == v) {
|
432
|
+
copts->time_format = XmlTime;
|
433
|
+
} else if (ruby_sym == v) {
|
434
|
+
copts->time_format = RubyTime;
|
435
|
+
} else {
|
436
|
+
rb_raise(rb_eArgError, ":time_format must be :unix, :unix_zone, :xmlschema, or :ruby.");
|
437
|
+
}
|
438
|
+
}
|
439
|
+
if (Qnil != (v = rb_hash_lookup(ropts, escape_mode_sym))) {
|
440
|
+
if (newline_sym == v) {
|
441
|
+
copts->escape_mode = NLEsc;
|
442
|
+
} else if (json_sym == v) {
|
443
|
+
copts->escape_mode = JSONEsc;
|
444
|
+
} else if (xss_safe_sym == v) {
|
445
|
+
copts->escape_mode = XSSEsc;
|
446
|
+
} else if (ascii_sym == v) {
|
447
|
+
copts->escape_mode = ASCIIEsc;
|
448
|
+
} else {
|
449
|
+
rb_raise(rb_eArgError, ":encoding must be :newline, :json, :xss_safe, or :ascii.");
|
450
|
+
}
|
451
|
+
}
|
452
|
+
if (Qnil != (v = rb_hash_lookup(ropts, bigdecimal_load_sym))) {
|
453
|
+
if (bigdecimal_sym == v || Qtrue == v) {
|
454
|
+
copts->bigdec_load = BigDec;
|
455
|
+
} else if (float_sym == v) {
|
456
|
+
copts->bigdec_load = FloatDec;
|
457
|
+
} else if (auto_sym == v || Qfalse == v) {
|
458
|
+
copts->bigdec_load = AutoDec;
|
459
|
+
} else {
|
460
|
+
rb_raise(rb_eArgError, ":bigdecimal_load must be :bigdecimal, :float, or :auto.");
|
461
|
+
}
|
462
|
+
}
|
463
|
+
if (Qtrue == rb_funcall(ropts, has_key_id, 1, create_id_sym)) {
|
464
|
+
v = rb_hash_lookup(ropts, create_id_sym);
|
465
|
+
if (Qnil == v) {
|
408
466
|
if (json_class != oj_default_options.create_id) {
|
409
467
|
xfree((char*)oj_default_options.create_id);
|
410
468
|
}
|
411
|
-
|
412
|
-
|
413
|
-
}
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
469
|
+
copts->create_id = NULL;
|
470
|
+
copts->create_id_len = 0;
|
471
|
+
} else if (T_STRING == rb_type(v)) {
|
472
|
+
const char *str = StringValuePtr(v);
|
473
|
+
|
474
|
+
len = RSTRING_LEN(v);
|
475
|
+
if (len != copts->create_id_len ||
|
476
|
+
0 != strcmp(copts->create_id, str)) {
|
477
|
+
copts->create_id = ALLOC_N(char, len + 1);
|
478
|
+
strcpy((char*)copts->create_id, str);
|
479
|
+
copts->create_id_len = len;
|
480
|
+
}
|
481
|
+
} else {
|
482
|
+
rb_raise(rb_eArgError, ":create_id must be string.");
|
421
483
|
}
|
422
484
|
}
|
423
|
-
|
424
485
|
for (o = ynos; 0 != o->attr; o++) {
|
425
|
-
if (
|
426
|
-
continue;
|
427
|
-
}
|
428
|
-
if (Qnil != (v = rb_hash_lookup(opts, o->sym))) {
|
486
|
+
if (Qnil != (v = rb_hash_lookup(ropts, o->sym))) {
|
429
487
|
if (Qtrue == v) {
|
430
488
|
*o->attr = Yes;
|
431
489
|
} else if (Qfalse == v) {
|
432
490
|
*o->attr = No;
|
433
491
|
} else {
|
434
|
-
rb_raise(rb_eArgError, "%s must be true
|
492
|
+
rb_raise(rb_eArgError, "%s must be true or false.", rb_id2name(SYM2ID(o->sym)));
|
435
493
|
}
|
436
494
|
}
|
437
495
|
}
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
}
|
447
|
-
|
448
|
-
void
|
449
|
-
oj_parse_options(VALUE ropts, Options copts) {
|
450
|
-
struct _YesNoOpt ynos[] = {
|
451
|
-
{ circular_sym, &copts->circular },
|
452
|
-
{ auto_define_sym, &copts->auto_define },
|
453
|
-
{ symbol_keys_sym, &copts->sym_key },
|
454
|
-
{ class_cache_sym, &copts->class_cache },
|
455
|
-
{ bigdecimal_as_decimal_sym, &copts->bigdec_as_num },
|
456
|
-
{ use_to_json_sym, &copts->to_json },
|
457
|
-
{ nilnil_sym, &copts->nilnil },
|
458
|
-
{ allow_gc_sym, &copts->allow_gc },
|
459
|
-
{ quirks_mode_sym, &copts->quirks_mode },
|
460
|
-
{ Qnil, 0 }
|
461
|
-
};
|
462
|
-
YesNoOpt o;
|
463
|
-
|
464
|
-
if (rb_cHash == rb_obj_class(ropts)) {
|
465
|
-
VALUE v;
|
466
|
-
|
467
|
-
if (Qnil != (v = rb_hash_lookup(ropts, indent_sym))) {
|
468
|
-
if (rb_cFixnum != rb_obj_class(v)) {
|
469
|
-
rb_raise(rb_eArgError, ":indent must be a Fixnum.");
|
470
|
-
}
|
471
|
-
copts->indent = NUM2INT(v);
|
472
|
-
}
|
473
|
-
if (Qnil != (v = rb_hash_lookup(ropts, float_prec_sym))) {
|
474
|
-
int n;
|
475
|
-
|
476
|
-
if (rb_cFixnum != rb_obj_class(v)) {
|
477
|
-
rb_raise(rb_eArgError, ":float_precision must be a Fixnum.");
|
478
|
-
}
|
479
|
-
Check_Type(v, T_FIXNUM);
|
480
|
-
n = FIX2INT(v);
|
481
|
-
if (0 >= n) {
|
482
|
-
*copts->float_fmt = '\0';
|
483
|
-
copts->float_prec = 0;
|
484
|
-
} else {
|
485
|
-
if (20 < n) {
|
486
|
-
n = 20;
|
487
|
-
}
|
488
|
-
sprintf(copts->float_fmt, "%%0.%dg", n);
|
489
|
-
copts->float_prec = n;
|
490
|
-
}
|
491
|
-
}
|
492
|
-
if (Qnil != (v = rb_hash_lookup(ropts, sec_prec_sym))) {
|
493
|
-
int n;
|
494
|
-
|
495
|
-
if (rb_cFixnum != rb_obj_class(v)) {
|
496
|
-
rb_raise(rb_eArgError, ":second_precision must be a Fixnum.");
|
497
|
-
}
|
498
|
-
n = NUM2INT(v);
|
499
|
-
if (0 > n) {
|
500
|
-
n = 0;
|
501
|
-
} else if (9 < n) {
|
502
|
-
n = 9;
|
503
|
-
}
|
504
|
-
copts->sec_prec = n;
|
505
|
-
}
|
506
|
-
if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
|
507
|
-
if (object_sym == v) {
|
508
|
-
copts->mode = ObjectMode;
|
509
|
-
} else if (strict_sym == v) {
|
510
|
-
copts->mode = StrictMode;
|
511
|
-
} else if (compat_sym == v) {
|
512
|
-
copts->mode = CompatMode;
|
513
|
-
} else if (null_sym == v) {
|
514
|
-
copts->mode = NullMode;
|
515
|
-
} else {
|
516
|
-
rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, or :null.");
|
517
|
-
}
|
518
|
-
}
|
519
|
-
if (Qnil != (v = rb_hash_lookup(ropts, time_format_sym))) {
|
520
|
-
if (unix_sym == v) {
|
521
|
-
copts->time_format = UnixTime;
|
522
|
-
} else if (unix_zone_sym == v) {
|
523
|
-
copts->time_format = UnixZTime;
|
524
|
-
} else if (xmlschema_sym == v) {
|
525
|
-
copts->time_format = XmlTime;
|
526
|
-
} else if (ruby_sym == v) {
|
527
|
-
copts->time_format = RubyTime;
|
528
|
-
} else {
|
529
|
-
rb_raise(rb_eArgError, ":time_format must be :unix, :unix_zone, :xmlschema, or :ruby.");
|
530
|
-
}
|
531
|
-
}
|
532
|
-
|
533
|
-
if (Qnil != (v = rb_hash_lookup(ropts, escape_mode_sym))) {
|
534
|
-
if (newline_sym == v) {
|
535
|
-
copts->escape_mode = NLEsc;
|
536
|
-
} else if (json_sym == v) {
|
537
|
-
copts->escape_mode = JSONEsc;
|
538
|
-
} else if (xss_safe_sym == v) {
|
539
|
-
copts->escape_mode = XSSEsc;
|
540
|
-
} else if (ascii_sym == v) {
|
541
|
-
copts->escape_mode = ASCIIEsc;
|
542
|
-
} else {
|
543
|
-
rb_raise(rb_eArgError, ":encoding must be :newline, :json, :xss_safe, or :ascii.");
|
496
|
+
if (Qtrue == rb_funcall(ropts, has_key_id, 1, space_sym)) {
|
497
|
+
if (Qnil == (v = rb_hash_lookup(ropts, space_sym))) {
|
498
|
+
copts->dump_opts.after_size = 0;
|
499
|
+
*copts->dump_opts.after_sep = '\0';
|
500
|
+
} else {
|
501
|
+
rb_check_type(v, T_STRING);
|
502
|
+
if (sizeof(copts->dump_opts.after_sep) <= (len = RSTRING_LEN(v))) {
|
503
|
+
rb_raise(rb_eArgError, "space string is limited to %lu characters.", sizeof(copts->dump_opts.after_sep));
|
544
504
|
}
|
505
|
+
strcpy(copts->dump_opts.after_sep, StringValuePtr(v));
|
506
|
+
copts->dump_opts.after_size = (uint8_t)len;
|
545
507
|
}
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
rb_raise(rb_eArgError, ":bigdecimal_load must be :bigdecimal, :float, or :auto.");
|
508
|
+
}
|
509
|
+
if (Qtrue == rb_funcall(ropts, has_key_id, 1, space_before_sym)) {
|
510
|
+
if (Qnil == (v = rb_hash_lookup(ropts, space_before_sym))) {
|
511
|
+
copts->dump_opts.before_size = 0;
|
512
|
+
*copts->dump_opts.before_sep = '\0';
|
513
|
+
} else {
|
514
|
+
rb_check_type(v, T_STRING);
|
515
|
+
if (sizeof(copts->dump_opts.before_sep) <= (len = RSTRING_LEN(v))) {
|
516
|
+
rb_raise(rb_eArgError, "sapce_before string is limited to %lu characters.", sizeof(copts->dump_opts.before_sep));
|
556
517
|
}
|
518
|
+
strcpy(copts->dump_opts.before_sep, StringValuePtr(v));
|
519
|
+
copts->dump_opts.before_size = (uint8_t)len;
|
557
520
|
}
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
copts->
|
567
|
-
} else if (T_STRING == rb_type(v)) {
|
568
|
-
size_t len = RSTRING_LEN(v);
|
569
|
-
const char *str = StringValuePtr(v);
|
570
|
-
|
571
|
-
if (len != copts->create_id_len ||
|
572
|
-
0 != strcmp(copts->create_id, str)) {
|
573
|
-
copts->create_id = ALLOC_N(char, len + 1);
|
574
|
-
strcpy((char*)copts->create_id, str);
|
575
|
-
copts->create_id_len = len;
|
576
|
-
}
|
577
|
-
} else {
|
578
|
-
rb_raise(rb_eArgError, ":create_id must be string.");
|
521
|
+
}
|
522
|
+
if (Qtrue == rb_funcall(ropts, has_key_id, 1, object_nl_sym)) {
|
523
|
+
if (Qnil == (v = rb_hash_lookup(ropts, object_nl_sym))) {
|
524
|
+
copts->dump_opts.hash_size = 0;
|
525
|
+
*copts->dump_opts.hash_nl = '\0';
|
526
|
+
} else {
|
527
|
+
rb_check_type(v, T_STRING);
|
528
|
+
if (sizeof(copts->dump_opts.hash_nl) <= (len = RSTRING_LEN(v))) {
|
529
|
+
rb_raise(rb_eArgError, "object_nl string is limited to %lu characters.", sizeof(copts->dump_opts.hash_nl));
|
579
530
|
}
|
531
|
+
strcpy(copts->dump_opts.hash_nl, StringValuePtr(v));
|
532
|
+
copts->dump_opts.hash_size = (uint8_t)len;
|
580
533
|
}
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
534
|
+
}
|
535
|
+
if (Qtrue == rb_funcall(ropts, has_key_id, 1, array_nl_sym)) {
|
536
|
+
if (Qnil == (v = rb_hash_lookup(ropts, array_nl_sym))) {
|
537
|
+
copts->dump_opts.array_size = 0;
|
538
|
+
*copts->dump_opts.array_nl = '\0';
|
539
|
+
} else {
|
540
|
+
rb_check_type(v, T_STRING);
|
541
|
+
if (sizeof(copts->dump_opts.array_nl) <= (len = RSTRING_LEN(v))) {
|
542
|
+
rb_raise(rb_eArgError, "array_nl string is limited to %lu characters.", sizeof(copts->dump_opts.array_nl));
|
590
543
|
}
|
591
|
-
|
592
|
-
|
593
|
-
v = rb_hash_lookup(ropts, ascii_only_sym);
|
594
|
-
if (Qtrue == v) {
|
595
|
-
copts->escape_mode = ASCIIEsc;
|
596
|
-
} else if (Qfalse == v) {
|
597
|
-
copts->escape_mode = JSONEsc;
|
544
|
+
strcpy(copts->dump_opts.array_nl, StringValuePtr(v));
|
545
|
+
copts->dump_opts.array_size = (uint8_t)len;
|
598
546
|
}
|
599
547
|
}
|
548
|
+
copts->dump_opts.use = (0 < copts->dump_opts.indent_size ||
|
549
|
+
0 < copts->dump_opts.after_size ||
|
550
|
+
0 < copts->dump_opts.before_size ||
|
551
|
+
0 < copts->dump_opts.hash_size ||
|
552
|
+
0 < copts->dump_opts.array_size);
|
553
|
+
// This is here only for backwards compatibility with the original Oj.
|
554
|
+
v = rb_hash_lookup(ropts, ascii_only_sym);
|
555
|
+
if (Qtrue == v) {
|
556
|
+
copts->escape_mode = ASCIIEsc;
|
557
|
+
} else if (Qfalse == v) {
|
558
|
+
copts->escape_mode = JSONEsc;
|
559
|
+
}
|
600
560
|
}
|
601
561
|
|
602
562
|
/* Document-method: strict_load
|
@@ -1665,53 +1625,57 @@ mimic_generate_core(int argc, VALUE *argv, Options copts) {
|
|
1665
1625
|
out.end = buf + sizeof(buf) - 10;
|
1666
1626
|
out.allocated = 0;
|
1667
1627
|
if (2 == argc && Qnil != argv[1]) {
|
1668
|
-
|
1669
|
-
VALUE
|
1670
|
-
|
1628
|
+
VALUE ropts = argv[1];
|
1629
|
+
VALUE v;
|
1630
|
+
size_t len;
|
1671
1631
|
|
1672
|
-
memset(&dump_opts, 0, sizeof(dump_opts)); // may not be needed
|
1673
1632
|
if (T_HASH != rb_type(ropts)) {
|
1674
1633
|
rb_raise(rb_eArgError, "options must be a hash.");
|
1675
1634
|
}
|
1676
|
-
if (Qnil != (v = rb_hash_lookup(ropts, indent_sym))) {
|
1635
|
+
if (Qnil != (v = rb_hash_lookup(ropts, indent_sym))) { // TBD fixnum also ok
|
1677
1636
|
rb_check_type(v, T_STRING);
|
1678
|
-
if (
|
1679
|
-
copts->dump_opts
|
1637
|
+
if (sizeof(copts->dump_opts.indent_str) <= (len = RSTRING_LEN(v))) {
|
1638
|
+
rb_raise(rb_eArgError, "indent string is limited to %lu characters.", sizeof(copts->dump_opts.indent_str));
|
1680
1639
|
}
|
1681
|
-
copts->dump_opts
|
1682
|
-
copts->dump_opts
|
1640
|
+
strcpy(copts->dump_opts.indent_str, StringValuePtr(v));
|
1641
|
+
copts->dump_opts.indent_size = (uint8_t)len;
|
1642
|
+
copts->dump_opts.use = true;
|
1683
1643
|
}
|
1684
1644
|
if (Qnil != (v = rb_hash_lookup(ropts, space_sym))) {
|
1685
1645
|
rb_check_type(v, T_STRING);
|
1686
|
-
if (
|
1687
|
-
copts->dump_opts
|
1646
|
+
if (sizeof(copts->dump_opts.after_sep) <= (len = RSTRING_LEN(v))) {
|
1647
|
+
rb_raise(rb_eArgError, "space string is limited to %lu characters.", sizeof(copts->dump_opts.after_sep));
|
1688
1648
|
}
|
1689
|
-
copts->dump_opts
|
1690
|
-
copts->dump_opts
|
1649
|
+
strcpy(copts->dump_opts.after_sep, StringValuePtr(v));
|
1650
|
+
copts->dump_opts.after_size = (uint8_t)len;
|
1651
|
+
copts->dump_opts.use = true;
|
1691
1652
|
}
|
1692
1653
|
if (Qnil != (v = rb_hash_lookup(ropts, space_before_sym))) {
|
1693
1654
|
rb_check_type(v, T_STRING);
|
1694
|
-
if (
|
1695
|
-
copts->dump_opts
|
1655
|
+
if (sizeof(copts->dump_opts.before_sep) <= (len = RSTRING_LEN(v))) {
|
1656
|
+
rb_raise(rb_eArgError, "space_before string is limited to %lu characters.", sizeof(copts->dump_opts.before_sep));
|
1696
1657
|
}
|
1697
|
-
copts->dump_opts
|
1698
|
-
copts->dump_opts
|
1658
|
+
strcpy(copts->dump_opts.before_sep, StringValuePtr(v));
|
1659
|
+
copts->dump_opts.before_size = (uint8_t)len;
|
1660
|
+
copts->dump_opts.use = true;
|
1699
1661
|
}
|
1700
1662
|
if (Qnil != (v = rb_hash_lookup(ropts, object_nl_sym))) {
|
1701
1663
|
rb_check_type(v, T_STRING);
|
1702
|
-
if (
|
1703
|
-
copts->dump_opts
|
1664
|
+
if (sizeof(copts->dump_opts.hash_nl) <= (len = RSTRING_LEN(v))) {
|
1665
|
+
rb_raise(rb_eArgError, "object_nl string is limited to %lu characters.", sizeof(copts->dump_opts.hash_nl));
|
1704
1666
|
}
|
1705
|
-
copts->dump_opts
|
1706
|
-
copts->dump_opts
|
1667
|
+
strcpy(copts->dump_opts.hash_nl, StringValuePtr(v));
|
1668
|
+
copts->dump_opts.hash_size = (uint8_t)len;
|
1669
|
+
copts->dump_opts.use = true;
|
1707
1670
|
}
|
1708
1671
|
if (Qnil != (v = rb_hash_lookup(ropts, array_nl_sym))) {
|
1709
1672
|
rb_check_type(v, T_STRING);
|
1710
|
-
if (
|
1711
|
-
copts->dump_opts
|
1673
|
+
if (sizeof(copts->dump_opts.array_nl) <= (len = RSTRING_LEN(v))) {
|
1674
|
+
rb_raise(rb_eArgError, "array_nl string is limited to %lu characters.", sizeof(copts->dump_opts.array_nl));
|
1712
1675
|
}
|
1713
|
-
copts->dump_opts
|
1714
|
-
copts->dump_opts
|
1676
|
+
strcpy(copts->dump_opts.array_nl, StringValuePtr(v));
|
1677
|
+
copts->dump_opts.array_size = (uint8_t)len;
|
1678
|
+
copts->dump_opts.use = true;
|
1715
1679
|
}
|
1716
1680
|
// :allow_nan is not supported as Oj always allows_nan
|
1717
1681
|
// :max_nesting is always set to 100
|
@@ -1738,19 +1702,18 @@ mimic_generate(int argc, VALUE *argv, VALUE self) {
|
|
1738
1702
|
static VALUE
|
1739
1703
|
mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
|
1740
1704
|
struct _Options copts = oj_default_options;
|
1741
|
-
|
1742
|
-
|
1743
|
-
dump_opts.
|
1744
|
-
dump_opts.
|
1745
|
-
dump_opts.
|
1746
|
-
dump_opts.
|
1747
|
-
dump_opts.
|
1748
|
-
dump_opts.
|
1749
|
-
dump_opts.
|
1750
|
-
dump_opts.
|
1751
|
-
dump_opts.
|
1752
|
-
dump_opts.
|
1753
|
-
copts.dump_opts = &dump_opts;
|
1705
|
+
|
1706
|
+
strcpy(copts.dump_opts.indent_str, " ");
|
1707
|
+
copts.dump_opts.indent_size = (uint8_t)strlen(copts.dump_opts.indent_str);
|
1708
|
+
strcpy(copts.dump_opts.before_sep, " ");
|
1709
|
+
copts.dump_opts.before_size = (uint8_t)strlen(copts.dump_opts.before_sep);
|
1710
|
+
strcpy(copts.dump_opts.after_sep, " ");
|
1711
|
+
copts.dump_opts.after_size = (uint8_t)strlen(copts.dump_opts.after_sep);
|
1712
|
+
strcpy(copts.dump_opts.hash_nl, "\n");
|
1713
|
+
copts.dump_opts.hash_size = (uint8_t)strlen(copts.dump_opts.hash_nl);
|
1714
|
+
strcpy(copts.dump_opts.array_nl, "\n");
|
1715
|
+
copts.dump_opts.array_size = (uint8_t)strlen(copts.dump_opts.array_nl);
|
1716
|
+
copts.dump_opts.use = true;
|
1754
1717
|
|
1755
1718
|
return mimic_generate_core(argc, argv, &copts);
|
1756
1719
|
}
|
@@ -1833,26 +1796,38 @@ mimic_create_id(VALUE self, VALUE id) {
|
|
1833
1796
|
}
|
1834
1797
|
|
1835
1798
|
static struct _Options mimic_object_to_json_options = {
|
1836
|
-
0,
|
1837
|
-
No,
|
1838
|
-
No,
|
1839
|
-
No,
|
1840
|
-
JSONEsc,
|
1841
|
-
CompatMode,
|
1842
|
-
No,
|
1843
|
-
RubyTime,
|
1844
|
-
No,
|
1845
|
-
FloatDec,
|
1846
|
-
No,
|
1847
|
-
Yes,
|
1848
|
-
Yes,
|
1849
|
-
Yes,
|
1850
|
-
json_class,
|
1851
|
-
10,
|
1852
|
-
9,
|
1853
|
-
|
1854
|
-
|
1855
|
-
|
1799
|
+
0, // indent
|
1800
|
+
No, // circular
|
1801
|
+
No, // auto_define
|
1802
|
+
No, // sym_key
|
1803
|
+
JSONEsc, // escape_mode
|
1804
|
+
CompatMode, // mode
|
1805
|
+
No, // class_cache
|
1806
|
+
RubyTime, // time_format
|
1807
|
+
No, // bigdec_as_num
|
1808
|
+
FloatDec, // bigdec_load
|
1809
|
+
No, // to_json
|
1810
|
+
Yes, // nilnil
|
1811
|
+
Yes, // allow_gc
|
1812
|
+
Yes, // quirks_mode
|
1813
|
+
json_class, // create_id
|
1814
|
+
10, // create_id_len
|
1815
|
+
9, // sec_prec
|
1816
|
+
15, // float_prec
|
1817
|
+
"%0.15g", // float_fmt
|
1818
|
+
{ // dump_opts
|
1819
|
+
false, //use
|
1820
|
+
"", // indent
|
1821
|
+
"", // before_sep
|
1822
|
+
"", // after_sep
|
1823
|
+
"", // hash_nl
|
1824
|
+
"", // array_nl
|
1825
|
+
0, // indent_size
|
1826
|
+
0, // before_size
|
1827
|
+
0, // after_size
|
1828
|
+
0, // hash_size
|
1829
|
+
0, // array_size
|
1830
|
+
}
|
1856
1831
|
};
|
1857
1832
|
|
1858
1833
|
static VALUE
|
@@ -1961,11 +1936,7 @@ define_mimic_json(int argc, VALUE *argv, VALUE self) {
|
|
1961
1936
|
|
1962
1937
|
rb_gv_set("$VERBOSE", dummy);
|
1963
1938
|
|
1964
|
-
array_nl_sym = ID2SYM(rb_intern("array_nl")); rb_gc_register_address(&array_nl_sym);
|
1965
1939
|
create_additions_sym = ID2SYM(rb_intern("create_additions")); rb_gc_register_address(&create_additions_sym);
|
1966
|
-
object_nl_sym = ID2SYM(rb_intern("object_nl")); rb_gc_register_address(&object_nl_sym);
|
1967
|
-
space_before_sym = ID2SYM(rb_intern("space_before")); rb_gc_register_address(&space_before_sym);
|
1968
|
-
space_sym = ID2SYM(rb_intern("space")); rb_gc_register_address(&space_sym);
|
1969
1940
|
symbolize_names_sym = ID2SYM(rb_intern("symbolize_names")); rb_gc_register_address(&symbolize_names_sym);
|
1970
1941
|
|
1971
1942
|
if (rb_const_defined_at(mimic, rb_intern("ParserError"))) {
|
@@ -2121,6 +2092,7 @@ void Init_oj() {
|
|
2121
2092
|
oj_utc_offset_id = rb_intern("utc_offset");
|
2122
2093
|
oj_utcq_id = rb_intern("utc?");
|
2123
2094
|
oj_write_id = rb_intern("write");
|
2095
|
+
has_key_id = rb_intern("has_key?");
|
2124
2096
|
|
2125
2097
|
rb_require("oj/bag");
|
2126
2098
|
rb_require("oj/error");
|
@@ -2141,6 +2113,7 @@ void Init_oj() {
|
|
2141
2113
|
ascii_sym = ID2SYM(rb_intern("ascii")); rb_gc_register_address(&ascii_sym);
|
2142
2114
|
auto_define_sym = ID2SYM(rb_intern("auto_define")); rb_gc_register_address(&auto_define_sym);
|
2143
2115
|
auto_sym = ID2SYM(rb_intern("auto")); rb_gc_register_address(&auto_sym);
|
2116
|
+
array_nl_sym = ID2SYM(rb_intern("array_nl")); rb_gc_register_address(&array_nl_sym);
|
2144
2117
|
bigdecimal_as_decimal_sym = ID2SYM(rb_intern("bigdecimal_as_decimal"));rb_gc_register_address(&bigdecimal_as_decimal_sym);
|
2145
2118
|
bigdecimal_load_sym = ID2SYM(rb_intern("bigdecimal_load"));rb_gc_register_address(&bigdecimal_load_sym);
|
2146
2119
|
bigdecimal_sym = ID2SYM(rb_intern("bigdecimal")); rb_gc_register_address(&bigdecimal_sym);
|
@@ -2157,10 +2130,13 @@ void Init_oj() {
|
|
2157
2130
|
newline_sym = ID2SYM(rb_intern("newline")); rb_gc_register_address(&newline_sym);
|
2158
2131
|
nilnil_sym = ID2SYM(rb_intern("nilnil")); rb_gc_register_address(&nilnil_sym);
|
2159
2132
|
null_sym = ID2SYM(rb_intern("null")); rb_gc_register_address(&null_sym);
|
2133
|
+
object_nl_sym = ID2SYM(rb_intern("object_nl")); rb_gc_register_address(&object_nl_sym);
|
2160
2134
|
object_sym = ID2SYM(rb_intern("object")); rb_gc_register_address(&object_sym);
|
2161
2135
|
quirks_mode_sym = ID2SYM(rb_intern("quirks_mode")); rb_gc_register_address(&quirks_mode_sym);
|
2162
2136
|
ruby_sym = ID2SYM(rb_intern("ruby")); rb_gc_register_address(&ruby_sym);
|
2163
2137
|
sec_prec_sym = ID2SYM(rb_intern("second_precision"));rb_gc_register_address(&sec_prec_sym);
|
2138
|
+
space_before_sym = ID2SYM(rb_intern("space_before"));rb_gc_register_address(&space_before_sym);
|
2139
|
+
space_sym = ID2SYM(rb_intern("space")); rb_gc_register_address(&space_sym);
|
2164
2140
|
strict_sym = ID2SYM(rb_intern("strict")); rb_gc_register_address(&strict_sym);
|
2165
2141
|
symbol_keys_sym = ID2SYM(rb_intern("symbol_keys")); rb_gc_register_address(&symbol_keys_sym);
|
2166
2142
|
time_format_sym = ID2SYM(rb_intern("time_format")); rb_gc_register_address(&time_format_sym);
|