json 1.1.0-mswin32 → 1.1.1-mswin32
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.
Potentially problematic release.
This version of json might be problematic. Click here for more details.
- data/CHANGES +18 -0
- data/Rakefile +5 -5
- data/VERSION +1 -1
- data/benchmarks/benchmark_generator.rb +5 -1
- data/benchmarks/benchmark_parser.rb +5 -1
- data/bin/edit_json.rb +11 -11
- data/ext/json/ext/generator.so +0 -0
- data/ext/json/ext/generator/extconf.rb +2 -2
- data/ext/json/ext/generator/generator.c +185 -50
- data/ext/json/ext/parser.so +0 -0
- data/ext/json/ext/parser/extconf.rb +2 -2
- data/ext/json/ext/parser/parser.c +246 -117
- data/ext/json/ext/parser/parser.rl +54 -6
- data/lib/json.rb +23 -0
- data/lib/json/add/core.rb +119 -0
- data/lib/json/add/rails.rb +52 -0
- data/lib/json/common.rb +174 -23
- data/lib/json/editor.rb +12 -14
- data/lib/json/pure/generator.rb +83 -10
- data/lib/json/pure/parser.rb +15 -1
- data/lib/json/version.rb +1 -1
- data/tests/fixtures/fail18.json +1 -1
- data/tests/test_json.rb +51 -12
- data/tests/test_json_addition.rb +34 -3
- data/tests/test_json_fixtures.rb +2 -2
- data/tests/test_json_generate.rb +21 -2
- data/tests/test_json_unicode.rb +4 -1
- data/tools/fuzz.rb +2 -1
- metadata +5 -2
    
        data/CHANGES
    CHANGED
    
    | @@ -1,3 +1,21 @@ | |
| 1 | 
            +
            2007-07-06 (1.1.1)
         | 
| 2 | 
            +
              * Yui NARUSE <naruse@airemix.com> sent some patches to fix tests for Ruby
         | 
| 3 | 
            +
                1.9. I applied them and adapted some of them a bit to run both on 1.8 and
         | 
| 4 | 
            +
                1.9.
         | 
| 5 | 
            +
              * Introduced a JSON.parse! method without depth checking for people who like
         | 
| 6 | 
            +
                danger.
         | 
| 7 | 
            +
              * Made generate and pretty_generate methods configurable by an options hash.
         | 
| 8 | 
            +
              * Added :allow_nan option to parser and generator in order to handle NaN,
         | 
| 9 | 
            +
                Infinity, and -Infinity correctly - if requested. Floats, which aren't numbers,
         | 
| 10 | 
            +
                aren't valid JSON according to RFC4627, so by default an exception will be
         | 
| 11 | 
            +
                raised if any of these symbols are encountered. Thanks to Andrea Censi
         | 
| 12 | 
            +
                <andrea.censi@dis.uniroma1.it> for his hint about this.
         | 
| 13 | 
            +
              * Fixed some more tests for Ruby 1.9.
         | 
| 14 | 
            +
              * Implemented dump/load interface of Marshal as suggested in ruby-core:11405
         | 
| 15 | 
            +
                by murphy <murphy@rubychan.de>.
         | 
| 16 | 
            +
              * Implemented the max_nesting feature for generate methods, too.
         | 
| 17 | 
            +
              * Added some implementations for ruby core's custom objects for
         | 
| 18 | 
            +
                serialisation/deserialisation purposes.
         | 
| 1 19 | 
             
            2007-05-21 (1.1.0)
         | 
| 2 20 | 
             
              * Implemented max_nesting feature for parser to avoid stack overflows for
         | 
| 3 21 | 
             
                data from untrusted sources. If you trust the source, you can disable it
         | 
    
        data/Rakefile
    CHANGED
    
    | @@ -124,12 +124,12 @@ end | |
| 124 124 |  | 
| 125 125 | 
             
            desc "Benchmarking parser (pure)"
         | 
| 126 126 | 
             
            task :benchmark_parser_pure do
         | 
| 127 | 
            -
              ruby '-I lib benchmarks/benchmark_parser.rb'
         | 
| 127 | 
            +
              ruby '-I lib benchmarks/benchmark_parser.rb pure'
         | 
| 128 128 | 
             
            end
         | 
| 129 129 |  | 
| 130 130 | 
             
            desc "Benchmarking generator (pure)"
         | 
| 131 131 | 
             
            task :benchmark_generator_pure do
         | 
| 132 | 
            -
              ruby '-I lib benchmarks/benchmark_generator.rb'
         | 
| 132 | 
            +
              ruby '-I lib benchmarks/benchmark_generator.rb pure'
         | 
| 133 133 | 
             
              ruby 'benchmarks/benchmark_rails.rb'
         | 
| 134 134 | 
             
            end
         | 
| 135 135 |  | 
| @@ -138,12 +138,12 @@ task :benchmark_pure => [ :benchmark_parser_pure, :benchmark_generator_pure ] | |
| 138 138 |  | 
| 139 139 | 
             
            desc "Benchmarking parser (extension)"
         | 
| 140 140 | 
             
            task :benchmark_parser_ext => :compile do
         | 
| 141 | 
            -
              ruby '-I ext:lib benchmarks/benchmark_parser.rb'
         | 
| 141 | 
            +
              ruby '-I ext:lib benchmarks/benchmark_parser.rb ext'
         | 
| 142 142 | 
             
            end
         | 
| 143 143 |  | 
| 144 144 | 
             
            desc "Benchmarking generator (extension)"
         | 
| 145 145 | 
             
            task :benchmark_generator_ext => :compile do
         | 
| 146 | 
            -
              ruby '-I ext:lib benchmarks/benchmark_generator.rb'
         | 
| 146 | 
            +
              ruby '-I ext:lib benchmarks/benchmark_generator.rb ext'
         | 
| 147 147 | 
             
              ruby 'benchmarks/benchmark_rails.rb'
         | 
| 148 148 | 
             
            end
         | 
| 149 149 |  | 
| @@ -164,7 +164,7 @@ end | |
| 164 164 |  | 
| 165 165 | 
             
            desc "Create RDOC documentation"
         | 
| 166 166 | 
             
            task :doc => [ :version, EXT_PARSER_SRC ] do
         | 
| 167 | 
            -
              sh "rdoc -m JSON - | 
| 167 | 
            +
              sh "rdoc -m JSON -S -o doc #{FileList['lib/**/*.rb']} #{EXT_PARSER_SRC} #{EXT_GENERATOR_SRC}"
         | 
| 168 168 | 
             
            end
         | 
| 169 169 |  | 
| 170 170 | 
             
            spec_pure = Gem::Specification.new do |s|
         | 
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            1.1. | 
| 1 | 
            +
            1.1.1
         | 
    
        data/bin/edit_json.rb
    CHANGED
    
    | @@ -1,11 +1,11 @@ | |
| 1 | 
            -
            #!/usr/bin/env ruby
         | 
| 2 | 
            -
            $KCODE = 'U'
         | 
| 3 | 
            -
            require 'json/editor'
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            filename, encoding = ARGV
         | 
| 6 | 
            -
            JSON::Editor.start(encoding) do |window|
         | 
| 7 | 
            -
              if filename | 
| 8 | 
            -
                window.file_open(filename)
         | 
| 9 | 
            -
              end
         | 
| 10 | 
            -
            end
         | 
| 11 | 
            -
              # vim: set et sw=2 ts=2:
         | 
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
            $KCODE = 'U'
         | 
| 3 | 
            +
            require 'json/editor'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            filename, encoding = ARGV
         | 
| 6 | 
            +
            JSON::Editor.start(encoding) do |window|
         | 
| 7 | 
            +
              if filename
         | 
| 8 | 
            +
                window.file_open(filename)
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
            end
         | 
| 11 | 
            +
              # vim: set et sw=2 ts=2:
         | 
    
        data/ext/json/ext/generator.so
    CHANGED
    
    | Binary file | 
| @@ -4,15 +4,22 @@ | |
| 4 4 | 
             
            #include "ruby.h"
         | 
| 5 5 | 
             
            #include "st.h"
         | 
| 6 6 | 
             
            #include "unicode.h"
         | 
| 7 | 
            +
            #include <math.h>
         | 
| 8 | 
            +
             | 
| 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 %u is too deep", current_nesting); \
         | 
| 13 | 
            +
            } while (0);
         | 
| 7 14 |  | 
| 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;
         | 
| 12 19 |  | 
| 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,  | 
| 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;
         | 
| 16 23 |  | 
| 17 24 | 
             
            typedef struct JSON_Generator_StateStruct {
         | 
| 18 25 | 
             
                VALUE indent;
         | 
| @@ -24,7 +31,9 @@ typedef struct JSON_Generator_StateStruct { | |
| 24 31 | 
             
                VALUE seen;
         | 
| 25 32 | 
             
                VALUE memo;
         | 
| 26 33 | 
             
                VALUE depth;
         | 
| 34 | 
            +
                long max_nesting;
         | 
| 27 35 | 
             
                int flag;
         | 
| 36 | 
            +
                int allow_nan;
         | 
| 28 37 | 
             
            } JSON_Generator_State;
         | 
| 29 38 |  | 
| 30 39 | 
             
            #define GET_STATE(self)                       \
         | 
| @@ -138,6 +147,7 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self) | |
| 138 147 | 
             
                    rb_str_buf_cat2(result, "}");
         | 
| 139 148 | 
             
                } else {
         | 
| 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))) {
         | 
| @@ -162,6 +172,7 @@ inline static VALUE mArray_json_transfrom(VALUE self, VALUE Vstate, VALUE Vdepth | |
| 162 172 | 
             
                VALUE delim = rb_str_new2(",");
         | 
| 163 173 | 
             
                GET_STATE(Vstate);
         | 
| 164 174 |  | 
| 175 | 
            +
                check_max_nesting(state, depth);
         | 
| 165 176 | 
             
                if (state->check_circular) {
         | 
| 166 177 | 
             
                    VALUE self_id = rb_obj_id(self);
         | 
| 167 178 | 
             
                    rb_hash_aset(state->seen, self_id, Qtrue);
         | 
| @@ -170,6 +181,7 @@ inline static VALUE mArray_json_transfrom(VALUE self, VALUE Vstate, VALUE Vdepth | |
| 170 181 | 
             
                    shift = rb_str_times(state->indent, LONG2FIX(depth + 1));
         | 
| 171 182 |  | 
| 172 183 | 
             
                    rb_str_buf_cat2(result, "[");
         | 
| 184 | 
            +
                    OBJ_INFECT(result, self);
         | 
| 173 185 | 
             
                    rb_str_buf_append(result, state->array_nl);
         | 
| 174 186 | 
             
                    for (i = 0;  i < len; i++) {
         | 
| 175 187 | 
             
                        VALUE element = RARRAY_PTR(self)[i];
         | 
| @@ -190,6 +202,7 @@ inline static VALUE mArray_json_transfrom(VALUE self, VALUE Vstate, VALUE Vdepth | |
| 190 202 | 
             
                    rb_hash_delete(state->seen, self_id);
         | 
| 191 203 | 
             
                } else {
         | 
| 192 204 | 
             
                    result = rb_str_buf_new(len);
         | 
| 205 | 
            +
                    OBJ_INFECT(result, self);
         | 
| 193 206 | 
             
                    if (RSTRING_LEN(state->array_nl)) rb_str_append(delim, state->array_nl);
         | 
| 194 207 | 
             
                    shift = rb_str_times(state->indent, LONG2FIX(depth + 1));
         | 
| 195 208 |  | 
| @@ -228,6 +241,7 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) { | |
| 228 241 | 
             
                    long i, len = RARRAY_LEN(self);
         | 
| 229 242 | 
             
                    result = rb_str_buf_new(2 + 2 * len);
         | 
| 230 243 | 
             
                    rb_str_buf_cat2(result, "[");
         | 
| 244 | 
            +
                    OBJ_INFECT(result, self);
         | 
| 231 245 | 
             
                    for (i = 0;  i < len; i++) {
         | 
| 232 246 | 
             
                        VALUE element = RARRAY_PTR(self)[i];
         | 
| 233 247 | 
             
                        OBJ_INFECT(result, element);
         | 
| @@ -259,7 +273,28 @@ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self) | |
| 259 273 | 
             
             */
         | 
| 260 274 | 
             
            static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
         | 
| 261 275 | 
             
            {
         | 
| 262 | 
            -
                 | 
| 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);
         | 
| 281 | 
            +
                if (isinf(value)) {
         | 
| 282 | 
            +
                    if (!state || state->allow_nan) {
         | 
| 283 | 
            +
                        return rb_funcall(self, i_to_s, 0);
         | 
| 284 | 
            +
                    } else {
         | 
| 285 | 
            +
                        tmp = rb_funcall(self, i_to_s, 0);
         | 
| 286 | 
            +
                        rb_raise(eGeneratorError, "%s not allowed in JSON", StringValueCStr(tmp));
         | 
| 287 | 
            +
                    }
         | 
| 288 | 
            +
                } else if (isnan(value)) {
         | 
| 289 | 
            +
                    if (!state || state->allow_nan) {
         | 
| 290 | 
            +
                        return rb_funcall(self, i_to_s, 0);
         | 
| 291 | 
            +
                    } else {
         | 
| 292 | 
            +
                        tmp = rb_funcall(self, i_to_s, 0);
         | 
| 293 | 
            +
                        rb_raise(eGeneratorError, "%s not allowed in JSON", StringValueCStr(tmp));
         | 
| 294 | 
            +
                    }
         | 
| 295 | 
            +
                } else {
         | 
| 296 | 
            +
                    return rb_funcall(self, i_to_s, 0);
         | 
| 297 | 
            +
                }
         | 
| 263 298 | 
             
            }
         | 
| 264 299 |  | 
| 265 300 | 
             
            /*
         | 
| @@ -403,6 +438,92 @@ static VALUE cState_s_allocate(VALUE klass) | |
| 403 438 | 
             
                return Data_Wrap_Struct(klass, State_mark, -1, state);
         | 
| 404 439 | 
             
            }
         | 
| 405 440 |  | 
| 441 | 
            +
            /*
         | 
| 442 | 
            +
             * call-seq: configure(opts)
         | 
| 443 | 
            +
             *
         | 
| 444 | 
            +
             * Configure this State instance with the Hash _opts_, and return
         | 
| 445 | 
            +
             * itself.
         | 
| 446 | 
            +
             */
         | 
| 447 | 
            +
            static inline VALUE cState_configure(VALUE self, VALUE opts)
         | 
| 448 | 
            +
            {
         | 
| 449 | 
            +
                VALUE tmp;
         | 
| 450 | 
            +
                GET_STATE(self);
         | 
| 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");
         | 
| 453 | 
            +
                if (NIL_P(tmp)) {
         | 
| 454 | 
            +
                    rb_raise(rb_eArgError, "opts has to be hash like or convertable into a hash");
         | 
| 455 | 
            +
                }
         | 
| 456 | 
            +
                opts = tmp;
         | 
| 457 | 
            +
                tmp = rb_hash_aref(opts, ID2SYM(i_indent));
         | 
| 458 | 
            +
                if (RTEST(tmp)) {
         | 
| 459 | 
            +
                    Check_Type(tmp, T_STRING);
         | 
| 460 | 
            +
                    state->indent = tmp;
         | 
| 461 | 
            +
                }
         | 
| 462 | 
            +
                tmp = rb_hash_aref(opts, ID2SYM(i_space));
         | 
| 463 | 
            +
                if (RTEST(tmp)) {
         | 
| 464 | 
            +
                    Check_Type(tmp, T_STRING);
         | 
| 465 | 
            +
                    state->space = tmp;
         | 
| 466 | 
            +
                }
         | 
| 467 | 
            +
                tmp = rb_hash_aref(opts, ID2SYM(i_space_before));
         | 
| 468 | 
            +
                if (RTEST(tmp)) {
         | 
| 469 | 
            +
                    Check_Type(tmp, T_STRING);
         | 
| 470 | 
            +
                    state->space_before = tmp;
         | 
| 471 | 
            +
                }
         | 
| 472 | 
            +
                tmp = rb_hash_aref(opts, ID2SYM(i_array_nl));
         | 
| 473 | 
            +
                if (RTEST(tmp)) {
         | 
| 474 | 
            +
                    Check_Type(tmp, T_STRING);
         | 
| 475 | 
            +
                    state->array_nl = tmp;
         | 
| 476 | 
            +
                }
         | 
| 477 | 
            +
                tmp = rb_hash_aref(opts, ID2SYM(i_object_nl));
         | 
| 478 | 
            +
                if (RTEST(tmp)) {
         | 
| 479 | 
            +
                    Check_Type(tmp, T_STRING);
         | 
| 480 | 
            +
                    state->object_nl = tmp;
         | 
| 481 | 
            +
                }
         | 
| 482 | 
            +
                tmp = ID2SYM(i_check_circular);
         | 
| 483 | 
            +
                if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {
         | 
| 484 | 
            +
                    tmp = rb_hash_aref(opts, ID2SYM(i_check_circular));
         | 
| 485 | 
            +
                    state->check_circular = RTEST(tmp);
         | 
| 486 | 
            +
                } else {
         | 
| 487 | 
            +
                    state->check_circular = 1;
         | 
| 488 | 
            +
                }
         | 
| 489 | 
            +
                tmp = ID2SYM(i_max_nesting);
         | 
| 490 | 
            +
                state->max_nesting = 19;
         | 
| 491 | 
            +
                if (st_lookup(RHASH(opts)->tbl, 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);
         | 
| 496 | 
            +
                    } else {
         | 
| 497 | 
            +
                        state->max_nesting = 0;
         | 
| 498 | 
            +
                    }
         | 
| 499 | 
            +
                }
         | 
| 500 | 
            +
                tmp = rb_hash_aref(opts, ID2SYM(i_allow_nan));
         | 
| 501 | 
            +
                state->allow_nan = RTEST(tmp);
         | 
| 502 | 
            +
                return self;
         | 
| 503 | 
            +
            }
         | 
| 504 | 
            +
             | 
| 505 | 
            +
            /*
         | 
| 506 | 
            +
             * call-seq: to_h
         | 
| 507 | 
            +
             *
         | 
| 508 | 
            +
             * Returns the configuration instance variables as a hash, that can be
         | 
| 509 | 
            +
             * passed to the configure method.
         | 
| 510 | 
            +
             */
         | 
| 511 | 
            +
            static VALUE cState_to_h(VALUE self)
         | 
| 512 | 
            +
            {
         | 
| 513 | 
            +
                VALUE result = rb_hash_new();
         | 
| 514 | 
            +
                GET_STATE(self);
         | 
| 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));
         | 
| 523 | 
            +
                return result;
         | 
| 524 | 
            +
            }
         | 
| 525 | 
            +
             | 
| 526 | 
            +
             | 
| 406 527 | 
             
            /*
         | 
| 407 528 | 
             
             * call-seq: new(opts = {})
         | 
| 408 529 | 
             
             *
         | 
| @@ -417,6 +538,9 @@ static VALUE cState_s_allocate(VALUE klass) | |
| 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.
         | 
| 420 544 | 
             
             */
         | 
| 421 545 | 
             
            static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
         | 
| 422 546 | 
             
            {
         | 
| @@ -424,53 +548,17 @@ static VALUE cState_initialize(int argc, VALUE *argv, VALUE self) | |
| 424 548 | 
             
                GET_STATE(self);
         | 
| 425 549 |  | 
| 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-> | 
| 429 | 
            -
                    state-> | 
| 430 | 
            -
                    state-> | 
| 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;
         | 
| 434 560 | 
             
                } else {
         | 
| 435 | 
            -
                     | 
| 436 | 
            -
                    opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
         | 
| 437 | 
            -
                    tmp = rb_hash_aref(opts, ID2SYM(i_indent));
         | 
| 438 | 
            -
                    if (RTEST(tmp)) {
         | 
| 439 | 
            -
                        Check_Type(tmp, T_STRING);
         | 
| 440 | 
            -
                        state->indent = tmp;
         | 
| 441 | 
            -
                    } else {
         | 
| 442 | 
            -
                        state->indent = rb_str_new2("");
         | 
| 443 | 
            -
                    }
         | 
| 444 | 
            -
                    tmp = rb_hash_aref(opts, ID2SYM(i_space));
         | 
| 445 | 
            -
                    if (RTEST(tmp)) {
         | 
| 446 | 
            -
                        Check_Type(tmp, T_STRING);
         | 
| 447 | 
            -
                        state->space = tmp;
         | 
| 448 | 
            -
                    } else {
         | 
| 449 | 
            -
                        state->space = rb_str_new2("");
         | 
| 450 | 
            -
                    }
         | 
| 451 | 
            -
                    tmp = rb_hash_aref(opts, ID2SYM(i_space_before));
         | 
| 452 | 
            -
                    if (RTEST(tmp)) {
         | 
| 453 | 
            -
                        Check_Type(tmp, T_STRING);
         | 
| 454 | 
            -
                        state->space_before = tmp;
         | 
| 455 | 
            -
                    } else {
         | 
| 456 | 
            -
                        state->space_before = rb_str_new2("");
         | 
| 457 | 
            -
                    }
         | 
| 458 | 
            -
                    tmp = rb_hash_aref(opts, ID2SYM(i_array_nl));
         | 
| 459 | 
            -
                    if (RTEST(tmp)) {
         | 
| 460 | 
            -
                        Check_Type(tmp, T_STRING);
         | 
| 461 | 
            -
                        state->array_nl = tmp;
         | 
| 462 | 
            -
                    } else {
         | 
| 463 | 
            -
                        state->array_nl = rb_str_new2("");
         | 
| 464 | 
            -
                    }
         | 
| 465 | 
            -
                    tmp = rb_hash_aref(opts, ID2SYM(i_object_nl));
         | 
| 466 | 
            -
                    if (RTEST(tmp)) {
         | 
| 467 | 
            -
                        Check_Type(tmp, T_STRING);
         | 
| 468 | 
            -
                        state->object_nl = tmp;
         | 
| 469 | 
            -
                    } else {
         | 
| 470 | 
            -
                        state->object_nl = rb_str_new2("");
         | 
| 471 | 
            -
                    }
         | 
| 472 | 
            -
                    tmp = rb_hash_aref(opts, ID2SYM(i_check_circular));
         | 
| 473 | 
            -
                    state->check_circular = RTEST(tmp);
         | 
| 561 | 
            +
                    cState_configure(self, opts);
         | 
| 474 562 | 
             
                }
         | 
| 475 563 | 
             
                state->seen = rb_hash_new();
         | 
| 476 564 | 
             
                state->memo = Qnil;
         | 
| @@ -616,7 +704,7 @@ static VALUE cState_array_nl_set(VALUE self, VALUE array_nl) | |
| 616 704 | 
             
            }
         | 
| 617 705 |  | 
| 618 706 | 
             
            /*
         | 
| 619 | 
            -
             * call-seq: check_circular? | 
| 707 | 
            +
             * call-seq: check_circular?
         | 
| 620 708 | 
             
             *
         | 
| 621 709 | 
             
             * Returns true, if circular data structures should be checked,
         | 
| 622 710 | 
             
             * otherwise returns false.
         | 
| @@ -627,6 +715,44 @@ static VALUE cState_check_circular_p(VALUE self) | |
| 627 715 | 
             
                return state->check_circular ? Qtrue : Qfalse;
         | 
| 628 716 | 
             
            }
         | 
| 629 717 |  | 
| 718 | 
            +
            /*
         | 
| 719 | 
            +
             * call-seq: max_nesting
         | 
| 720 | 
            +
             *
         | 
| 721 | 
            +
             * This integer returns the maximum level of data structure nesting in
         | 
| 722 | 
            +
             * the generated JSON, max_nesting = 0 if no maximum is checked.
         | 
| 723 | 
            +
             */
         | 
| 724 | 
            +
            static VALUE cState_max_nesting(VALUE self)
         | 
| 725 | 
            +
            {
         | 
| 726 | 
            +
                GET_STATE(self);
         | 
| 727 | 
            +
                return LONG2FIX(state->max_nesting);
         | 
| 728 | 
            +
            }
         | 
| 729 | 
            +
             | 
| 730 | 
            +
            /*
         | 
| 731 | 
            +
             * call-seq: max_nesting=(depth)
         | 
| 732 | 
            +
             *
         | 
| 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.
         | 
| 735 | 
            +
             */
         | 
| 736 | 
            +
            static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
         | 
| 737 | 
            +
            {
         | 
| 738 | 
            +
                GET_STATE(self);
         | 
| 739 | 
            +
                Check_Type(depth, T_FIXNUM);
         | 
| 740 | 
            +
                state->max_nesting = FIX2LONG(depth);
         | 
| 741 | 
            +
                return Qnil;
         | 
| 742 | 
            +
            }
         | 
| 743 | 
            +
             | 
| 744 | 
            +
            /*
         | 
| 745 | 
            +
             * call-seq: allow_nan?
         | 
| 746 | 
            +
             *
         | 
| 747 | 
            +
             * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
         | 
| 748 | 
            +
             * returns false.
         | 
| 749 | 
            +
             */
         | 
| 750 | 
            +
            static VALUE cState_allow_nan_p(VALUE self)
         | 
| 751 | 
            +
            {
         | 
| 752 | 
            +
                GET_STATE(self);
         | 
| 753 | 
            +
                return state->allow_nan ? Qtrue : Qfalse;
         | 
| 754 | 
            +
            }
         | 
| 755 | 
            +
             | 
| 630 756 | 
             
            /*
         | 
| 631 757 | 
             
             * call-seq: seen?(object)
         | 
| 632 758 | 
             
             *
         | 
| @@ -668,6 +794,7 @@ void Init_generator() | |
| 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,9 +811,15 @@ void Init_generator() | |
| 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);
         | 
| 822 | 
            +
             | 
| 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);
         | 
| @@ -721,6 +854,8 @@ void Init_generator() | |
| 721 854 | 
             
                i_object_nl = rb_intern("object_nl");
         | 
| 722 855 | 
             
                i_array_nl = rb_intern("array_nl");
         | 
| 723 856 | 
             
                i_check_circular = rb_intern("check_circular");
         | 
| 857 | 
            +
                i_max_nesting = rb_intern("max_nesting");
         | 
| 858 | 
            +
                i_allow_nan = rb_intern("allow_nan");
         | 
| 724 859 | 
             
                i_pack = rb_intern("pack");
         | 
| 725 860 | 
             
                i_unpack = rb_intern("unpack");
         | 
| 726 861 | 
             
                i_create_id = rb_intern("create_id");
         |