1
1
/* vim: set cin et sw=4 ts=4: */
9
#define check_max_nesting(state, depth) do { \
10
long current_nesting = 1 + depth; \
11
if (state->max_nesting != 0 && current_nesting > state->max_nesting) \
12
rb_raise(eNestingError, "nesting of %ld is too deep", current_nesting); \
8
15
static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
9
16
mHash, mArray, mInteger, mFloat, mString, mString_Extend,
10
17
mTrueClass, mFalseClass, mNilClass, eGeneratorError,
11
eCircularDatastructure;
18
eCircularDatastructure, eNestingError;
13
20
static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
14
i_object_nl, i_array_nl, i_check_circular, i_pack, i_unpack,
15
i_create_id, i_extend;
21
i_object_nl, i_array_nl, i_check_circular, i_max_nesting,
22
i_allow_nan, i_pack, i_unpack, i_create_id, i_extend;
17
24
typedef struct JSON_Generator_StateStruct {
131
140
rb_scan_args(argc, argv, "02", &Vstate, &Vdepth);
132
141
depth = NIL_P(Vdepth) ? 0 : FIX2LONG(Vdepth);
133
142
if (NIL_P(Vstate)) {
134
long len = RHASH(self)->tbl->num_entries;
143
long len = RHASH_SIZE(self);
135
144
result = rb_str_buf_new(len);
136
145
rb_str_buf_cat2(result, "{");
137
146
rb_hash_foreach(self, hash_to_json_i, result);
138
147
rb_str_buf_cat2(result, "}");
140
149
GET_STATE(Vstate);
150
check_max_nesting(state, depth);
141
151
if (state->check_circular) {
142
152
VALUE self_id = rb_obj_id(self);
143
153
if (RTEST(rb_hash_aref(state->seen, self_id))) {
260
274
static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
262
return rb_funcall(self, i_to_s, 0);
276
JSON_Generator_State *state = NULL;
277
VALUE Vstate, rest, tmp;
278
double value = RFLOAT(self)->value;
279
rb_scan_args(argc, argv, "01*", &Vstate, &rest);
280
if (!NIL_P(Vstate)) Data_Get_Struct(Vstate, JSON_Generator_State, state);
282
if (!state || state->allow_nan) {
283
return rb_funcall(self, i_to_s, 0);
285
tmp = rb_funcall(self, i_to_s, 0);
286
rb_raise(eGeneratorError, "%s not allowed in JSON", StringValueCStr(tmp));
288
} else if (isnan(value)) {
289
if (!state || state->allow_nan) {
290
return rb_funcall(self, i_to_s, 0);
292
tmp = rb_funcall(self, i_to_s, 0);
293
rb_raise(eGeneratorError, "%s not allowed in JSON", StringValueCStr(tmp));
296
return rb_funcall(self, i_to_s, 0);
442
* call-seq: configure(opts)
444
* Configure this State instance with the Hash _opts_, and return
447
static inline VALUE cState_configure(VALUE self, VALUE opts)
451
tmp = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
452
if (NIL_P(tmp)) tmp = rb_convert_type(opts, T_HASH, "Hash", "to_h");
454
rb_raise(rb_eArgError, "opts has to be hash like or convertable into a hash");
457
tmp = rb_hash_aref(opts, ID2SYM(i_indent));
459
Check_Type(tmp, T_STRING);
462
tmp = rb_hash_aref(opts, ID2SYM(i_space));
464
Check_Type(tmp, T_STRING);
467
tmp = rb_hash_aref(opts, ID2SYM(i_space_before));
469
Check_Type(tmp, T_STRING);
470
state->space_before = tmp;
472
tmp = rb_hash_aref(opts, ID2SYM(i_array_nl));
474
Check_Type(tmp, T_STRING);
475
state->array_nl = tmp;
477
tmp = rb_hash_aref(opts, ID2SYM(i_object_nl));
479
Check_Type(tmp, T_STRING);
480
state->object_nl = tmp;
482
tmp = ID2SYM(i_check_circular);
483
if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
484
tmp = rb_hash_aref(opts, ID2SYM(i_check_circular));
485
state->check_circular = RTEST(tmp);
487
state->check_circular = 1;
489
tmp = ID2SYM(i_max_nesting);
490
state->max_nesting = 19;
491
if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
492
VALUE max_nesting = rb_hash_aref(opts, tmp);
493
if (RTEST(max_nesting)) {
494
Check_Type(max_nesting, T_FIXNUM);
495
state->max_nesting = FIX2LONG(max_nesting);
497
state->max_nesting = 0;
500
tmp = rb_hash_aref(opts, ID2SYM(i_allow_nan));
501
state->allow_nan = RTEST(tmp);
508
* Returns the configuration instance variables as a hash, that can be
509
* passed to the configure method.
511
static VALUE cState_to_h(VALUE self)
513
VALUE result = rb_hash_new();
515
rb_hash_aset(result, ID2SYM(i_indent), state->indent);
516
rb_hash_aset(result, ID2SYM(i_space), state->space);
517
rb_hash_aset(result, ID2SYM(i_space_before), state->space_before);
518
rb_hash_aset(result, ID2SYM(i_object_nl), state->object_nl);
519
rb_hash_aset(result, ID2SYM(i_array_nl), state->array_nl);
520
rb_hash_aset(result, ID2SYM(i_check_circular), state->check_circular ? Qtrue : Qfalse);
521
rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
522
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
407
528
* call-seq: new(opts = {})
409
530
* Instantiates a new State object, configured by _opts_.
417
538
* * *array_nl*: a string that is put at the end of a JSON array (default: ''),
418
539
* * *check_circular*: true if checking for circular data structures
419
540
* should be done, false (the default) otherwise.
541
* * *allow_nan*: true if NaN, Infinity, and -Infinity should be
542
* generated, otherwise an exception is thrown, if these values are
543
* encountered. This options defaults to false.
421
545
static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
426
550
rb_scan_args(argc, argv, "01", &opts);
551
state->indent = rb_str_new2("");
552
state->space = rb_str_new2("");
553
state->space_before = rb_str_new2("");
554
state->array_nl = rb_str_new2("");
555
state->object_nl = rb_str_new2("");
427
556
if (NIL_P(opts)) {
428
state->indent = rb_str_new2("");
429
state->space = rb_str_new2("");
430
state->space_before = rb_str_new2("");
431
state->array_nl = rb_str_new2("");
432
state->object_nl = rb_str_new2("");
433
state->check_circular = 0;
557
state->check_circular = 1;
558
state->allow_nan = 0;
559
state->max_nesting = 19;
436
opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
437
tmp = rb_hash_aref(opts, ID2SYM(i_indent));
439
Check_Type(tmp, T_STRING);
442
state->indent = rb_str_new2("");
444
tmp = rb_hash_aref(opts, ID2SYM(i_space));
446
Check_Type(tmp, T_STRING);
449
state->space = rb_str_new2("");
451
tmp = rb_hash_aref(opts, ID2SYM(i_space_before));
453
Check_Type(tmp, T_STRING);
454
state->space_before = tmp;
456
state->space_before = rb_str_new2("");
458
tmp = rb_hash_aref(opts, ID2SYM(i_array_nl));
460
Check_Type(tmp, T_STRING);
461
state->array_nl = tmp;
463
state->array_nl = rb_str_new2("");
465
tmp = rb_hash_aref(opts, ID2SYM(i_object_nl));
467
Check_Type(tmp, T_STRING);
468
state->object_nl = tmp;
470
state->object_nl = rb_str_new2("");
472
tmp = rb_hash_aref(opts, ID2SYM(i_check_circular));
473
state->check_circular = RTEST(tmp);
561
cState_configure(self, opts);
475
563
state->seen = rb_hash_new();
476
564
state->memo = Qnil;
719
* call-seq: max_nesting
721
* This integer returns the maximum level of data structure nesting in
722
* the generated JSON, max_nesting = 0 if no maximum is checked.
724
static VALUE cState_max_nesting(VALUE self)
727
return LONG2FIX(state->max_nesting);
731
* call-seq: max_nesting=(depth)
733
* This sets the maximum level of data structure nesting in the generated JSON
734
* to the integer depth, max_nesting = 0 if no maximum should be checked.
736
static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
739
Check_Type(depth, T_FIXNUM);
740
state->max_nesting = FIX2LONG(depth);
745
* call-seq: allow_nan?
747
* Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
750
static VALUE cState_allow_nan_p(VALUE self)
753
return state->allow_nan ? Qtrue : Qfalse;
631
757
* call-seq: seen?(object)
633
759
* Returns _true_, if _object_ was already seen during this generating run.
668
794
mGenerator = rb_define_module_under(mExt, "Generator");
669
795
eGeneratorError = rb_path2class("JSON::GeneratorError");
670
796
eCircularDatastructure = rb_path2class("JSON::CircularDatastructure");
797
eNestingError = rb_path2class("JSON::NestingError");
671
798
cState = rb_define_class_under(mGenerator, "State", rb_cObject);
672
799
rb_define_alloc_func(cState, cState_s_allocate);
673
800
rb_define_singleton_method(cState, "from_state", cState_from_state_s, 1);
684
811
rb_define_method(cState, "array_nl", cState_array_nl, 0);
685
812
rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
686
813
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
814
rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
815
rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
816
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
687
817
rb_define_method(cState, "seen?", cState_seen_p, 1);
688
818
rb_define_method(cState, "remember", cState_remember, 1);
689
819
rb_define_method(cState, "forget", cState_forget, 1);
820
rb_define_method(cState, "configure", cState_configure, 1);
821
rb_define_method(cState, "to_h", cState_to_h, 0);
690
823
mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
691
824
mObject = rb_define_module_under(mGeneratorMethods, "Object");
692
825
rb_define_method(mObject, "to_json", mObject_to_json, -1);