oj 3.2.1 → 3.3.0
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.
- checksums.yaml +4 -4
- data/ext/oj/dump.c +2 -1
- data/ext/oj/dump.h +1 -0
- data/ext/oj/oj.c +59 -6
- data/ext/oj/oj.h +2 -0
- data/ext/oj/parse.h +1 -0
- data/ext/oj/wab.c +562 -0
- data/lib/oj/version.rb +1 -1
- data/pages/Modes.md +47 -40
- data/pages/WAB.md +13 -0
- data/test/perf_wab.rb +131 -0
- data/test/test_wab.rb +307 -0
- data/test/tests.rb +1 -0
- metadata +9 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 1373424e4c2fd32c52eaea6561ddfff276babeb5
         | 
| 4 | 
            +
              data.tar.gz: e35e9cd9d69496cc46838dcdf3da63a46908a657
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 19cc74647936b9ca942b3e88fea44f93efd7d3bb6d703fca5c53ed7a3cefd3f12e0c48f32d71fdc2a264d68ad6dd2662edffddcee046ab3b65d5b1354487116b
         | 
| 7 | 
            +
              data.tar.gz: 90ce6b08d284b3cded6aba7b946ce794751a1b85f6e5ff0f1e37337679263cf88641949f3fe5898a22db89bf5d71d9b7c36322de37a11ef31bf275965d69d364
         | 
    
        data/ext/oj/dump.c
    CHANGED
    
    | @@ -572,6 +572,7 @@ oj_dump_obj_to_json_using_params(VALUE obj, Options copts, Out out, int argc, VA | |
| 572 572 | 
             
                case CompatMode:	oj_dump_compat_val(obj, 0, out, Yes == copts->to_json);	break;
         | 
| 573 573 | 
             
                case RailsMode:	oj_dump_rails_val(obj, 0, out);				break;
         | 
| 574 574 | 
             
                case CustomMode:	oj_dump_custom_val(obj, 0, out, true);			break;
         | 
| 575 | 
            +
                case WabMode:	oj_dump_wab_val(obj, 0, out);				break;
         | 
| 575 576 | 
             
                default:		oj_dump_custom_val(obj, 0, out, true);			break;
         | 
| 576 577 | 
             
                }
         | 
| 577 578 | 
             
                if (0 < out->indent) {
         | 
| @@ -680,7 +681,7 @@ oj_dump_str(VALUE obj, int depth, Out out, bool as_ok) { | |
| 680 681 | 
             
            void
         | 
| 681 682 | 
             
            oj_dump_sym(VALUE obj, int depth, Out out, bool as_ok) {
         | 
| 682 683 | 
             
                const char	*sym = rb_id2name(SYM2ID(obj));
         | 
| 683 | 
            -
             | 
| 684 | 
            +
             | 
| 684 685 | 
             
                oj_dump_cstr(sym, strlen(sym), 0, 0, out);
         | 
| 685 686 | 
             
            }
         | 
| 686 687 |  | 
    
        data/ext/oj/dump.h
    CHANGED
    
    | @@ -43,6 +43,7 @@ extern void	oj_dump_obj_val(VALUE obj, int depth, Out out); | |
| 43 43 | 
             
            extern void	oj_dump_compat_val(VALUE obj, int depth, Out out, bool as_ok);
         | 
| 44 44 | 
             
            extern void	oj_dump_rails_val(VALUE obj, int depth, Out out);
         | 
| 45 45 | 
             
            extern void	oj_dump_custom_val(VALUE obj, int depth, Out out, bool as_ok);
         | 
| 46 | 
            +
            extern void	oj_dump_wab_val(VALUE obj, int depth, Out out);
         | 
| 46 47 |  | 
| 47 48 | 
             
            extern VALUE	oj_add_to_json(int argc, VALUE *argv, VALUE self);
         | 
| 48 49 | 
             
            extern VALUE	oj_remove_to_json(int argc, VALUE *argv, VALUE self);
         | 
    
        data/ext/oj/oj.c
    CHANGED
    
    | @@ -139,6 +139,7 @@ static VALUE	unix_zone_sym; | |
| 139 139 | 
             
            static VALUE	use_as_json_sym;
         | 
| 140 140 | 
             
            static VALUE	use_to_hash_sym;
         | 
| 141 141 | 
             
            static VALUE	use_to_json_sym;
         | 
| 142 | 
            +
            static VALUE	wab_sym;
         | 
| 142 143 | 
             
            static VALUE	word_sym;
         | 
| 143 144 | 
             
            static VALUE	xmlschema_sym;
         | 
| 144 145 | 
             
            static VALUE	xss_safe_sym;
         | 
| @@ -218,7 +219,7 @@ struct _Options	oj_default_options = { | |
| 218 219 | 
             
             * - *:symbol_keys* [_Boolean_|_nil_] use symbols instead of strings for hash keys
         | 
| 219 220 | 
             
             * - *:escape_mode* [_:newline_|_:json_|_:xss_safe_|_:ascii_|_unicode_xss_|_nil_] determines the characters to escape
         | 
| 220 221 | 
             
             * - *:class_cache* [_Boolean_|_nil_] cache classes for faster parsing (if dynamically modifying classes or reloading classes then don't use this)
         | 
| 221 | 
            -
             * - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_] load and dump modes to use for JSON
         | 
| 222 | 
            +
             * - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_|_:wab_] load and dump modes to use for JSON
         | 
| 222 223 | 
             
             * - *:time_format* [_:unix_|_:unix_zone_|_:xmlschema_|_:ruby_] time format when dumping in :compat and :object mode
         | 
| 223 224 | 
             
             * - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a String
         | 
| 224 225 | 
             
             * - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_] load decimals as BigDecimal instead of as a Float. :auto pick the most precise for the number of digits.
         | 
| @@ -277,6 +278,7 @@ get_def_opts(VALUE self) { | |
| 277 278 | 
             
                case ObjectMode:	rb_hash_aset(opts, mode_sym, object_sym);	break;
         | 
| 278 279 | 
             
                case CustomMode:	rb_hash_aset(opts, mode_sym, custom_sym);	break;
         | 
| 279 280 | 
             
                case RailsMode:	rb_hash_aset(opts, mode_sym, rails_sym);	break;
         | 
| 281 | 
            +
                case WabMode:	rb_hash_aset(opts, mode_sym, wab_sym);		break;
         | 
| 280 282 | 
             
                default:		rb_hash_aset(opts, mode_sym, object_sym);	break;
         | 
| 281 283 | 
             
                }
         | 
| 282 284 | 
             
                switch (oj_default_options.escape_mode) {
         | 
| @@ -334,7 +336,7 @@ get_def_opts(VALUE self) { | |
| 334 336 | 
             
             *   - *:escape* [_:newline_|_:json_|_:xss_safe_|_:ascii_|_unicode_xss_|_nil_] mode encodes all high-bit characters as escaped sequences if :ascii, :json is standand UTF-8 JSON encoding, :newline is the same as :json but newlines are not escaped, :unicode_xss allows unicode but escapes &, <, and >, and any \u20xx characters along with some others, and :xss_safe escapes &, <, and >, and some others.
         | 
| 335 337 | 
             
             *   - *:bigdecimal_as_decimal* [_Boolean_|_nil_] dump BigDecimal as a decimal number or as a String.
         | 
| 336 338 | 
             
             *   - *:bigdecimal_load* [_:bigdecimal_|_:float_|_:auto_|_nil_] load decimals as BigDecimal instead of as a Float. :auto pick the most precise for the number of digits.
         | 
| 337 | 
            -
             *   - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_] load and dump mode to use for JSON :strict raises an exception when a non-supported Object is encountered. :compat attempts to extract variable values from an Object using to_json() or to_hash() then it walks the Object's variables if neither is found. The :object mode ignores to_hash() and to_json() methods and encodes variables using code internal to the Oj gem. The :null mode ignores non-supported Objects and replaces them with a null. The :custom mode honors all dump options. The :rails more mimics rails and Active behavior.
         | 
| 339 | 
            +
             *   - *:mode* [_:object_|_:strict_|_:compat_|_:null_|_:custom_|_:rails_|_:wab_] load and dump mode to use for JSON :strict raises an exception when a non-supported Object is encountered. :compat attempts to extract variable values from an Object using to_json() or to_hash() then it walks the Object's variables if neither is found. The :object mode ignores to_hash() and to_json() methods and encodes variables using code internal to the Oj gem. The :null mode ignores non-supported Objects and replaces them with a null. The :custom mode honors all dump options. The :rails more mimics rails and Active behavior.
         | 
| 338 340 | 
             
             *   - *:time_format* [_:unix_|_:xmlschema_|_:ruby_] time format when dumping in :compat mode :unix decimal number denoting the number of seconds since 1/1/1970, :unix_zone decimal number denoting the number of seconds since 1/1/1970 plus the utc_offset in the exponent, :xmlschema date-time format taken from XML Schema as a String, :ruby Time.to_s formatted String.
         | 
| 339 341 | 
             
             *   - *:create_id* [_String_|_nil_] create id for json compatible object encoding
         | 
| 340 342 | 
             
             *   - *:second_precision* [_Fixnum_|_nil_] number of digits after the decimal when dumping the seconds portion of time.
         | 
| @@ -463,7 +465,9 @@ oj_parse_options(VALUE ropts, Options copts) { | |
| 463 465 | 
             
            	copts->sec_prec = n;
         | 
| 464 466 | 
             
                }
         | 
| 465 467 | 
             
                if (Qnil != (v = rb_hash_lookup(ropts, mode_sym))) {
         | 
| 466 | 
            -
            	if ( | 
| 468 | 
            +
            	if (wab_sym == v) {
         | 
| 469 | 
            +
            	    copts->mode = WabMode;
         | 
| 470 | 
            +
            	} else if (object_sym == v) {
         | 
| 467 471 | 
             
            	    copts->mode = ObjectMode;
         | 
| 468 472 | 
             
            	} else if (strict_sym == v) {
         | 
| 469 473 | 
             
            	    copts->mode = StrictMode;
         | 
| @@ -476,7 +480,7 @@ oj_parse_options(VALUE ropts, Options copts) { | |
| 476 480 | 
             
            	} else if (rails_sym == v) {
         | 
| 477 481 | 
             
            	    copts->mode = RailsMode;
         | 
| 478 482 | 
             
            	} else {
         | 
| 479 | 
            -
            	    rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, or : | 
| 483 | 
            +
            	    rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, :rails, or :wab.");
         | 
| 480 484 | 
             
            	}
         | 
| 481 485 | 
             
                }
         | 
| 482 486 | 
             
                if (Qnil != (v = rb_hash_lookup(ropts, time_format_sym))) {
         | 
| @@ -759,8 +763,10 @@ load(int argc, VALUE *argv, VALUE self) { | |
| 759 763 | 
             
            		mode = CustomMode;
         | 
| 760 764 | 
             
            	    } else if (rails_sym == v) {
         | 
| 761 765 | 
             
            		mode = RailsMode;
         | 
| 766 | 
            +
            	    } else if (wab_sym == v) {
         | 
| 767 | 
            +
            		mode = WabMode;
         | 
| 762 768 | 
             
            	    } else {
         | 
| 763 | 
            -
            		rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, or : | 
| 769 | 
            +
            		rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, :rails, or :wab.");
         | 
| 764 770 | 
             
            	    }
         | 
| 765 771 | 
             
            	}
         | 
| 766 772 | 
             
                }
         | 
| @@ -773,6 +779,8 @@ load(int argc, VALUE *argv, VALUE self) { | |
| 773 779 | 
             
            	return oj_compat_parse(argc, argv, self);
         | 
| 774 780 | 
             
                case CustomMode:
         | 
| 775 781 | 
             
            	return oj_custom_parse(argc, argv, self);
         | 
| 782 | 
            +
                case WabMode:
         | 
| 783 | 
            +
            	return oj_wab_parse(argc, argv, self);
         | 
| 776 784 | 
             
                case ObjectMode:
         | 
| 777 785 | 
             
                default:
         | 
| 778 786 | 
             
            	break;
         | 
| @@ -849,8 +857,10 @@ load_file(int argc, VALUE *argv, VALUE self) { | |
| 849 857 | 
             
            		mode = CustomMode;
         | 
| 850 858 | 
             
            	    } else if (rails_sym == v) {
         | 
| 851 859 | 
             
            		mode = RailsMode;
         | 
| 860 | 
            +
            	    } else if (wab_sym == v) {
         | 
| 861 | 
            +
            		mode = WabMode;
         | 
| 852 862 | 
             
            	    } else {
         | 
| 853 | 
            -
            		rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, :rails.");
         | 
| 863 | 
            +
            		rb_raise(rb_eArgError, ":mode must be :object, :strict, :compat, :null, :custom, :rails, or :wab.");
         | 
| 854 864 | 
             
            	    }
         | 
| 855 865 | 
             
            	}
         | 
| 856 866 | 
             
                }
         | 
| @@ -868,6 +878,9 @@ load_file(int argc, VALUE *argv, VALUE self) { | |
| 868 878 | 
             
                case RailsMode:
         | 
| 869 879 | 
             
            	oj_set_compat_callbacks(&pi);
         | 
| 870 880 | 
             
            	return oj_pi_sparse(argc, argv, &pi, fd);
         | 
| 881 | 
            +
                case WabMode:
         | 
| 882 | 
            +
            	oj_set_wab_callbacks(&pi);
         | 
| 883 | 
            +
            	return oj_pi_sparse(argc, argv, &pi, fd);
         | 
| 871 884 | 
             
                case ObjectMode:
         | 
| 872 885 | 
             
                default:
         | 
| 873 886 | 
             
            	break;
         | 
| @@ -1269,6 +1282,42 @@ extern VALUE	oj_compat_parse(int argc, VALUE *argv, VALUE self); | |
| 1269 1282 | 
             
             */
         | 
| 1270 1283 | 
             
            extern VALUE	oj_object_parse(int argc, VALUE *argv, VALUE self);
         | 
| 1271 1284 |  | 
| 1285 | 
            +
            /* Document-method: wab_load
         | 
| 1286 | 
            +
             * call-seq: wab_load(json, options) { _|_obj, start, len_|_ }
         | 
| 1287 | 
            +
             *
         | 
| 1288 | 
            +
             * Parses a JSON document String into an Hash, Array, String, Fixnum, Float,
         | 
| 1289 | 
            +
             * true, false, or nil. It parses using a mode that is :wab in that it maps
         | 
| 1290 | 
            +
             * each primitive JSON type to a similar Ruby type. The :create_id is not
         | 
| 1291 | 
            +
             * honored in this mode. Note that a Ruby Hash is used to represent the JSON
         | 
| 1292 | 
            +
             * Object type. These two are not the same since the JSON Object type can have
         | 
| 1293 | 
            +
             * repeating entries with the same key and Ruby Hash can not.
         | 
| 1294 | 
            +
             *
         | 
| 1295 | 
            +
             * When used with a document that has multiple JSON elements the block, if
         | 
| 1296 | 
            +
             * any, will be yielded to. If no block then the last element read will be
         | 
| 1297 | 
            +
             * returned.
         | 
| 1298 | 
            +
             *
         | 
| 1299 | 
            +
             * Raises an exception if the JSON is malformed or the classes specified are not
         | 
| 1300 | 
            +
             * valid. If the input is not a valid JSON document (an empty string is not a
         | 
| 1301 | 
            +
             * valid JSON document) an exception is raised.
         | 
| 1302 | 
            +
             *
         | 
| 1303 | 
            +
             * A block can be provided with a single argument. That argument will be the
         | 
| 1304 | 
            +
             * parsed JSON document. This is useful when parsing a string that includes
         | 
| 1305 | 
            +
             * multiple JSON documents. The block can take up to 3 arguments, the parsed
         | 
| 1306 | 
            +
             * object, the position in the string or stream of the start of the JSON for
         | 
| 1307 | 
            +
             * that object, and the length of the JSON for that object plus trailing
         | 
| 1308 | 
            +
             * whitespace.
         | 
| 1309 | 
            +
             *
         | 
| 1310 | 
            +
             * - *json* [_String_|_IO_] JSON String or an Object that responds to read().
         | 
| 1311 | 
            +
             * - *options* [_Hash_] load options (same as default_options).
         | 
| 1312 | 
            +
             *   - -
         | 
| 1313 | 
            +
             * - *obj* [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_] parsed object.
         | 
| 1314 | 
            +
             * - *start* [_optional, _Integer_] start position of parsed JSON for obj.
         | 
| 1315 | 
            +
             * - *len* [_optional, _Integer_] length of parsed JSON for obj.
         | 
| 1316 | 
            +
             *
         | 
| 1317 | 
            +
             * Returns [_Hash_|_Array_|_String_|_Fixnum_|_Float_|_Boolean_|_nil_]
         | 
| 1318 | 
            +
             */
         | 
| 1319 | 
            +
            extern VALUE	oj_wab_parse(int argc, VALUE *argv, VALUE self);
         | 
| 1320 | 
            +
             | 
| 1272 1321 | 
             
            /* Document-method: add_to_json
         | 
| 1273 1322 | 
             
             * call-seq: add_to_json(*args)
         | 
| 1274 1323 | 
             
             *
         | 
| @@ -1406,6 +1455,8 @@ protect_require(VALUE x) { | |
| 1406 1455 | 
             
             * - *:rails* is the compatibility mode for Rails or Active support.
         | 
| 1407 1456 | 
             
             *
         | 
| 1408 1457 | 
             
             * - *:custom* is the most configurable mode.
         | 
| 1458 | 
            +
             *
         | 
| 1459 | 
            +
             * - *:wab* specifically for WAB data exchange.
         | 
| 1409 1460 | 
             
             */
         | 
| 1410 1461 | 
             
            void
         | 
| 1411 1462 | 
             
            Init_oj() {
         | 
| @@ -1445,6 +1496,7 @@ Init_oj() { | |
| 1445 1496 | 
             
                rb_define_module_function(Oj, "strict_load", oj_strict_parse, -1);
         | 
| 1446 1497 | 
             
                rb_define_module_function(Oj, "compat_load", oj_compat_parse, -1);
         | 
| 1447 1498 | 
             
                rb_define_module_function(Oj, "object_load", oj_object_parse, -1);
         | 
| 1499 | 
            +
                rb_define_module_function(Oj, "wab_load", oj_wab_parse, -1);
         | 
| 1448 1500 |  | 
| 1449 1501 | 
             
                rb_define_module_function(Oj, "dump", dump, -1);
         | 
| 1450 1502 |  | 
| @@ -1580,6 +1632,7 @@ Init_oj() { | |
| 1580 1632 | 
             
                use_as_json_sym = ID2SYM(rb_intern("use_as_json"));		rb_gc_register_address(&use_as_json_sym);
         | 
| 1581 1633 | 
             
                use_to_hash_sym = ID2SYM(rb_intern("use_to_hash"));		rb_gc_register_address(&use_to_hash_sym);
         | 
| 1582 1634 | 
             
                use_to_json_sym = ID2SYM(rb_intern("use_to_json"));		rb_gc_register_address(&use_to_json_sym);
         | 
| 1635 | 
            +
                wab_sym = ID2SYM(rb_intern("wab"));				rb_gc_register_address(&wab_sym);
         | 
| 1583 1636 | 
             
                word_sym = ID2SYM(rb_intern("word"));			rb_gc_register_address(&word_sym);
         | 
| 1584 1637 | 
             
                xmlschema_sym = ID2SYM(rb_intern("xmlschema"));		rb_gc_register_address(&xmlschema_sym);
         | 
| 1585 1638 | 
             
                xss_safe_sym = ID2SYM(rb_intern("xss_safe"));		rb_gc_register_address(&xss_safe_sym);
         | 
    
        data/ext/oj/oj.h
    CHANGED
    
    | @@ -61,6 +61,7 @@ typedef enum { | |
| 61 61 | 
             
                CompatMode	= 'c',
         | 
| 62 62 | 
             
                RailsMode	= 'r',
         | 
| 63 63 | 
             
                CustomMode	= 'C',
         | 
| 64 | 
            +
                WabMode	= 'w',
         | 
| 64 65 | 
             
            } Mode;
         | 
| 65 66 |  | 
| 66 67 | 
             
            typedef enum {
         | 
| @@ -245,6 +246,7 @@ extern VALUE	oj_strict_sparse(int argc, VALUE *argv, VALUE self); | |
| 245 246 | 
             
            extern VALUE	oj_compat_parse(int argc, VALUE *argv, VALUE self);
         | 
| 246 247 | 
             
            extern VALUE	oj_object_parse(int argc, VALUE *argv, VALUE self);
         | 
| 247 248 | 
             
            extern VALUE	oj_custom_parse(int argc, VALUE *argv, VALUE self);
         | 
| 249 | 
            +
            extern VALUE	oj_wab_parse(int argc, VALUE *argv, VALUE self);
         | 
| 248 250 |  | 
| 249 251 | 
             
            extern VALUE	oj_strict_parse_cstr(int argc, VALUE *argv, char *json, size_t len);
         | 
| 250 252 | 
             
            extern VALUE	oj_compat_parse_cstr(int argc, VALUE *argv, char *json, size_t len);
         | 
    
        data/ext/oj/parse.h
    CHANGED
    
    | @@ -80,6 +80,7 @@ extern VALUE	oj_num_as_value(NumInfo ni); | |
| 80 80 | 
             
            extern void	oj_set_strict_callbacks(ParseInfo pi);
         | 
| 81 81 | 
             
            extern void	oj_set_object_callbacks(ParseInfo pi);
         | 
| 82 82 | 
             
            extern void	oj_set_compat_callbacks(ParseInfo pi);
         | 
| 83 | 
            +
            extern void	oj_set_wab_callbacks(ParseInfo pi);
         | 
| 83 84 |  | 
| 84 85 | 
             
            extern void	oj_sparse2(ParseInfo pi);
         | 
| 85 86 | 
             
            extern VALUE	oj_pi_sparse(int argc, VALUE *argv, ParseInfo pi, int fd);
         | 
    
        data/ext/oj/wab.c
    ADDED
    
    | @@ -0,0 +1,562 @@ | |
| 1 | 
            +
            /* wab.c
         | 
| 2 | 
            +
             * Copyright (c) 2012, Peter Ohler
         | 
| 3 | 
            +
             * All rights reserved.
         | 
| 4 | 
            +
             */
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            #include <stdlib.h>
         | 
| 7 | 
            +
            #include <stdio.h>
         | 
| 8 | 
            +
            #include <string.h>
         | 
| 9 | 
            +
            #include <time.h>
         | 
| 10 | 
            +
            #include <unistd.h>
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            #include "oj.h"
         | 
| 13 | 
            +
            #include "err.h"
         | 
| 14 | 
            +
            #include "parse.h"
         | 
| 15 | 
            +
            #include "encode.h"
         | 
| 16 | 
            +
            #include "dump.h"
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            // Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
         | 
| 19 | 
            +
            #define OJ_INFINITY (1.0/0.0)
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            static char	hex_chars[256] = "\
         | 
| 22 | 
            +
            ................................\
         | 
| 23 | 
            +
            ................xxxxxxxxxx......\
         | 
| 24 | 
            +
            .xxxxxx.........................\
         | 
| 25 | 
            +
            .xxxxxx.........................\
         | 
| 26 | 
            +
            ................................\
         | 
| 27 | 
            +
            ................................\
         | 
| 28 | 
            +
            ................................\
         | 
| 29 | 
            +
            ................................";
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            static VALUE	wab_uuid_clas = Qundef;
         | 
| 32 | 
            +
            static VALUE	uri_clas = Qundef;
         | 
| 33 | 
            +
            static VALUE	uri_http_clas = Qundef;
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            ///// dump functions /////
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            static VALUE
         | 
| 38 | 
            +
            resolve_wab_uuid_class() {
         | 
| 39 | 
            +
                if (Qundef == wab_uuid_clas) {
         | 
| 40 | 
            +
            	volatile VALUE	wab_module;
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            	wab_uuid_clas = Qnil;
         | 
| 43 | 
            +
            	if (rb_const_defined_at(rb_cObject, rb_intern("WAB"))) {
         | 
| 44 | 
            +
            	    wab_module = rb_const_get_at(rb_cObject, rb_intern("WAB"));
         | 
| 45 | 
            +
            	    if (rb_const_defined_at(wab_module, rb_intern("UUID"))) {
         | 
| 46 | 
            +
            		wab_uuid_clas = rb_const_get(wab_module, rb_intern("UUID"));
         | 
| 47 | 
            +
            	    }
         | 
| 48 | 
            +
            	}
         | 
| 49 | 
            +
                }
         | 
| 50 | 
            +
                return wab_uuid_clas;
         | 
| 51 | 
            +
            }
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            static VALUE
         | 
| 54 | 
            +
            resolve_uri_class() {
         | 
| 55 | 
            +
                if (Qundef == uri_clas) {
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            	uri_clas = Qnil;
         | 
| 58 | 
            +
            	if (rb_const_defined_at(rb_cObject, rb_intern("URI"))) {
         | 
| 59 | 
            +
            	    uri_clas = rb_const_get_at(rb_cObject, rb_intern("URI"));
         | 
| 60 | 
            +
            	}
         | 
| 61 | 
            +
                }
         | 
| 62 | 
            +
                return uri_clas;
         | 
| 63 | 
            +
            }
         | 
| 64 | 
            +
             | 
| 65 | 
            +
            static VALUE
         | 
| 66 | 
            +
            resolve_uri_http_class() {
         | 
| 67 | 
            +
                if (Qundef == uri_http_clas) {
         | 
| 68 | 
            +
            	volatile VALUE	uri_module;
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            	uri_http_clas = Qnil;
         | 
| 71 | 
            +
            	if (rb_const_defined_at(rb_cObject, rb_intern("URI"))) {
         | 
| 72 | 
            +
            	    uri_module = rb_const_get_at(rb_cObject, rb_intern("URI"));
         | 
| 73 | 
            +
            	    if (rb_const_defined_at(uri_module, rb_intern("HTTP"))) {
         | 
| 74 | 
            +
            		uri_http_clas = rb_const_get(uri_module, rb_intern("HTTP"));
         | 
| 75 | 
            +
            	    }
         | 
| 76 | 
            +
            	}
         | 
| 77 | 
            +
                }
         | 
| 78 | 
            +
                return uri_http_clas;
         | 
| 79 | 
            +
            }
         | 
| 80 | 
            +
             | 
| 81 | 
            +
            static void
         | 
| 82 | 
            +
            raise_wab(VALUE obj) {
         | 
| 83 | 
            +
                rb_raise(rb_eTypeError, "Failed to dump %s Object to JSON in wab mode.\n", rb_class2name(rb_obj_class(obj)));
         | 
| 84 | 
            +
            }
         | 
| 85 | 
            +
             | 
| 86 | 
            +
            // Removed dependencies on math due to problems with CentOS 5.4.
         | 
| 87 | 
            +
            static void
         | 
| 88 | 
            +
            dump_float(VALUE obj, int depth, Out out, bool as_ok) {
         | 
| 89 | 
            +
                char	buf[64];
         | 
| 90 | 
            +
                char	*b;
         | 
| 91 | 
            +
                double	d = rb_num2dbl(obj);
         | 
| 92 | 
            +
                int		cnt = 0;
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                if (0.0 == d) {
         | 
| 95 | 
            +
            	b = buf;
         | 
| 96 | 
            +
            	*b++ = '0';
         | 
| 97 | 
            +
            	*b++ = '.';
         | 
| 98 | 
            +
            	*b++ = '0';
         | 
| 99 | 
            +
            	*b++ = '\0';
         | 
| 100 | 
            +
            	cnt = 3;
         | 
| 101 | 
            +
                } else {
         | 
| 102 | 
            +
            	if (OJ_INFINITY == d || -OJ_INFINITY == d || isnan(d)) {
         | 
| 103 | 
            +
            	    raise_wab(obj);
         | 
| 104 | 
            +
            	} else if (d == (double)(long long int)d) {
         | 
| 105 | 
            +
            	    cnt = snprintf(buf, sizeof(buf), "%.1f", d);
         | 
| 106 | 
            +
            	} else {
         | 
| 107 | 
            +
            	    cnt = snprintf(buf, sizeof(buf), "%0.16g", d);
         | 
| 108 | 
            +
            	}
         | 
| 109 | 
            +
                }
         | 
| 110 | 
            +
                assure_size(out, cnt);
         | 
| 111 | 
            +
                for (b = buf; '\0' != *b; b++) {
         | 
| 112 | 
            +
            	*out->cur++ = *b;
         | 
| 113 | 
            +
                }
         | 
| 114 | 
            +
                *out->cur = '\0';
         | 
| 115 | 
            +
            }
         | 
| 116 | 
            +
             | 
| 117 | 
            +
            static void
         | 
| 118 | 
            +
            dump_array(VALUE a, int depth, Out out, bool as_ok) {
         | 
| 119 | 
            +
                size_t	size;
         | 
| 120 | 
            +
                int		i, cnt;
         | 
| 121 | 
            +
                int		d2 = depth + 1;
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                cnt = (int)RARRAY_LEN(a);
         | 
| 124 | 
            +
                *out->cur++ = '[';
         | 
| 125 | 
            +
                size = 2;
         | 
| 126 | 
            +
                assure_size(out, size);
         | 
| 127 | 
            +
                if (0 == cnt) {
         | 
| 128 | 
            +
            	*out->cur++ = ']';
         | 
| 129 | 
            +
                } else {
         | 
| 130 | 
            +
            	size = d2 * out->indent + 2;
         | 
| 131 | 
            +
            	cnt--;
         | 
| 132 | 
            +
            	for (i = 0; i <= cnt; i++) {
         | 
| 133 | 
            +
            	    assure_size(out, size);
         | 
| 134 | 
            +
            	    fill_indent(out, d2);
         | 
| 135 | 
            +
            	    oj_dump_wab_val(rb_ary_entry(a, i), d2, out);
         | 
| 136 | 
            +
            	    if (i < cnt) {
         | 
| 137 | 
            +
            		*out->cur++ = ',';
         | 
| 138 | 
            +
            	    }
         | 
| 139 | 
            +
            	}
         | 
| 140 | 
            +
            	size = depth * out->indent + 1;
         | 
| 141 | 
            +
            	assure_size(out, size);
         | 
| 142 | 
            +
            	fill_indent(out, depth);
         | 
| 143 | 
            +
            	*out->cur++ = ']';
         | 
| 144 | 
            +
                }
         | 
| 145 | 
            +
                *out->cur = '\0';
         | 
| 146 | 
            +
            }
         | 
| 147 | 
            +
             | 
| 148 | 
            +
            static int
         | 
| 149 | 
            +
            hash_cb(VALUE key, VALUE value, Out out) {
         | 
| 150 | 
            +
                int		depth = out->depth;
         | 
| 151 | 
            +
                long	size;
         | 
| 152 | 
            +
                int		rtype = rb_type(key);
         | 
| 153 | 
            +
                
         | 
| 154 | 
            +
                if (rtype != T_SYMBOL) {
         | 
| 155 | 
            +
            	rb_raise(rb_eTypeError, "In :wab mode all Hash keys must be Symbols, not %s.\n", rb_class2name(rb_obj_class(key)));
         | 
| 156 | 
            +
                }
         | 
| 157 | 
            +
                size = depth * out->indent + 1;
         | 
| 158 | 
            +
                assure_size(out, size);
         | 
| 159 | 
            +
                fill_indent(out, depth);
         | 
| 160 | 
            +
                oj_dump_sym(key, 0, out, false);
         | 
| 161 | 
            +
                *out->cur++ = ':';
         | 
| 162 | 
            +
                oj_dump_wab_val(value, depth, out);
         | 
| 163 | 
            +
                out->depth = depth;
         | 
| 164 | 
            +
                *out->cur++ = ',';
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                return ST_CONTINUE;
         | 
| 167 | 
            +
            }
         | 
| 168 | 
            +
             | 
| 169 | 
            +
            static void
         | 
| 170 | 
            +
            dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
         | 
| 171 | 
            +
                int		cnt;
         | 
| 172 | 
            +
                size_t	size;
         | 
| 173 | 
            +
             | 
| 174 | 
            +
                cnt = (int)RHASH_SIZE(obj);
         | 
| 175 | 
            +
                size = depth * out->indent + 2;
         | 
| 176 | 
            +
                assure_size(out, 2);
         | 
| 177 | 
            +
                *out->cur++ = '{';
         | 
| 178 | 
            +
                if (0 == cnt) {
         | 
| 179 | 
            +
            	*out->cur++ = '}';
         | 
| 180 | 
            +
                } else {
         | 
| 181 | 
            +
            	out->depth = depth + 1;
         | 
| 182 | 
            +
            	rb_hash_foreach(obj, hash_cb, (VALUE)out);
         | 
| 183 | 
            +
            	if (',' == *(out->cur - 1)) {
         | 
| 184 | 
            +
            	    out->cur--; // backup to overwrite last comma
         | 
| 185 | 
            +
            	}
         | 
| 186 | 
            +
            	assure_size(out, size);
         | 
| 187 | 
            +
            	fill_indent(out, depth);
         | 
| 188 | 
            +
            	*out->cur++ = '}';
         | 
| 189 | 
            +
                }
         | 
| 190 | 
            +
                *out->cur = '\0';
         | 
| 191 | 
            +
            }
         | 
| 192 | 
            +
             | 
| 193 | 
            +
            static void
         | 
| 194 | 
            +
            dump_time(VALUE obj, Out out) {
         | 
| 195 | 
            +
                char		buf[64];
         | 
| 196 | 
            +
                struct tm		*tm;
         | 
| 197 | 
            +
            #if HAS_RB_TIME_TIMESPEC
         | 
| 198 | 
            +
                struct timespec	ts = rb_time_timespec(obj);
         | 
| 199 | 
            +
                time_t		sec = ts.tv_sec;
         | 
| 200 | 
            +
                long		nsec = ts.tv_nsec;
         | 
| 201 | 
            +
            #else
         | 
| 202 | 
            +
                time_t		sec = NUM2LONG(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
         | 
| 203 | 
            +
            #if HAS_NANO_TIME
         | 
| 204 | 
            +
                long long		nsec = rb_num2ll(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
         | 
| 205 | 
            +
            #else
         | 
| 206 | 
            +
                long long		nsec = rb_num2ll(rb_funcall2(obj, oj_tv_usec_id, 0, 0)) * 1000;
         | 
| 207 | 
            +
            #endif
         | 
| 208 | 
            +
            #endif
         | 
| 209 | 
            +
                int			len;
         | 
| 210 | 
            +
             | 
| 211 | 
            +
                assure_size(out, 36);
         | 
| 212 | 
            +
                // 2012-01-05T23:58:07.123456000Z
         | 
| 213 | 
            +
                tm = gmtime(&sec);
         | 
| 214 | 
            +
             | 
| 215 | 
            +
                len = sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02d.%09ldZ",
         | 
| 216 | 
            +
            		  tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
         | 
| 217 | 
            +
            		  tm->tm_hour, tm->tm_min, tm->tm_sec, nsec);
         | 
| 218 | 
            +
                oj_dump_cstr(buf, len, 0, 0, out);
         | 
| 219 | 
            +
            }
         | 
| 220 | 
            +
             | 
| 221 | 
            +
            static void
         | 
| 222 | 
            +
            dump_obj(VALUE obj, int depth, Out out, bool as_ok) {
         | 
| 223 | 
            +
                volatile VALUE	clas = rb_obj_class(obj);
         | 
| 224 | 
            +
             | 
| 225 | 
            +
                if (rb_cTime == clas) {
         | 
| 226 | 
            +
            	dump_time(obj, out);
         | 
| 227 | 
            +
                } else if (oj_bigdecimal_class == clas) {
         | 
| 228 | 
            +
            	volatile VALUE	rstr = rb_funcall(obj, oj_to_s_id, 0);
         | 
| 229 | 
            +
             | 
| 230 | 
            +
            	oj_dump_raw(rb_string_value_ptr((VALUE*)&rstr), RSTRING_LEN(rstr), out);
         | 
| 231 | 
            +
                } else if (resolve_wab_uuid_class() == clas) {
         | 
| 232 | 
            +
            	oj_dump_str(rb_funcall(obj, oj_to_s_id, 0), depth, out, false);
         | 
| 233 | 
            +
                } else if (resolve_uri_http_class() == clas) {
         | 
| 234 | 
            +
            	oj_dump_str(rb_funcall(obj, oj_to_s_id, 0), depth, out, false);
         | 
| 235 | 
            +
                } else {
         | 
| 236 | 
            +
            	raise_wab(obj);
         | 
| 237 | 
            +
                }
         | 
| 238 | 
            +
            }
         | 
| 239 | 
            +
             | 
| 240 | 
            +
            static DumpFunc	wab_funcs[] = {
         | 
| 241 | 
            +
                NULL,	 	// RUBY_T_NONE   = 0x00,
         | 
| 242 | 
            +
                dump_obj,		// RUBY_T_OBJECT = 0x01,
         | 
| 243 | 
            +
                NULL, 		// RUBY_T_CLASS  = 0x02,
         | 
| 244 | 
            +
                NULL, 		// RUBY_T_MODULE = 0x03,
         | 
| 245 | 
            +
                dump_float, 	// RUBY_T_FLOAT  = 0x04,
         | 
| 246 | 
            +
                oj_dump_str, 	// RUBY_T_STRING = 0x05,
         | 
| 247 | 
            +
                NULL, 		// RUBY_T_REGEXP = 0x06,
         | 
| 248 | 
            +
                dump_array,		// RUBY_T_ARRAY  = 0x07,
         | 
| 249 | 
            +
                dump_hash,	 	// RUBY_T_HASH   = 0x08,
         | 
| 250 | 
            +
                NULL, 		// RUBY_T_STRUCT = 0x09,
         | 
| 251 | 
            +
                oj_dump_bignum,	// RUBY_T_BIGNUM = 0x0a,
         | 
| 252 | 
            +
                NULL, 		// RUBY_T_FILE   = 0x0b,
         | 
| 253 | 
            +
                dump_obj,		// RUBY_T_DATA   = 0x0c,
         | 
| 254 | 
            +
                NULL, 		// RUBY_T_MATCH  = 0x0d,
         | 
| 255 | 
            +
                NULL, 		// RUBY_T_COMPLEX  = 0x0e,
         | 
| 256 | 
            +
                NULL, 		// RUBY_T_RATIONAL = 0x0f,
         | 
| 257 | 
            +
                NULL, 		// 0x10
         | 
| 258 | 
            +
                oj_dump_nil, 	// RUBY_T_NIL    = 0x11,
         | 
| 259 | 
            +
                oj_dump_true, 	// RUBY_T_TRUE   = 0x12,
         | 
| 260 | 
            +
                oj_dump_false,	// RUBY_T_FALSE  = 0x13,
         | 
| 261 | 
            +
                oj_dump_sym,	// RUBY_T_SYMBOL = 0x14,
         | 
| 262 | 
            +
                oj_dump_fixnum,	// RUBY_T_FIXNUM = 0x15,
         | 
| 263 | 
            +
            };
         | 
| 264 | 
            +
             | 
| 265 | 
            +
            void
         | 
| 266 | 
            +
            oj_dump_wab_val(VALUE obj, int depth, Out out) {
         | 
| 267 | 
            +
                int	type = rb_type(obj);
         | 
| 268 | 
            +
                
         | 
| 269 | 
            +
                if (MAX_DEPTH < depth) {
         | 
| 270 | 
            +
            	rb_raise(rb_eNoMemError, "Too deeply nested.\n");
         | 
| 271 | 
            +
                }
         | 
| 272 | 
            +
                if (0 < type && type <= RUBY_T_FIXNUM) {
         | 
| 273 | 
            +
            	DumpFunc	f = wab_funcs[type];
         | 
| 274 | 
            +
             | 
| 275 | 
            +
            	//printf("*** type %02x\n", type);
         | 
| 276 | 
            +
             | 
| 277 | 
            +
            	if (NULL != f) {
         | 
| 278 | 
            +
            	    f(obj, depth, out, false);
         | 
| 279 | 
            +
            	    return;
         | 
| 280 | 
            +
            	}
         | 
| 281 | 
            +
                }
         | 
| 282 | 
            +
                raise_wab(obj);
         | 
| 283 | 
            +
            }
         | 
| 284 | 
            +
             | 
| 285 | 
            +
            ///// load functions /////
         | 
| 286 | 
            +
             | 
| 287 | 
            +
            static void
         | 
| 288 | 
            +
            noop_end(struct _ParseInfo *pi) {
         | 
| 289 | 
            +
            }
         | 
| 290 | 
            +
             | 
| 291 | 
            +
            static VALUE
         | 
| 292 | 
            +
            noop_hash_key(struct _ParseInfo *pi, const char *key, size_t klen) {
         | 
| 293 | 
            +
                return Qundef;
         | 
| 294 | 
            +
            }
         | 
| 295 | 
            +
             | 
| 296 | 
            +
            static void
         | 
| 297 | 
            +
            add_value(ParseInfo pi, VALUE val) {
         | 
| 298 | 
            +
                pi->stack.head->val = val;
         | 
| 299 | 
            +
            }
         | 
| 300 | 
            +
             | 
| 301 | 
            +
            // 123e4567-e89b-12d3-a456-426655440000
         | 
| 302 | 
            +
            static bool
         | 
| 303 | 
            +
            uuid_check(const char *str, int len) {
         | 
| 304 | 
            +
                int		i;
         | 
| 305 | 
            +
                
         | 
| 306 | 
            +
                for (i = 0; i < 8; i++, str++) {
         | 
| 307 | 
            +
            	if ('x' != hex_chars[*(uint8_t*)str]) {
         | 
| 308 | 
            +
            	    return false;
         | 
| 309 | 
            +
            	}
         | 
| 310 | 
            +
                }
         | 
| 311 | 
            +
                str++;
         | 
| 312 | 
            +
                for (i = 0; i < 4; i++, str++) {
         | 
| 313 | 
            +
            	if ('x' != hex_chars[*(uint8_t*)str]) {
         | 
| 314 | 
            +
            	    return false;
         | 
| 315 | 
            +
            	}
         | 
| 316 | 
            +
                }
         | 
| 317 | 
            +
                str++;
         | 
| 318 | 
            +
                for (i = 0; i < 4; i++, str++) {
         | 
| 319 | 
            +
            	if ('x' != hex_chars[*(uint8_t*)str]) {
         | 
| 320 | 
            +
            	    return false;
         | 
| 321 | 
            +
            	}
         | 
| 322 | 
            +
                }
         | 
| 323 | 
            +
                str++;
         | 
| 324 | 
            +
                for (i = 0; i < 4; i++, str++) {
         | 
| 325 | 
            +
            	if ('x' != hex_chars[*(uint8_t*)str]) {
         | 
| 326 | 
            +
            	    return false;
         | 
| 327 | 
            +
            	}
         | 
| 328 | 
            +
                }
         | 
| 329 | 
            +
                str++;
         | 
| 330 | 
            +
                for (i = 0; i < 12; i++, str++) {
         | 
| 331 | 
            +
            	if ('x' != hex_chars[*(uint8_t*)str]) {
         | 
| 332 | 
            +
            	    return false;
         | 
| 333 | 
            +
            	}
         | 
| 334 | 
            +
                }
         | 
| 335 | 
            +
                return true;
         | 
| 336 | 
            +
            }
         | 
| 337 | 
            +
             | 
| 338 | 
            +
            static const char*
         | 
| 339 | 
            +
            read_num(const char *s, int len, int *vp) {
         | 
| 340 | 
            +
                uint32_t	v = 0;
         | 
| 341 | 
            +
             | 
| 342 | 
            +
                for (; 0 < len; len--, s++) {
         | 
| 343 | 
            +
            	if ('0' <= *s && *s <= '9') {
         | 
| 344 | 
            +
            	    v = v * 10 + *s - '0';
         | 
| 345 | 
            +
            	} else {
         | 
| 346 | 
            +
            	    return NULL;
         | 
| 347 | 
            +
            	}
         | 
| 348 | 
            +
                }
         | 
| 349 | 
            +
                *vp = (int)v;
         | 
| 350 | 
            +
             | 
| 351 | 
            +
                return s;
         | 
| 352 | 
            +
            }
         | 
| 353 | 
            +
             | 
| 354 | 
            +
            static VALUE
         | 
| 355 | 
            +
            time_parse(const char *s, int len) {
         | 
| 356 | 
            +
                struct tm	tm;
         | 
| 357 | 
            +
                bool	neg = false;
         | 
| 358 | 
            +
                long	nsecs = 0;
         | 
| 359 | 
            +
                int		i;
         | 
| 360 | 
            +
                time_t	secs;
         | 
| 361 | 
            +
                
         | 
| 362 | 
            +
                memset(&tm, 0, sizeof(tm));
         | 
| 363 | 
            +
                if ('-' == *s) {
         | 
| 364 | 
            +
            	s++;
         | 
| 365 | 
            +
            	neg = true;
         | 
| 366 | 
            +
                }
         | 
| 367 | 
            +
                if (NULL == (s = read_num(s, 4, &tm.tm_year))) {
         | 
| 368 | 
            +
            	return Qnil;
         | 
| 369 | 
            +
                }
         | 
| 370 | 
            +
                if (neg) {
         | 
| 371 | 
            +
            	tm.tm_year = -tm.tm_year;
         | 
| 372 | 
            +
            	neg = false;
         | 
| 373 | 
            +
                }
         | 
| 374 | 
            +
                tm.tm_year -= 1900;
         | 
| 375 | 
            +
                s++;
         | 
| 376 | 
            +
                if (NULL == (s = read_num(s, 2, &tm.tm_mon))) {
         | 
| 377 | 
            +
            	return Qnil;
         | 
| 378 | 
            +
                }
         | 
| 379 | 
            +
                tm.tm_mon--;
         | 
| 380 | 
            +
                s++;
         | 
| 381 | 
            +
                if (NULL == (s = read_num(s, 2, &tm.tm_mday))) {
         | 
| 382 | 
            +
            	return Qnil;
         | 
| 383 | 
            +
                }
         | 
| 384 | 
            +
                s++;
         | 
| 385 | 
            +
                if (NULL == (s = read_num(s, 2, &tm.tm_hour))) {
         | 
| 386 | 
            +
            	return Qnil;
         | 
| 387 | 
            +
                }
         | 
| 388 | 
            +
                s++;
         | 
| 389 | 
            +
                if (NULL == (s = read_num(s, 2, &tm.tm_min))) {
         | 
| 390 | 
            +
            	return Qnil;
         | 
| 391 | 
            +
                }
         | 
| 392 | 
            +
                s++;
         | 
| 393 | 
            +
                if (NULL == (s = read_num(s, 2, &tm.tm_sec))) {
         | 
| 394 | 
            +
            	return Qnil;
         | 
| 395 | 
            +
                }
         | 
| 396 | 
            +
                s++;
         | 
| 397 | 
            +
             | 
| 398 | 
            +
                for (i = 9; 0 < i; i--, s++) {
         | 
| 399 | 
            +
            	if ('0' <= *s && *s <= '9') {
         | 
| 400 | 
            +
            	    nsecs = nsecs * 10 + *s - '0';
         | 
| 401 | 
            +
            	} else {
         | 
| 402 | 
            +
            	    return Qnil;
         | 
| 403 | 
            +
            	}
         | 
| 404 | 
            +
                }
         | 
| 405 | 
            +
                secs = (time_t)timegm(&tm);
         | 
| 406 | 
            +
             | 
| 407 | 
            +
                return rb_funcall(rb_time_nano_new(secs, nsecs), oj_utc_id, 0);
         | 
| 408 | 
            +
            }
         | 
| 409 | 
            +
             | 
| 410 | 
            +
            static VALUE
         | 
| 411 | 
            +
            protect_uri(VALUE rstr) {
         | 
| 412 | 
            +
                return rb_funcall(resolve_uri_class(), oj_parse_id, 1, rstr);
         | 
| 413 | 
            +
            }
         | 
| 414 | 
            +
             | 
| 415 | 
            +
            static VALUE
         | 
| 416 | 
            +
            cstr_to_rstr(const char *str, size_t len) {
         | 
| 417 | 
            +
                volatile VALUE	v = Qnil;
         | 
| 418 | 
            +
                
         | 
| 419 | 
            +
                if (30 == len && '-' == str[4] && '-' == str[7] && 'T' == str[10] && ':' == str[13] && ':' == str[16]  && '.' == str[19] && 'Z' == str[29]) {
         | 
| 420 | 
            +
            	if (Qnil != (v = time_parse(str, len))) {
         | 
| 421 | 
            +
            	    return v;
         | 
| 422 | 
            +
            	}
         | 
| 423 | 
            +
                }
         | 
| 424 | 
            +
                if (36 == len && '-' == str[8] && '-' == str[13] && '-' == str[18] && '-' == str[23] && uuid_check(str, len) && Qnil != resolve_wab_uuid_class()) {
         | 
| 425 | 
            +
            	return rb_funcall(wab_uuid_clas, oj_new_id, 1, rb_str_new(str, len));
         | 
| 426 | 
            +
                }
         | 
| 427 | 
            +
                v = rb_str_new(str, len);
         | 
| 428 | 
            +
                if (7 < len && 0 == strncasecmp("http://", str, 7)) {
         | 
| 429 | 
            +
            	int		err = 0;
         | 
| 430 | 
            +
            	volatile VALUE	uri = rb_protect(protect_uri, v, &err);
         | 
| 431 | 
            +
             | 
| 432 | 
            +
            	if (0 == err) {
         | 
| 433 | 
            +
            	    return uri;
         | 
| 434 | 
            +
            	}
         | 
| 435 | 
            +
                }
         | 
| 436 | 
            +
                return oj_encode(v);
         | 
| 437 | 
            +
            }
         | 
| 438 | 
            +
             | 
| 439 | 
            +
            static void
         | 
| 440 | 
            +
            add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
         | 
| 441 | 
            +
                pi->stack.head->val = cstr_to_rstr(str, len);
         | 
| 442 | 
            +
            }
         | 
| 443 | 
            +
             | 
| 444 | 
            +
            static void
         | 
| 445 | 
            +
            add_num(ParseInfo pi, NumInfo ni) {
         | 
| 446 | 
            +
                if (ni->infinity || ni->nan) {
         | 
| 447 | 
            +
            	oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
         | 
| 448 | 
            +
                }
         | 
| 449 | 
            +
                pi->stack.head->val = oj_num_as_value(ni);
         | 
| 450 | 
            +
            }
         | 
| 451 | 
            +
             | 
| 452 | 
            +
            static VALUE
         | 
| 453 | 
            +
            start_hash(ParseInfo pi) {
         | 
| 454 | 
            +
                if (Qnil != pi->options.hash_class) {
         | 
| 455 | 
            +
            	return rb_class_new_instance(0, NULL, pi->options.hash_class);
         | 
| 456 | 
            +
                }
         | 
| 457 | 
            +
                return rb_hash_new();
         | 
| 458 | 
            +
            }
         | 
| 459 | 
            +
             | 
| 460 | 
            +
            static VALUE
         | 
| 461 | 
            +
            calc_hash_key(ParseInfo pi, Val parent) {
         | 
| 462 | 
            +
                volatile VALUE	rkey = parent->key_val;
         | 
| 463 | 
            +
             | 
| 464 | 
            +
                if (Qundef == rkey) {
         | 
| 465 | 
            +
            	rkey = rb_str_new(parent->key, parent->klen);
         | 
| 466 | 
            +
                }
         | 
| 467 | 
            +
                rkey = oj_encode(rkey);
         | 
| 468 | 
            +
                rkey = rb_str_intern(rkey);
         | 
| 469 | 
            +
             | 
| 470 | 
            +
                return rkey;
         | 
| 471 | 
            +
            }
         | 
| 472 | 
            +
             | 
| 473 | 
            +
            static void
         | 
| 474 | 
            +
            hash_set_cstr(ParseInfo pi, Val parent, const char *str, size_t len, const char *orig) {
         | 
| 475 | 
            +
                rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), cstr_to_rstr(str, len));
         | 
| 476 | 
            +
            }
         | 
| 477 | 
            +
             | 
| 478 | 
            +
            static void
         | 
| 479 | 
            +
            hash_set_num(struct _ParseInfo *pi, Val parent, NumInfo ni) {
         | 
| 480 | 
            +
                if (ni->infinity || ni->nan) {
         | 
| 481 | 
            +
            	oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
         | 
| 482 | 
            +
                }
         | 
| 483 | 
            +
                rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), oj_num_as_value(ni));
         | 
| 484 | 
            +
            }
         | 
| 485 | 
            +
             | 
| 486 | 
            +
            static void
         | 
| 487 | 
            +
            hash_set_value(ParseInfo pi, Val parent, VALUE value) {
         | 
| 488 | 
            +
                rb_hash_aset(stack_peek(&pi->stack)->val, calc_hash_key(pi, parent), value);
         | 
| 489 | 
            +
            }
         | 
| 490 | 
            +
             | 
| 491 | 
            +
            static VALUE
         | 
| 492 | 
            +
            start_array(ParseInfo pi) {
         | 
| 493 | 
            +
                return rb_ary_new();
         | 
| 494 | 
            +
            }
         | 
| 495 | 
            +
             | 
| 496 | 
            +
            static void
         | 
| 497 | 
            +
            array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
         | 
| 498 | 
            +
                rb_ary_push(stack_peek(&pi->stack)->val, cstr_to_rstr(str, len));
         | 
| 499 | 
            +
            }
         | 
| 500 | 
            +
             | 
| 501 | 
            +
            static void
         | 
| 502 | 
            +
            array_append_num(ParseInfo pi, NumInfo ni) {
         | 
| 503 | 
            +
                if (ni->infinity || ni->nan) {
         | 
| 504 | 
            +
            	oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
         | 
| 505 | 
            +
                }
         | 
| 506 | 
            +
                rb_ary_push(stack_peek(&pi->stack)->val, oj_num_as_value(ni));
         | 
| 507 | 
            +
            }
         | 
| 508 | 
            +
             | 
| 509 | 
            +
            static void
         | 
| 510 | 
            +
            array_append_value(ParseInfo pi, VALUE value) {
         | 
| 511 | 
            +
                rb_ary_push(stack_peek(&pi->stack)->val, value);
         | 
| 512 | 
            +
            }
         | 
| 513 | 
            +
             | 
| 514 | 
            +
            void
         | 
| 515 | 
            +
            oj_set_wab_callbacks(ParseInfo pi) {
         | 
| 516 | 
            +
                pi->start_hash = start_hash;
         | 
| 517 | 
            +
                pi->end_hash = noop_end;
         | 
| 518 | 
            +
                pi->hash_key = noop_hash_key;
         | 
| 519 | 
            +
                pi->hash_set_cstr = hash_set_cstr;
         | 
| 520 | 
            +
                pi->hash_set_num = hash_set_num;
         | 
| 521 | 
            +
                pi->hash_set_value = hash_set_value;
         | 
| 522 | 
            +
                pi->start_array = start_array;
         | 
| 523 | 
            +
                pi->end_array = noop_end;
         | 
| 524 | 
            +
                pi->array_append_cstr = array_append_cstr;
         | 
| 525 | 
            +
                pi->array_append_num = array_append_num;
         | 
| 526 | 
            +
                pi->array_append_value = array_append_value;
         | 
| 527 | 
            +
                pi->add_cstr = add_cstr;
         | 
| 528 | 
            +
                pi->add_num = add_num;
         | 
| 529 | 
            +
                pi->add_value = add_value;
         | 
| 530 | 
            +
                pi->expect_value = 1;
         | 
| 531 | 
            +
            }
         | 
| 532 | 
            +
             | 
| 533 | 
            +
            VALUE
         | 
| 534 | 
            +
            oj_wab_parse(int argc, VALUE *argv, VALUE self) {
         | 
| 535 | 
            +
                struct _ParseInfo	pi;
         | 
| 536 | 
            +
             | 
| 537 | 
            +
                parse_info_init(&pi);
         | 
| 538 | 
            +
                pi.options = oj_default_options;
         | 
| 539 | 
            +
                pi.handler = Qnil;
         | 
| 540 | 
            +
                pi.err_class = Qnil;
         | 
| 541 | 
            +
                oj_set_wab_callbacks(&pi);
         | 
| 542 | 
            +
             | 
| 543 | 
            +
                if (T_STRING == rb_type(*argv)) {
         | 
| 544 | 
            +
            	return oj_pi_parse(argc, argv, &pi, 0, 0, true);
         | 
| 545 | 
            +
                } else {
         | 
| 546 | 
            +
            	return oj_pi_sparse(argc, argv, &pi, 0);
         | 
| 547 | 
            +
                }
         | 
| 548 | 
            +
            }
         | 
| 549 | 
            +
             | 
| 550 | 
            +
            VALUE
         | 
| 551 | 
            +
            oj_wab_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
         | 
| 552 | 
            +
                struct _ParseInfo	pi;
         | 
| 553 | 
            +
             | 
| 554 | 
            +
                parse_info_init(&pi);
         | 
| 555 | 
            +
                pi.options = oj_default_options;
         | 
| 556 | 
            +
                pi.handler = Qnil;
         | 
| 557 | 
            +
                pi.err_class = Qnil;
         | 
| 558 | 
            +
                oj_set_wab_callbacks(&pi);
         | 
| 559 | 
            +
             | 
| 560 | 
            +
                return oj_pi_parse(argc, argv, &pi, json, len, true);
         | 
| 561 | 
            +
            }
         | 
| 562 | 
            +
             |