scout 5.1.2 → 5.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +5 -0
- data/lib/scout.rb +1 -1
- data/lib/scout/server.rb +4 -1
- data/vendor/json_pure/CHANGES +43 -0
- data/vendor/json_pure/{RUBY → COPYING} +1 -1
- data/vendor/json_pure/GPL +7 -7
- data/vendor/json_pure/README +319 -39
- data/vendor/json_pure/Rakefile +69 -47
- data/vendor/json_pure/VERSION +1 -1
- data/vendor/json_pure/benchmarks/generator2_benchmark.rb +222 -0
- data/vendor/json_pure/benchmarks/generator_benchmark.rb +64 -5
- data/vendor/json_pure/benchmarks/ohai.json +1216 -0
- data/vendor/json_pure/benchmarks/ohai.ruby +1 -0
- data/vendor/json_pure/benchmarks/parser2_benchmark.rb +251 -0
- data/vendor/json_pure/benchmarks/parser_benchmark.rb +67 -5
- data/vendor/json_pure/ext/json/ext/generator/extconf.rb +9 -4
- data/vendor/json_pure/ext/json/ext/generator/generator.c +831 -409
- data/vendor/json_pure/ext/json/ext/generator/generator.h +170 -0
- data/vendor/json_pure/ext/json/ext/parser/extconf.rb +8 -4
- data/vendor/json_pure/ext/json/ext/parser/parser.c +292 -186
- data/vendor/json_pure/ext/json/ext/parser/parser.h +71 -0
- data/vendor/json_pure/ext/json/ext/parser/parser.rl +218 -112
- data/vendor/json_pure/lib/json/add/core.rb +20 -7
- data/vendor/json_pure/lib/json/add/rails.rb +2 -2
- data/vendor/json_pure/lib/json/common.rb +85 -42
- data/vendor/json_pure/lib/json/pure.rb +3 -3
- data/vendor/json_pure/lib/json/pure/generator.rb +112 -90
- data/vendor/json_pure/lib/json/pure/parser.rb +42 -4
- data/vendor/json_pure/lib/json/version.rb +1 -1
- data/vendor/json_pure/tests/test_json.rb +46 -18
- data/vendor/json_pure/tests/test_json_addition.rb +4 -6
- data/vendor/json_pure/tests/test_json_encoding.rb +68 -0
- data/vendor/json_pure/tests/test_json_generate.rb +30 -14
- data/vendor/json_pure/tests/test_json_rails.rb +5 -7
- data/vendor/json_pure/tests/test_json_unicode.rb +20 -6
- metadata +26 -15
- data/vendor/json_pure/doc-templates/main.txt +0 -283
- data/vendor/json_pure/ext/json/ext/generator/unicode.c +0 -182
- data/vendor/json_pure/ext/json/ext/generator/unicode.h +0 -53
- data/vendor/json_pure/ext/json/ext/parser/unicode.c +0 -154
- data/vendor/json_pure/ext/json/ext/parser/unicode.h +0 -58
@@ -0,0 +1 @@
|
|
1
|
+
{"kernel"=>{"name"=>"Darwin", "machine"=>"i386", "modules"=>{"com.apple.driver.AppleAPIC"=>{"size"=>12288, "version"=>"1.4", "index"=>"26", "refcount"=>"0"}, "com.apple.driver.AirPort.Atheros"=>{"size"=>593920, "version"=>"318.8.3", "index"=>"88", "refcount"=>"0"}, "com.apple.driver.AppleIntelCPUPowerManagement"=>{"size"=>102400, "version"=>"59.0.1", "index"=>"22", "refcount"=>"0"}, "com.apple.iokit.IOStorageFamily"=>{"size"=>98304, "version"=>"1.5.5", "index"=>"44", "refcount"=>"9"}, "com.apple.iokit.IOATAPIProtocolTransport"=>{"size"=>16384, "version"=>"1.5.2", "index"=>"52", "refcount"=>"0"}, "com.apple.iokit.IOPCIFamily"=>{"size"=>65536, "version"=>"2.5", "index"=>"17", "refcount"=>"18"}, "org.virtualbox.kext.VBoxDrv"=>{"size"=>118784, "version"=>"2.2.0", "index"=>"114", "refcount"=>"3"}, "com.cisco.nke.ipsec"=>{"size"=>454656, "version"=>"2.0.1", "index"=>"111", "refcount"=>"0"}, "com.apple.driver.AppleHPET"=>{"size"=>12288, "version"=>"1.3", "index"=>"33", "refcount"=>"0"}, "com.apple.driver.AppleUSBHub"=>{"size"=>49152, "version"=>"3.2.7", "index"=>"47", "refcount"=>"0"}, "com.apple.iokit.IOFireWireFamily"=>{"size"=>258048, "version"=>"3.4.6", "index"=>"49", "refcount"=>"2"}, "com.apple.driver.AppleUSBComposite"=>{"size"=>16384, "version"=>"3.2.0", "index"=>"60", "refcount"=>"1"}, "com.apple.driver.AppleIntelPIIXATA"=>{"size"=>36864, "version"=>"2.0.0", "index"=>"41", "refcount"=>"0"}, "com.apple.driver.AppleSmartBatteryManager"=>{"size"=>28672, "version"=>"158.6.0", "index"=>"32", "refcount"=>"0"}, "com.apple.filesystems.udf"=>{"size"=>233472, "version"=>"2.0.2", "index"=>"119", "refcount"=>"0"}, "com.apple.iokit.IOSMBusFamily"=>{"size"=>12288, "version"=>"1.1", "index"=>"27", "refcount"=>"2"}, "com.apple.iokit.IOACPIFamily"=>{"size"=>16384, "version"=>"1.2.0", "index"=>"18", "refcount"=>"10"}, "foo.tap"=>{"size"=>24576, "version"=>"1.0", "index"=>"113", "refcount"=>"0"}, "com.vmware.kext.vmx86"=>{"size"=>864256, "version"=>"2.0.4", "index"=>"104", "refcount"=>"0"}, "com.apple.iokit.CHUDUtils"=>{"size"=>28672, "version"=>"200", "index"=>"98", "refcount"=>"0"}, "com.apple.driver.AppleACPIButtons"=>{"size"=>16384, "version"=>"1.2.4", "index"=>"30", "refcount"=>"0"}, "com.apple.driver.AppleFWOHCI"=>{"size"=>139264, "version"=>"3.7.2", "index"=>"50", "refcount"=>"0"}, "com.apple.iokit.IOSCSIArchitectureModelFamily"=>{"size"=>102400, "version"=>"2.0.5", "index"=>"51", "refcount"=>"4"}, "org.virtualbox.kext.VBoxNetAdp"=>{"size"=>8192, "version"=>"2.2.0", "index"=>"117", "refcount"=>"0"}, "com.apple.filesystems.autofs"=>{"size"=>45056, "version"=>"2.0.1", "index"=>"109", "refcount"=>"0"}, "com.vmware.kext.vmnet"=>{"size"=>36864, "version"=>"2.0.4", "index"=>"108", "refcount"=>"0"}, "com.apple.iokit.IOSCSIBlockCommandsDevice"=>{"size"=>90112, "version"=>"2.0.5", "index"=>"57", "refcount"=>"1"}, "com.apple.driver.AppleACPIPCI"=>{"size"=>12288, "version"=>"1.2.4", "index"=>"31", "refcount"=>"0"}, "com.apple.security.seatbelt"=>{"size"=>98304, "version"=>"107.10", "index"=>"25", "refcount"=>"0"}, "com.apple.driver.AppleUpstreamUserClient"=>{"size"=>16384, "version"=>"2.7.2", "index"=>"100", "refcount"=>"0"}, "com.apple.kext.OSvKernDSPLib"=>{"size"=>12288, "version"=>"1.1", "index"=>"79", "refcount"=>"1"}, "com.apple.iokit.IOBDStorageFamily"=>{"size"=>20480, "version"=>"1.5", "index"=>"58", "refcount"=>"1"}, "com.apple.iokit.IOGraphicsFamily"=>{"size"=>118784, "version"=>"1.7.1", "index"=>"70", "refcount"=>"5"}, "com.apple.iokit.IONetworkingFamily"=>{"size"=>90112, "version"=>"1.6.1", "index"=>"82", "refcount"=>"4"}, "com.apple.iokit.IOATAFamily"=>{"size"=>53248, "version"=>"2.0.0", "index"=>"40", "refcount"=>"2"}, "com.apple.iokit.IOUSBHIDDriver"=>{"size"=>20480, "version"=>"3.2.2", "index"=>"63", "refcount"=>"2"}, "org.virtualbox.kext.VBoxUSB"=>{"size"=>28672, "version"=>"2.2.0", "index"=>"115", "refcount"=>"0"}, "com.apple.security.TMSafetyNet"=>{"size"=>12288, "version"=>"3", "index"=>"23", "refcount"=>"0"}, "com.apple.iokit.IONDRVSupport"=>{"size"=>57344, "version"=>"1.7.1", "index"=>"71", "refcount"=>"3"}, "com.apple.BootCache"=>{"size"=>20480, "version"=>"30.3", "index"=>"20", "refcount"=>"0"}, "com.vmware.kext.vmioplug"=>{"size"=>24576, "version"=>"2.0.4", "index"=>"107", "refcount"=>"0"}, "com.apple.iokit.IOUSBUserClient"=>{"size"=>8192, "version"=>"3.2.4", "index"=>"46", "refcount"=>"1"}, "com.apple.iokit.IOSCSIMultimediaCommandsDevice"=>{"size"=>90112, "version"=>"2.0.5", "index"=>"59", "refcount"=>"0"}, "com.apple.driver.AppleIRController"=>{"size"=>20480, "version"=>"110", "index"=>"78", "refcount"=>"0"}, "com.apple.driver.AudioIPCDriver"=>{"size"=>16384, "version"=>"1.0.5", "index"=>"81", "refcount"=>"0"}, "com.apple.driver.AppleLPC"=>{"size"=>12288, "version"=>"1.2.11", "index"=>"73", "refcount"=>"0"}, "org.virtualbox.kext.VBoxNetFlt"=>{"size"=>16384, "version"=>"2.2.0", "index"=>"116", "refcount"=>"0"}, "com.apple.iokit.CHUDKernLib"=>{"size"=>20480, "version"=>"196", "index"=>"93", "refcount"=>"2"}, "com.apple.iokit.CHUDProf"=>{"size"=>49152, "version"=>"207", "index"=>"97", "refcount"=>"0"}, "com.apple.NVDAResman"=>{"size"=>2478080, "version"=>"5.3.6", "index"=>"90", "refcount"=>"2"}, "com.apple.driver.AppleACPIEC"=>{"size"=>20480, "version"=>"1.2.4", "index"=>"28", "refcount"=>"0"}, "foo.tun"=>{"size"=>24576, "version"=>"1.0", "index"=>"118", "refcount"=>"0"}, "com.apple.iokit.IOSerialFamily"=>{"size"=>36864, "version"=>"9.3", "index"=>"102", "refcount"=>"1"}, "com.apple.GeForce"=>{"size"=>622592, "version"=>"5.3.6", "index"=>"96", "refcount"=>"0"}, "com.apple.iokit.IOCDStorageFamily"=>{"size"=>32768, "version"=>"1.5", "index"=>"55", "refcount"=>"3"}, "com.apple.driver.AppleUSBEHCI"=>{"size"=>73728, "version"=>"3.2.5", "index"=>"39", "refcount"=>"0"}, "com.apple.nvidia.nv50hal"=>{"size"=>2445312, "version"=>"5.3.6", "index"=>"91", "refcount"=>"0"}, "com.apple.driver.AppleSMBIOS"=>{"size"=>16384, "version"=>"1.1.1", "index"=>"29", "refcount"=>"0"}, "com.apple.driver.AppleBacklight"=>{"size"=>16384, "version"=>"1.4.4", "index"=>"72", "refcount"=>"0"}, "com.apple.driver.AppleACPIPlatform"=>{"size"=>253952, "version"=>"1.2.4", "index"=>"19", "refcount"=>"3"}, "com.apple.iokit.SCSITaskUserClient"=>{"size"=>24576, "version"=>"2.0.5", "index"=>"54", "refcount"=>"0"}, "com.apple.iokit.IOHIDFamily"=>{"size"=>233472, "version"=>"1.5.3", "index"=>"21", "refcount"=>"7"}, "com.apple.driver.DiskImages"=>{"size"=>65536, "version"=>"195.2.2", "index"=>"101", "refcount"=>"0"}, "com.apple.iokit.IODVDStorageFamily"=>{"size"=>24576, "version"=>"1.5", "index"=>"56", "refcount"=>"2"}, "com.apple.iokit.IOFireWireIP"=>{"size"=>36864, "version"=>"1.7.6", "index"=>"83", "refcount"=>"0"}, "com.apple.driver.AppleRTC"=>{"size"=>20480, "version"=>"1.2.3", "index"=>"34", "refcount"=>"0"}, "com.apple.driver.XsanFilter"=>{"size"=>20480, "version"=>"2.7.91", "index"=>"53", "refcount"=>"0"}, "com.apple.driver.AppleEFIRuntime"=>{"size"=>12288, "version"=>"1.2.0", "index"=>"35", "refcount"=>"1"}, "com.apple.iokit.IOAHCIBlockStorage"=>{"size"=>69632, "version"=>"1.2.0", "index"=>"48", "refcount"=>"0"}, "com.apple.nke.applicationfirewall"=>{"size"=>32768, "version"=>"1.0.77", "index"=>"24", "refcount"=>"0"}, "com.apple.iokit.IO80211Family"=>{"size"=>126976, "version"=>"215.1", "index"=>"87", "refcount"=>"1"}, "com.vmware.kext.vmci"=>{"size"=>45056, "version"=>"2.0.4", "index"=>"106", "refcount"=>"0"}, "com.apple.iokit.IOAHCIFamily"=>{"size"=>24576, "version"=>"1.5.0", "index"=>"42", "refcount"=>"2"}, "com.apple.driver.AppleUSBUHCI"=>{"size"=>57344, "version"=>"3.2.5", "index"=>"38", "refcount"=>"0"}, "com.apple.driver.AppleUSBMergeNub"=>{"size"=>12288, "version"=>"3.2.4", "index"=>"61", "refcount"=>"0"}, "com.apple.iokit.IOUSBFamily"=>{"size"=>167936, "version"=>"3.2.7", "index"=>"37", "refcount"=>"13"}, "com.apple.driver.AppleEFINVRAM"=>{"size"=>24576, "version"=>"1.2.0", "index"=>"36", "refcount"=>"0"}, "com.apple.driver.AppleAHCIPort"=>{"size"=>53248, "version"=>"1.5.2", "index"=>"43", "refcount"=>"0"}}, "os"=>"Darwin", "version"=>"Darwin Kernel Version 9.6.0: Mon Nov 24 17:37:00 PST 2008; root:xnu-1228.9.59~1/RELEASE_I386", "release"=>"9.6.0"}, "command"=>{"ps"=>"ps -ef"}, "platform"=>"mac_os_x", "platform_version"=>"10.5.6", "keys"=>{"ssh"=>{"host_dsa_public"=>"private", "host_rsa_public"=>"private"}}, "ipaddress"=>"192.168.88.1", "fqdn"=>"local.local", "network"=>{"settings"=>{"net.inet6.ip6.forwarding"=>"0", "net.inet.ip.dummynet.debug"=>"0", "net.inet.ip.rtexpire"=>"10", "net.inet6.ipsec6.esp_trans_deflev"=>"1", "net.inet.tcp.tcbhashsize"=>"4096", "net.key.esp_auth"=>"0", "net.inet6.ip6.hlim"=>"64", "net.inet.ip.fw.dyn_fin_lifetime"=>"1", "net.inet.ip.fw.dyn_udp_lifetime"=>"10", "net.inet.icmp.bmcastecho"=>"1", "net.athbgscan"=>"1 1", "net.inet.tcp.reass.maxsegments"=>"2048", "net.athforceBias"=>"2 2", "net.inet6.ip6.auto_flowlabel"=>"1", "net.inet6.ip6.rtmaxcache"=>"128", "net.inet.tcp.sendspace"=>"131072", "net.inet.tcp.keepinit"=>"75000", "net.inet.ip.dummynet.max_chain_len"=>"16", "net.inet.tcp.rfc1644"=>"0", "net.inet.ip.fw.curr_dyn_buckets"=>"256", "net.inet.ip.dummynet.ready_heap"=>"0", "net.inet.ip.portrange.first"=>"49152", "net.inet.tcp.background_io_trigger"=>"5", "net.link.ether.inet.host_down_time"=>"20", "net.inet6.ipsec6.def_policy"=>"1", "net.inet6.ipsec6.ecn"=>"0", "net.inet.ip.fastforwarding"=>"0", "net.inet6.ip6.v6only"=>"0", "net.inet.tcp.sack"=>"1", "net.inet6.ip6.rtexpire"=>"3600", "net.link.ether.inet.proxyall"=>"0", "net.athaddbaignore"=>"0 0", "net.inet6.ip6.keepfaith"=>"0", "net.key.spi_trycnt"=>"1000", "net.link.ether.inet.prune_intvl"=>"300", "net.inet.tcp.ecn_initiate_out"=>"0", "net.inet.ip.fw.dyn_rst_lifetime"=>"1", "net.local.stream.sendspace"=>"8192", "net.inet.tcp.socket_unlocked_on_output"=>"1", "net.inet.ip.fw.verbose_limit"=>"0", "net.local.dgram.recvspace"=>"4096", "net.inet.ipsec.debug"=>"0", "net.link.ether.inet.log_arp_warnings"=>"0", "net.inet.tcp.ecn_negotiate_in"=>"0", "net.inet.tcp.rfc3465"=>"1", "net.inet.tcp.icmp_may_rst"=>"1", "net.link.ether.inet.sendllconflict"=>"0", "net.inet.ipsec.ah_offsetmask"=>"0", "net.key.blockacq_count"=>"10", "net.inet.tcp.delayed_ack"=>"3", "net.inet.ip.fw.verbose"=>"2", "net.inet.ip.fw.dyn_count"=>"0", "net.inet.tcp.slowlink_wsize"=>"8192", "net.inet6.ip6.fw.enable"=>"1", "net.inet.ip.portrange.hilast"=>"65535", "net.inet.icmp.maskrepl"=>"0", "net.link.ether.inet.apple_hwcksum_rx"=>"1", "net.inet.tcp.drop_synfin"=>"1", "net.key.spi_maxval"=>"268435455", "net.inet.ipsec.ecn"=>"0", "net.inet.ip.fw.dyn_keepalive"=>"1", "net.key.int_random"=>"60", "net.key.debug"=>"0", "net.inet.ip.dummynet.curr_time"=>"0", "net.inet.udp.blackhole"=>"0", "net.athaggrqmin"=>"1 1", "net.inet.ip.fw.dyn_syn_lifetime"=>"20", "net.inet.tcp.keepidle"=>"7200000", "net.inet6.ip6.tempvltime"=>"604800", "net.inet.tcp.recvspace"=>"358400", "net.inet.udp.maxdgram"=>"9216", "net.inet.tcp.keepintvl"=>"75000", "net.inet.ip.maxchainsent"=>"0", "net.athppmenable"=>"1 1", "net.inet.ipsec.esp_net_deflev"=>"1", "net.inet6.icmp6.nd6_useloopback"=>"1", "net.inet.tcp.slowstart_flightsize"=>"1", "net.inet.ip.fw.debug"=>"0", "net.inet.ip.linklocal.in.allowbadttl"=>"1", "net.key.spi_minval"=>"256", "net.inet.ip.forwarding"=>"0", "net.inet.tcp.v6mssdflt"=>"1024", "net.key.larval_lifetime"=>"30", "net.inet6.ip6.fw.verbose_limit"=>"0", "net.inet.ip.dummynet.red_lookup_depth"=>"256", "net.inet.tcp.pcbcount"=>"36", "net.inet.ip.fw.dyn_ack_lifetime"=>"300", "net.athCCAThreshold"=>"28 28", "net.inet.ip.portrange.lowlast"=>"600", "net.link.ether.inet.useloopback"=>"1", "net.athqdepth"=>"0 0", "net.inet.ip.ttl"=>"64", "net.inet.ip.rtmaxcache"=>"128", "net.inet.ipsec.bypass"=>"0", "net.inet6.icmp6.nd6_debug"=>"0", "net.inet.ip.use_route_genid"=>"1", "net.inet6.icmp6.rediraccept"=>"1", "net.inet.ip.fw.static_count"=>"1", "net.inet6.ip6.fw.debug"=>"0", "net.inet.udp.pcbcount"=>"104", "net.inet.ipsec.esp_randpad"=>"-1", "net.inet6.icmp6.nd6_maxnudhint"=>"0", "net.inet.tcp.always_keepalive"=>"0", "net.inet.udp.checksum"=>"1", "net.link.ether.inet.keep_announcements"=>"1", "net.athfixedDropThresh"=>"150 150", "net.inet6.ip6.kame_version"=>"20010528/apple-darwin", "net.inet.ip.fw.dyn_max"=>"4096", "net.inet.udp.log_in_vain"=>"0", "net.inet6.icmp6.nd6_mmaxtries"=>"3", "net.inet.ip.rtminexpire"=>"10", "net.inet.ip.fw.dyn_buckets"=>"256", "net.inet6.ip6.accept_rtadv"=>"0", "net.inet6.ip6.rr_prune"=>"5", "net.key.ah_keymin"=>"128", "net.inet.ip.redirect"=>"1", "net.inet.tcp.sack_globalmaxholes"=>"65536", "net.inet.ip.keepfaith"=>"0", "net.inet.ip.dummynet.expire"=>"1", "net.inet.ip.gifttl"=>"30", "net.inet.ip.portrange.last"=>"65535", "net.inet.ipsec.ah_net_deflev"=>"1", "net.inet6.icmp6.nd6_delay"=>"5", "net.inet.tcp.packetchain"=>"50", "net.inet6.ip6.hdrnestlimit"=>"50", "net.inet.tcp.newreno"=>"0", "net.inet6.ip6.dad_count"=>"1", "net.inet6.ip6.auto_linklocal"=>"1", "net.inet6.ip6.temppltime"=>"86400", "net.inet.tcp.strict_rfc1948"=>"0", "net.inet.ip.dummynet.red_max_pkt_size"=>"1500", "net.inet.ip.maxfrags"=>"2048", "net.inet.tcp.log_in_vain"=>"0", "net.athdupie"=>"1 1", "net.inet.tcp.rfc1323"=>"1", "net.inet.ip.subnets_are_local"=>"0", "net.inet.ip.dummynet.search_steps"=>"0", "net.inet.icmp.icmplim"=>"250", "net.link.ether.inet.apple_hwcksum_tx"=>"1", "net.inet6.icmp6.redirtimeout"=>"600", "net.inet.ipsec.ah_cleartos"=>"1", "net.inet6.ip6.log_interval"=>"5", "net.link.ether.inet.max_age"=>"1200", "net.inet.ip.fw.enable"=>"1", "net.inet6.ip6.redirect"=>"1", "net.athaggrfmax"=>"28 28", "net.inet.ip.maxfragsperpacket"=>"128", "net.inet6.ip6.use_deprecated"=>"1", "net.link.generic.system.dlil_input_sanity_check"=>"0", "net.inet.tcp.sack_globalholes"=>"0", "net.inet.tcp.reass.cursegments"=>"0", "net.inet6.icmp6.nodeinfo"=>"3", "net.local.inflight"=>"0", "net.inet.ip.dummynet.hash_size"=>"64", "net.inet.ip.dummynet.red_avg_pkt_size"=>"512", "net.inet.ipsec.dfbit"=>"0", "net.inet.tcp.reass.overflows"=>"0", "net.inet.tcp.rexmt_thresh"=>"2", "net.inet6.ip6.maxfrags"=>"8192", "net.inet6.ip6.rtminexpire"=>"10", "net.inet6.ipsec6.esp_net_deflev"=>"1", "net.inet.tcp.blackhole"=>"0", "net.key.esp_keymin"=>"256", "net.inet.ip.check_interface"=>"0", "net.inet.tcp.minmssoverload"=>"0", "net.link.ether.inet.maxtries"=>"5", "net.inet.tcp.do_tcpdrain"=>"0", "net.inet.ipsec.esp_port"=>"4500", "net.inet6.ipsec6.ah_net_deflev"=>"1", "net.inet.ip.dummynet.extract_heap"=>"0", "net.inet.tcp.path_mtu_discovery"=>"1", "net.inet.ip.intr_queue_maxlen"=>"50", "net.inet.ipsec.def_policy"=>"1", "net.inet.ip.fw.autoinc_step"=>"100", "net.inet.ip.accept_sourceroute"=>"0", "net.inet.raw.maxdgram"=>"8192", "net.inet.ip.maxfragpackets"=>"1024", "net.inet.ip.fw.one_pass"=>"0", "net.appletalk.routermix"=>"2000", "net.inet.tcp.tcp_lq_overflow"=>"1", "net.link.generic.system.ifcount"=>"9", "net.link.ether.inet.send_conflicting_probes"=>"1", "net.inet.tcp.background_io_enabled"=>"1", "net.inet6.ipsec6.debug"=>"0", "net.inet.tcp.win_scale_factor"=>"3", "net.key.natt_keepalive_interval"=>"20", "net.inet.tcp.msl"=>"15000", "net.inet.ip.portrange.hifirst"=>"49152", "net.inet.ipsec.ah_trans_deflev"=>"1", "net.inet.tcp.rtt_min"=>"1", "net.inet6.ip6.defmcasthlim"=>"1", "net.inet6.icmp6.nd6_prune"=>"1", "net.inet6.ip6.fw.verbose"=>"0", "net.inet.ip.portrange.lowfirst"=>"1023", "net.inet.tcp.maxseg_unacked"=>"8", "net.local.dgram.maxdgram"=>"2048", "net.key.blockacq_lifetime"=>"20", "net.inet.tcp.sack_maxholes"=>"128", "net.inet6.ip6.maxfragpackets"=>"1024", "net.inet6.ip6.use_tempaddr"=>"0", "net.athpowermode"=>"0 0", "net.inet.udp.recvspace"=>"73728", "net.inet.tcp.isn_reseed_interval"=>"0", "net.inet.tcp.local_slowstart_flightsize"=>"8", "net.inet.ip.dummynet.searches"=>"0", "net.inet.ip.intr_queue_drops"=>"0", "net.link.generic.system.multi_threaded_input"=>"1", "net.inet.raw.recvspace"=>"8192", "net.inet.ipsec.esp_trans_deflev"=>"1", "net.key.prefered_oldsa"=>"0", "net.local.stream.recvspace"=>"8192", "net.inet.tcp.sockthreshold"=>"64", "net.inet6.icmp6.nd6_umaxtries"=>"3", "net.pstimeout"=>"20 20", "net.inet.ip.sourceroute"=>"0", "net.inet.ip.fw.dyn_short_lifetime"=>"5", "net.inet.tcp.minmss"=>"216", "net.inet6.ip6.gifhlim"=>"0", "net.athvendorie"=>"1 1", "net.inet.ip.check_route_selfref"=>"1", "net.inet.icmp.log_redirect"=>"0", "net.inet6.icmp6.errppslimit"=>"100", "net.inet.tcp.mssdflt"=>"512", "net.inet.icmp.drop_redirect"=>"0", "net.inet6.ipsec6.esp_randpad"=>"-1", "net.inet6.ipsec6.ah_trans_deflev"=>"1", "net.inet.ip.random_id"=>"1", "net.inet.icmp.timestamp"=>"0"}, "interfaces"=>{"stf0"=>{"flags"=>[], "number"=>"0", "mtu"=>"1280", "type"=>"stf", "encapsulation"=>"6to4"}, "vmnet1"=>{"flags"=>["UP", "BROADCAST", "SMART", "RUNNING", "SIMPLEX", "MULTICAST"], "number"=>"1", "addresses"=>[{"broadcast"=>"192.168.88.255", "netmask"=>"255.255.255.0", "family"=>"inet", "address"=>"192.168.88.1"}, {"family"=>"lladdr", "address"=>"private"}], "mtu"=>"1500", "type"=>"vmnet", "encapsulation"=>"Ethernet"}, "vboxnet0"=>{"flags"=>["BROADCAST", "RUNNING", "SIMPLEX", "MULTICAST"], "number"=>"0", "addresses"=>[{"family"=>"lladdr", "address"=>"private"}], "mtu"=>"1500", "type"=>"vboxnet", "encapsulation"=>"Ethernet"}, "lo0"=>{"flags"=>["UP", "LOOPBACK", "RUNNING", "MULTICAST"], "number"=>"0", "addresses"=>[{"scope"=>"Link", "prefixlen"=>"64", "family"=>"inet6", "address"=>"fe80::1"}, {"netmask"=>"255.0.0.0", "family"=>"inet", "address"=>"127.0.0.1"}, {"scope"=>"Node", "prefixlen"=>"128", "family"=>"inet6", "address"=>"::1"}, {"scope"=>"Node", "prefixlen"=>"128", "family"=>"inet6", "address"=>"private"}], "mtu"=>"16384", "type"=>"lo", "encapsulation"=>"Loopback"}, "vboxn"=>{"counters"=>{"tx"=>{"packets"=>"0", "bytes"=>"0", "compressed"=>0, "collisions"=>"0", "carrier"=>0, "errors"=>"0", "drop"=>0, "overrun"=>0}, "rx"=>{"packets"=>"0", "bytes"=>"0", "compressed"=>0, "errors"=>"0", "drop"=>0, "overrun"=>0, "multicast"=>0, "frame"=>0}}}, "gif0"=>{"flags"=>["POINTOPOINT", "MULTICAST"], "number"=>"0", "mtu"=>"1280", "type"=>"gif", "encapsulation"=>"IPIP"}, "vmnet"=>{"counters"=>{"tx"=>{"packets"=>"0", "bytes"=>"0", "compressed"=>0, "collisions"=>"0", "carrier"=>0, "errors"=>"0", "drop"=>0, "overrun"=>0}, "rx"=>{"packets"=>"0", "bytes"=>"0", "compressed"=>0, "errors"=>"0", "drop"=>0, "overrun"=>0, "multicast"=>0, "frame"=>0}}}, "en0"=>{"flags"=>["UP", "BROADCAST", "SMART", "RUNNING", "SIMPLEX", "MULTICAST"], "status"=>"inactive", "number"=>"0", "addresses"=>[{"family"=>"lladdr", "address"=>"private"}], "mtu"=>"1500", "type"=>"en", "media"=>{"supported"=>[{"autoselect"=>{"options"=>[]}}, {"10baseT/UTP"=>{"options"=>["half-duplex"]}}, {"10baseT/UTP"=>{"options"=>["full-duplex"]}}, {"10baseT/UTP"=>{"options"=>["full-duplex", "hw-loopback"]}}, {"10baseT/UTP"=>{"options"=>["full-duplex", "flow-control"]}}, {"100baseTX"=>{"options"=>["half-duplex"]}}, {"100baseTX"=>{"options"=>["full-duplex"]}}, {"100baseTX"=>{"options"=>["full-duplex", "hw-loopback"]}}, {"100baseTX"=>{"options"=>["full-duplex", "flow-control"]}}, {"1000baseT"=>{"options"=>["full-duplex"]}}, {"1000baseT"=>{"options"=>["full-duplex", "hw-loopback"]}}, {"1000baseT"=>{"options"=>["full-duplex", "flow-control"]}}, {"none"=>{"options"=>[]}}], "selected"=>[{"autoselect"=>{"options"=>[]}}]}, "counters"=>{"tx"=>{"packets"=>"0", "bytes"=>"342", "compressed"=>0, "collisions"=>"0", "carrier"=>0, "errors"=>"0", "drop"=>0, "overrun"=>0}, "rx"=>{"packets"=>"0", "bytes"=>"0", "compressed"=>0, "errors"=>"0", "drop"=>0, "overrun"=>0, "multicast"=>0, "frame"=>0}}, "encapsulation"=>"Ethernet"}, "vmnet8"=>{"flags"=>["UP", "BROADCAST", "SMART", "RUNNING", "SIMPLEX", "MULTICAST"], "number"=>"8", "addresses"=>[{"broadcast"=>"192.168.237.255", "netmask"=>"255.255.255.0", "family"=>"inet", "address"=>"192.168.237.1"}, {"family"=>"lladdr", "address"=>"private"}], "mtu"=>"1500", "type"=>"vmnet", "encapsulation"=>"Ethernet"}, "en1"=>{"flags"=>["UP", "BROADCAST", "SMART", "RUNNING", "SIMPLEX", "MULTICAST"], "status"=>"active", "number"=>"1", "addresses"=>[{"scope"=>"Link", "prefixlen"=>"64", "family"=>"inet6", "address"=>"private"}, {"broadcast"=>"192.168.1.255", "netmask"=>"255.255.255.0", "family"=>"inet", "address"=>"192.168.1.4"}, {"family"=>"lladdr", "address"=>"private"}], "mtu"=>"1500", "type"=>"en", "media"=>{"supported"=>[{"autoselect"=>{"options"=>[]}}], "selected"=>[{"autoselect"=>{"options"=>[]}}]}, "counters"=>{"tx"=>{"packets"=>"7041789", "bytes"=>"449206298", "compressed"=>0, "collisions"=>"0", "carrier"=>0, "errors"=>"95", "drop"=>0, "overrun"=>0}, "rx"=>{"packets"=>"19966002", "bytes"=>"13673879120", "compressed"=>0, "errors"=>"1655893", "drop"=>0, "overrun"=>0, "multicast"=>0, "frame"=>0}}, "encapsulation"=>"Ethernet", "arp"=>{"192.168.1.7"=>"private"}}, "fw0"=>{"flags"=>["UP", "BROADCAST", "SMART", "RUNNING", "SIMPLEX", "MULTICAST"], "status"=>"inactive", "number"=>"0", "addresses"=>[{"family"=>"lladdr", "address"=>"private"}], "mtu"=>"4078", "type"=>"fw", "media"=>{"supported"=>[{"autoselect"=>{"options"=>["full-duplex"]}}], "selected"=>[{"autoselect"=>{"options"=>["full-duplex"]}}]}, "counters"=>{"tx"=>{"packets"=>"0", "bytes"=>"346", "compressed"=>0, "collisions"=>"0", "carrier"=>0, "errors"=>"0", "drop"=>0, "overrun"=>0}, "rx"=>{"packets"=>"0", "bytes"=>"0", "compressed"=>0, "errors"=>"0", "drop"=>0, "overrun"=>0, "multicast"=>0, "frame"=>0}}, "encapsulation"=>"1394"}}}, "os"=>"darwin", "domain"=>"local", "ohai_time"=>1240624355.08575, "platform_build"=>"9G55", "os_version"=>"9.6.0", "hostname"=>"local", "languages"=>{"ruby"=>{"target_os"=>"darwin9.0", "platform"=>"universal-darwin9.0", "host_vendor"=>"apple", "target_cpu"=>"i686", "target_vendor"=>"apple", "host_os"=>"darwin9.0", "version"=>"1.8.6", "host_cpu"=>"i686", "host"=>"i686-apple-darwin9.0", "release_date"=>"2008-03-03", "target"=>"i686-apple-darwin9.0"}}, "macaddress"=>"private"}
|
@@ -0,0 +1,251 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# CODING: UTF-8
|
3
|
+
|
4
|
+
require 'rbconfig'
|
5
|
+
RUBY_PATH=File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
|
6
|
+
RAKE_PATH=File.join(Config::CONFIG['bindir'], 'rake')
|
7
|
+
require 'bullshit'
|
8
|
+
case ARGV.first
|
9
|
+
when 'ext'
|
10
|
+
require 'json/ext'
|
11
|
+
when 'pure'
|
12
|
+
require 'json/pure'
|
13
|
+
when 'yaml'
|
14
|
+
require 'yaml'
|
15
|
+
require 'json/pure'
|
16
|
+
when 'rails'
|
17
|
+
require 'active_support'
|
18
|
+
require 'json/pure'
|
19
|
+
when 'yajl'
|
20
|
+
require 'yajl'
|
21
|
+
require 'json/pure'
|
22
|
+
else
|
23
|
+
require 'json/pure'
|
24
|
+
end
|
25
|
+
|
26
|
+
module Parser2BenchmarkCommon
|
27
|
+
include JSON
|
28
|
+
|
29
|
+
def setup
|
30
|
+
@big = @json = File.read(File.join(File.dirname(__FILE__), 'ohai.json'))
|
31
|
+
end
|
32
|
+
|
33
|
+
def generic_reset_method
|
34
|
+
@result == @big or raise "not equal"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Parser2BenchmarkExt < Bullshit::RepeatCase
|
39
|
+
include Parser2BenchmarkCommon
|
40
|
+
|
41
|
+
warmup yes
|
42
|
+
iterations 2000
|
43
|
+
|
44
|
+
truncate_data do
|
45
|
+
enabled false
|
46
|
+
alpha_level 0.05
|
47
|
+
window_size 50
|
48
|
+
slope_angle 0.1
|
49
|
+
end
|
50
|
+
|
51
|
+
autocorrelation do
|
52
|
+
alpha_level 0.05
|
53
|
+
max_lags 50
|
54
|
+
file yes
|
55
|
+
end
|
56
|
+
|
57
|
+
output_dir File.join(File.dirname(__FILE__), 'data')
|
58
|
+
output_filename benchmark_name + '.log'
|
59
|
+
data_file yes
|
60
|
+
histogram yes
|
61
|
+
|
62
|
+
def benchmark_parser
|
63
|
+
@result = JSON.parse(@json)
|
64
|
+
end
|
65
|
+
|
66
|
+
alias reset_parser generic_reset_method
|
67
|
+
|
68
|
+
def benchmark_parser_symbolic
|
69
|
+
@result = JSON.parse(@json, :symbolize_names => true)
|
70
|
+
end
|
71
|
+
|
72
|
+
alias reset_parser_symbolc generic_reset_method
|
73
|
+
end
|
74
|
+
|
75
|
+
class Parser2BenchmarkPure < Bullshit::RepeatCase
|
76
|
+
include Parser2BenchmarkCommon
|
77
|
+
|
78
|
+
warmup yes
|
79
|
+
iterations 400
|
80
|
+
|
81
|
+
truncate_data do
|
82
|
+
enabled false
|
83
|
+
alpha_level 0.05
|
84
|
+
window_size 50
|
85
|
+
slope_angle 0.1
|
86
|
+
end
|
87
|
+
|
88
|
+
autocorrelation do
|
89
|
+
alpha_level 0.05
|
90
|
+
max_lags 50
|
91
|
+
file yes
|
92
|
+
end
|
93
|
+
|
94
|
+
output_dir File.join(File.dirname(__FILE__), 'data')
|
95
|
+
output_filename benchmark_name + '.log'
|
96
|
+
data_file yes
|
97
|
+
histogram yes
|
98
|
+
|
99
|
+
def benchmark_parser
|
100
|
+
@result = JSON.parse(@json)
|
101
|
+
end
|
102
|
+
|
103
|
+
alias reset_parser generic_reset_method
|
104
|
+
|
105
|
+
def benchmark_parser_symbolic
|
106
|
+
@result = JSON.parse(@json, :symbolize_names => true)
|
107
|
+
end
|
108
|
+
|
109
|
+
alias reset_parser_symbolc generic_reset_method
|
110
|
+
end
|
111
|
+
|
112
|
+
class Parser2BenchmarkYAML < Bullshit::RepeatCase
|
113
|
+
warmup yes
|
114
|
+
iterations 400
|
115
|
+
|
116
|
+
truncate_data do
|
117
|
+
enabled false
|
118
|
+
alpha_level 0.05
|
119
|
+
window_size 50
|
120
|
+
slope_angle 0.1
|
121
|
+
end
|
122
|
+
|
123
|
+
autocorrelation do
|
124
|
+
alpha_level 0.05
|
125
|
+
max_lags 50
|
126
|
+
file yes
|
127
|
+
end
|
128
|
+
|
129
|
+
output_dir File.join(File.dirname(__FILE__), 'data')
|
130
|
+
output_filename benchmark_name + '.log'
|
131
|
+
data_file yes
|
132
|
+
histogram yes
|
133
|
+
|
134
|
+
def setup
|
135
|
+
@big = @json = File.read(File.join(File.dirname(__FILE__), 'ohai.json'))
|
136
|
+
end
|
137
|
+
|
138
|
+
def benchmark_parser
|
139
|
+
@result = YAML.load(@json)
|
140
|
+
end
|
141
|
+
|
142
|
+
def generic_reset_method
|
143
|
+
@result == @big or raise "not equal"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
class Parser2BenchmarkRails < Bullshit::RepeatCase
|
148
|
+
warmup yes
|
149
|
+
iterations 400
|
150
|
+
|
151
|
+
truncate_data do
|
152
|
+
alpha_level 0.05
|
153
|
+
window_size 50
|
154
|
+
slope_angle 0.1
|
155
|
+
end
|
156
|
+
|
157
|
+
autocorrelation do
|
158
|
+
alpha_level 0.05
|
159
|
+
max_lags 50
|
160
|
+
file yes
|
161
|
+
end
|
162
|
+
|
163
|
+
output_dir File.join(File.dirname(__FILE__), 'data')
|
164
|
+
output_filename benchmark_name + '.log'
|
165
|
+
data_file yes
|
166
|
+
histogram yes
|
167
|
+
|
168
|
+
def setup
|
169
|
+
a = [ nil, false, true, "fÖß\nÄr", [ "n€st€d", true ], { "fooß" => "bär", "qu\r\nux" => true } ]
|
170
|
+
@big = a * 100
|
171
|
+
@json = JSON.generate(@big)
|
172
|
+
end
|
173
|
+
|
174
|
+
def benchmark_parser
|
175
|
+
@result = ActiveSupport::JSON.decode(@json)
|
176
|
+
end
|
177
|
+
|
178
|
+
def generic_reset_method
|
179
|
+
@result == @big or raise "not equal"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
class Parser2BenchmarkYajl < Bullshit::RepeatCase
|
184
|
+
warmup yes
|
185
|
+
iterations 2000
|
186
|
+
|
187
|
+
truncate_data do
|
188
|
+
alpha_level 0.05
|
189
|
+
window_size 50
|
190
|
+
slope_angle 0.1
|
191
|
+
end
|
192
|
+
|
193
|
+
autocorrelation do
|
194
|
+
alpha_level 0.05
|
195
|
+
max_lags 50
|
196
|
+
file yes
|
197
|
+
end
|
198
|
+
|
199
|
+
output_dir File.join(File.dirname(__FILE__), 'data')
|
200
|
+
output_filename benchmark_name + '.log'
|
201
|
+
data_file yes
|
202
|
+
histogram yes
|
203
|
+
|
204
|
+
def setup
|
205
|
+
@big = @json = File.read(File.join(File.dirname(__FILE__), 'ohai.json'))
|
206
|
+
end
|
207
|
+
|
208
|
+
def benchmark_parser
|
209
|
+
@result = Yajl::Parser.new.parse(@json)
|
210
|
+
end
|
211
|
+
|
212
|
+
def generic_reset_method
|
213
|
+
@result == @big or raise "not equal"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
if $0 == __FILE__
|
218
|
+
Bullshit::Case.autorun false
|
219
|
+
|
220
|
+
case ARGV.first
|
221
|
+
when 'ext'
|
222
|
+
Parser2BenchmarkExt.run
|
223
|
+
when 'pure'
|
224
|
+
Parser2BenchmarkPure.run
|
225
|
+
when 'yaml'
|
226
|
+
Parser2BenchmarkYAML.run
|
227
|
+
when 'rails'
|
228
|
+
Parser2BenchmarkRails.run
|
229
|
+
when 'yajl'
|
230
|
+
Parser2BenchmarkYajl.run
|
231
|
+
else
|
232
|
+
system "#{RAKE_PATH} clean"
|
233
|
+
system "#{RUBY_PATH} #$0 yaml"
|
234
|
+
system "#{RUBY_PATH} #$0 rails"
|
235
|
+
system "#{RUBY_PATH} #$0 pure"
|
236
|
+
system "#{RAKE_PATH} compile_ext"
|
237
|
+
system "#{RUBY_PATH} #$0 ext"
|
238
|
+
system "#{RUBY_PATH} #$0 yajl"
|
239
|
+
Bullshit.compare do
|
240
|
+
output_filename File.join(File.dirname(__FILE__), 'data', 'Parser2BenchmarkComparison.log')
|
241
|
+
|
242
|
+
benchmark Parser2BenchmarkExt, :parser, :load => yes
|
243
|
+
benchmark Parser2BenchmarkExt, :parser_symbolic, :load => yes
|
244
|
+
benchmark Parser2BenchmarkPure, :parser, :load => yes
|
245
|
+
benchmark Parser2BenchmarkPure, :parser_symbolic, :load => yes
|
246
|
+
benchmark Parser2BenchmarkYAML, :parser, :load => yes
|
247
|
+
benchmark Parser2BenchmarkRails, :parser, :load => yes
|
248
|
+
benchmark Parser2BenchmarkYajl, :parser, :load => yes
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
@@ -16,6 +16,9 @@ when 'yaml'
|
|
16
16
|
when 'rails'
|
17
17
|
require 'active_support'
|
18
18
|
require 'json/pure'
|
19
|
+
when 'yajl'
|
20
|
+
require 'yajl'
|
21
|
+
require 'json/pure'
|
19
22
|
else
|
20
23
|
require 'json/pure'
|
21
24
|
end
|
@@ -38,9 +41,10 @@ class ParserBenchmarkExt < Bullshit::RepeatCase
|
|
38
41
|
include ParserBenchmarkCommon
|
39
42
|
|
40
43
|
warmup yes
|
41
|
-
iterations
|
44
|
+
iterations 2000
|
42
45
|
|
43
46
|
truncate_data do
|
47
|
+
enabled false
|
44
48
|
alpha_level 0.05
|
45
49
|
window_size 50
|
46
50
|
slope_angle 0.1
|
@@ -62,15 +66,22 @@ class ParserBenchmarkExt < Bullshit::RepeatCase
|
|
62
66
|
end
|
63
67
|
|
64
68
|
alias reset_parser generic_reset_method
|
69
|
+
|
70
|
+
def benchmark_parser_symbolic
|
71
|
+
@result = JSON.parse(@json, :symbolize_names => true)
|
72
|
+
end
|
73
|
+
|
74
|
+
alias reset_parser_symbolc generic_reset_method
|
65
75
|
end
|
66
76
|
|
67
77
|
class ParserBenchmarkPure < Bullshit::RepeatCase
|
68
78
|
include ParserBenchmarkCommon
|
69
79
|
|
70
80
|
warmup yes
|
71
|
-
iterations
|
81
|
+
iterations 400
|
72
82
|
|
73
83
|
truncate_data do
|
84
|
+
enabled false
|
74
85
|
alpha_level 0.05
|
75
86
|
window_size 50
|
76
87
|
slope_angle 0.1
|
@@ -92,13 +103,20 @@ class ParserBenchmarkPure < Bullshit::RepeatCase
|
|
92
103
|
end
|
93
104
|
|
94
105
|
alias reset_parser generic_reset_method
|
106
|
+
|
107
|
+
def benchmark_parser_symbolic
|
108
|
+
@result = JSON.parse(@json, :symbolize_names => true)
|
109
|
+
end
|
110
|
+
|
111
|
+
alias reset_parser_symbolc generic_reset_method
|
95
112
|
end
|
96
113
|
|
97
114
|
class ParserBenchmarkYAML < Bullshit::RepeatCase
|
98
115
|
warmup yes
|
99
|
-
iterations
|
116
|
+
iterations 400
|
100
117
|
|
101
118
|
truncate_data do
|
119
|
+
enabled false
|
102
120
|
alpha_level 0.05
|
103
121
|
window_size 50
|
104
122
|
slope_angle 0.1
|
@@ -132,9 +150,10 @@ end
|
|
132
150
|
|
133
151
|
class ParserBenchmarkRails < Bullshit::RepeatCase
|
134
152
|
warmup yes
|
135
|
-
iterations
|
153
|
+
iterations 400
|
136
154
|
|
137
155
|
truncate_data do
|
156
|
+
enabled false
|
138
157
|
alpha_level 0.05
|
139
158
|
window_size 50
|
140
159
|
slope_angle 0.1
|
@@ -166,6 +185,43 @@ class ParserBenchmarkRails < Bullshit::RepeatCase
|
|
166
185
|
end
|
167
186
|
end
|
168
187
|
|
188
|
+
class ParserBenchmarkYajl < Bullshit::RepeatCase
|
189
|
+
warmup yes
|
190
|
+
iterations 2000
|
191
|
+
|
192
|
+
truncate_data do
|
193
|
+
enabled false
|
194
|
+
alpha_level 0.05
|
195
|
+
window_size 50
|
196
|
+
slope_angle 0.1
|
197
|
+
end
|
198
|
+
|
199
|
+
autocorrelation do
|
200
|
+
alpha_level 0.05
|
201
|
+
max_lags 50
|
202
|
+
file yes
|
203
|
+
end
|
204
|
+
|
205
|
+
output_dir File.join(File.dirname(__FILE__), 'data')
|
206
|
+
output_filename benchmark_name + '.log'
|
207
|
+
data_file yes
|
208
|
+
histogram yes
|
209
|
+
|
210
|
+
def setup
|
211
|
+
a = [ nil, false, true, "fÖß\nÄr", [ "n€st€d", true ], { "fooß" => "bär", "qu\r\nux" => true } ]
|
212
|
+
@big = a * 100
|
213
|
+
@json = JSON.generate(@big)
|
214
|
+
end
|
215
|
+
|
216
|
+
def benchmark_parser
|
217
|
+
@result = Yajl::Parser.new.parse(@json)
|
218
|
+
end
|
219
|
+
|
220
|
+
def generic_reset_method
|
221
|
+
@result == @big or raise "not equal"
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
169
225
|
if $0 == __FILE__
|
170
226
|
Bullshit::Case.autorun false
|
171
227
|
|
@@ -178,20 +234,26 @@ if $0 == __FILE__
|
|
178
234
|
ParserBenchmarkYAML.run
|
179
235
|
when 'rails'
|
180
236
|
ParserBenchmarkRails.run
|
237
|
+
when 'yajl'
|
238
|
+
ParserBenchmarkYajl.run
|
181
239
|
else
|
182
240
|
system "#{RAKE_PATH} clean"
|
183
241
|
system "#{RUBY_PATH} #$0 yaml"
|
184
242
|
system "#{RUBY_PATH} #$0 rails"
|
185
243
|
system "#{RUBY_PATH} #$0 pure"
|
186
|
-
system "#{RAKE_PATH}
|
244
|
+
system "#{RAKE_PATH} compile_ext"
|
187
245
|
system "#{RUBY_PATH} #$0 ext"
|
246
|
+
system "#{RUBY_PATH} #$0 yajl"
|
188
247
|
Bullshit.compare do
|
189
248
|
output_filename File.join(File.dirname(__FILE__), 'data', 'ParserBenchmarkComparison.log')
|
190
249
|
|
191
250
|
benchmark ParserBenchmarkExt, :parser, :load => yes
|
251
|
+
benchmark ParserBenchmarkExt, :parser_symbolic, :load => yes
|
192
252
|
benchmark ParserBenchmarkPure, :parser, :load => yes
|
253
|
+
benchmark ParserBenchmarkPure, :parser_symbolic, :load => yes
|
193
254
|
benchmark ParserBenchmarkYAML, :parser, :load => yes
|
194
255
|
benchmark ParserBenchmarkRails, :parser, :load => yes
|
256
|
+
benchmark ParserBenchmarkYajl, :parser, :load => yes
|
195
257
|
end
|
196
258
|
end
|
197
259
|
end
|
@@ -1,11 +1,16 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
require 'rbconfig'
|
3
3
|
|
4
|
+
unless $CFLAGS.gsub!(/ -O[\dsz]?/, ' -O3')
|
5
|
+
$CFLAGS << ' -O3'
|
6
|
+
end
|
4
7
|
if CONFIG['CC'] =~ /gcc/
|
5
|
-
$CFLAGS
|
6
|
-
|
8
|
+
$CFLAGS << ' -Wall'
|
9
|
+
#unless $CFLAGS.gsub!(/ -O[\dsz]?/, ' -O0 -ggdb')
|
10
|
+
# $CFLAGS << ' -O0 -ggdb'
|
11
|
+
#end
|
7
12
|
end
|
8
13
|
|
9
|
-
have_header("ruby/
|
14
|
+
have_header("ruby/re.h") || have_header("re.h")
|
10
15
|
have_header("ruby/encoding.h")
|
11
|
-
create_makefile 'generator'
|
16
|
+
create_makefile 'json/ext/generator'
|
@@ -1,158 +1,424 @@
|
|
1
|
-
#include
|
2
|
-
#include "ruby.h"
|
3
|
-
#if HAVE_RUBY_ST_H
|
4
|
-
#include "ruby/st.h"
|
5
|
-
#endif
|
6
|
-
#if HAVE_ST_H
|
7
|
-
#include "st.h"
|
8
|
-
#endif
|
9
|
-
#include "unicode.h"
|
10
|
-
#include <math.h>
|
11
|
-
|
12
|
-
#ifndef RHASH_TBL
|
13
|
-
#define RHASH_TBL(hsh) (RHASH(hsh)->tbl)
|
14
|
-
#endif
|
15
|
-
|
16
|
-
#ifndef RHASH_SIZE
|
17
|
-
#define RHASH_SIZE(hsh) (RHASH(hsh)->tbl->num_entries)
|
18
|
-
#endif
|
19
|
-
|
20
|
-
#ifndef RFLOAT_VALUE
|
21
|
-
#define RFLOAT_VALUE(val) (RFLOAT(val)->value)
|
22
|
-
#endif
|
1
|
+
#include "generator.h"
|
23
2
|
|
24
3
|
#ifdef HAVE_RUBY_ENCODING_H
|
25
|
-
|
26
|
-
|
27
|
-
#else
|
28
|
-
#define FORCE_UTF8(obj)
|
4
|
+
static VALUE CEncoding_UTF_8;
|
5
|
+
static ID i_encoding, i_encode;
|
29
6
|
#endif
|
30
7
|
|
31
|
-
#define check_max_nesting(state, depth) do { \
|
32
|
-
long current_nesting = 1 + depth; \
|
33
|
-
if (state->max_nesting != 0 && current_nesting > state->max_nesting) \
|
34
|
-
rb_raise(eNestingError, "nesting of %ld is too deep", current_nesting); \
|
35
|
-
} while (0);
|
36
|
-
|
37
8
|
static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
|
38
9
|
mHash, mArray, mInteger, mFloat, mString, mString_Extend,
|
39
10
|
mTrueClass, mFalseClass, mNilClass, eGeneratorError,
|
40
|
-
|
11
|
+
eNestingError, CRegexp_MULTILINE, CJSON_SAFE_STATE_PROTOTYPE;
|
41
12
|
|
42
13
|
static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
|
43
|
-
i_object_nl, i_array_nl,
|
44
|
-
|
45
|
-
|
46
|
-
typedef struct JSON_Generator_StateStruct {
|
47
|
-
VALUE indent;
|
48
|
-
VALUE space;
|
49
|
-
VALUE space_before;
|
50
|
-
VALUE object_nl;
|
51
|
-
VALUE array_nl;
|
52
|
-
int check_circular;
|
53
|
-
VALUE seen;
|
54
|
-
VALUE memo;
|
55
|
-
VALUE depth;
|
56
|
-
long max_nesting;
|
57
|
-
int flag;
|
58
|
-
int allow_nan;
|
59
|
-
} JSON_Generator_State;
|
60
|
-
|
61
|
-
#define GET_STATE(self) \
|
62
|
-
JSON_Generator_State *state; \
|
63
|
-
Data_Get_Struct(self, JSON_Generator_State, state);
|
14
|
+
i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
|
15
|
+
i_pack, i_unpack, i_create_id, i_extend, i_key_p, i_aref, i_send,
|
16
|
+
i_respond_to_p, i_match;
|
64
17
|
|
65
|
-
/*
|
66
|
-
*
|
67
|
-
*
|
68
|
-
*
|
69
|
-
*
|
70
|
-
*
|
71
|
-
*
|
72
|
-
*
|
73
|
-
*
|
74
|
-
*
|
18
|
+
/*
|
19
|
+
* Copyright 2001-2004 Unicode, Inc.
|
20
|
+
*
|
21
|
+
* Disclaimer
|
22
|
+
*
|
23
|
+
* This source code is provided as is by Unicode, Inc. No claims are
|
24
|
+
* made as to fitness for any particular purpose. No warranties of any
|
25
|
+
* kind are expressed or implied. The recipient agrees to determine
|
26
|
+
* applicability of information provided. If this file has been
|
27
|
+
* purchased on magnetic or optical media from Unicode, Inc., the
|
28
|
+
* sole remedy for any claim will be exchange of defective media
|
29
|
+
* within 90 days of receipt.
|
30
|
+
*
|
31
|
+
* Limitations on Rights to Redistribute This Code
|
32
|
+
*
|
33
|
+
* Unicode, Inc. hereby grants the right to freely use the information
|
34
|
+
* supplied in this file in the creation of products supporting the
|
35
|
+
* Unicode Standard, and to make copies of this file in any form
|
36
|
+
* for internal or external distribution as long as this notice
|
37
|
+
* remains attached.
|
38
|
+
*/
|
39
|
+
|
40
|
+
/*
|
41
|
+
* Index into the table below with the first byte of a UTF-8 sequence to
|
42
|
+
* get the number of trailing bytes that are supposed to follow it.
|
43
|
+
* Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
|
44
|
+
* left as-is for anyone who may want to do such conversion, which was
|
45
|
+
* allowed in earlier algorithms.
|
46
|
+
*/
|
47
|
+
static const char trailingBytesForUTF8[256] = {
|
48
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
49
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
50
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
51
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
52
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
53
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
54
|
+
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
55
|
+
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
|
56
|
+
};
|
57
|
+
|
58
|
+
/*
|
59
|
+
* Magic values subtracted from a buffer value during UTF8 conversion.
|
60
|
+
* This table contains as many values as there might be trailing bytes
|
61
|
+
* in a UTF-8 sequence.
|
75
62
|
*/
|
63
|
+
static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
|
64
|
+
0x03C82080UL, 0xFA082080UL, 0x82082080UL };
|
65
|
+
|
66
|
+
/*
|
67
|
+
* Utility routine to tell whether a sequence of bytes is legal UTF-8.
|
68
|
+
* This must be called with the length pre-determined by the first byte.
|
69
|
+
* If not calling this from ConvertUTF8to*, then the length can be set by:
|
70
|
+
* length = trailingBytesForUTF8[*source]+1;
|
71
|
+
* and the sequence is illegal right away if there aren't that many bytes
|
72
|
+
* available.
|
73
|
+
* If presented with a length > 4, this returns 0. The Unicode
|
74
|
+
* definition of UTF-8 goes up to 4-byte sequences.
|
75
|
+
*/
|
76
|
+
static unsigned char isLegalUTF8(const UTF8 *source, int length)
|
77
|
+
{
|
78
|
+
UTF8 a;
|
79
|
+
const UTF8 *srcptr = source+length;
|
80
|
+
switch (length) {
|
81
|
+
default: return 0;
|
82
|
+
/* Everything else falls through when "1"... */
|
83
|
+
case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
|
84
|
+
case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
|
85
|
+
case 2: if ((a = (*--srcptr)) > 0xBF) return 0;
|
86
|
+
|
87
|
+
switch (*source) {
|
88
|
+
/* no fall-through in this inner switch */
|
89
|
+
case 0xE0: if (a < 0xA0) return 0; break;
|
90
|
+
case 0xED: if (a > 0x9F) return 0; break;
|
91
|
+
case 0xF0: if (a < 0x90) return 0; break;
|
92
|
+
case 0xF4: if (a > 0x8F) return 0; break;
|
93
|
+
default: if (a < 0x80) return 0;
|
94
|
+
}
|
95
|
+
|
96
|
+
case 1: if (*source >= 0x80 && *source < 0xC2) return 0;
|
97
|
+
}
|
98
|
+
if (*source > 0xF4) return 0;
|
99
|
+
return 1;
|
100
|
+
}
|
101
|
+
|
102
|
+
/* Escapes the UTF16 character and stores the result in the buffer buf. */
|
103
|
+
static void unicode_escape(char *buf, UTF16 character)
|
104
|
+
{
|
105
|
+
const char *digits = "0123456789abcdef";
|
76
106
|
|
77
|
-
|
107
|
+
buf[2] = digits[character >> 12];
|
108
|
+
buf[3] = digits[(character >> 8) & 0xf];
|
109
|
+
buf[4] = digits[(character >> 4) & 0xf];
|
110
|
+
buf[5] = digits[character & 0xf];
|
111
|
+
}
|
112
|
+
|
113
|
+
/* Escapes the UTF16 character and stores the result in the buffer buf, then
|
114
|
+
* the buffer buf іs appended to the FBuffer buffer. */
|
115
|
+
static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16
|
116
|
+
character)
|
78
117
|
{
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
Vdepth = state->depth;
|
118
|
+
unicode_escape(buf, character);
|
119
|
+
fbuffer_append(buffer, buf, 6);
|
120
|
+
}
|
83
121
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
122
|
+
/* Converts string to a JSON string in FBuffer buffer, where all but the ASCII
|
123
|
+
* and control characters are JSON escaped. */
|
124
|
+
static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
|
125
|
+
{
|
126
|
+
const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
|
127
|
+
const UTF8 *sourceEnd = source + RSTRING_LEN(string);
|
128
|
+
char buf[6] = { '\\', 'u' };
|
129
|
+
|
130
|
+
while (source < sourceEnd) {
|
131
|
+
UTF32 ch = 0;
|
132
|
+
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
|
133
|
+
if (source + extraBytesToRead >= sourceEnd) {
|
134
|
+
rb_raise(rb_path2class("JSON::GeneratorError"),
|
135
|
+
"partial character in source, but hit end");
|
136
|
+
}
|
137
|
+
if (!isLegalUTF8(source, extraBytesToRead+1)) {
|
138
|
+
rb_raise(rb_path2class("JSON::GeneratorError"),
|
139
|
+
"source sequence is illegal/malformed utf-8");
|
140
|
+
}
|
141
|
+
/*
|
142
|
+
* The cases all fall through. See "Note A" below.
|
143
|
+
*/
|
144
|
+
switch (extraBytesToRead) {
|
145
|
+
case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
|
146
|
+
case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
|
147
|
+
case 3: ch += *source++; ch <<= 6;
|
148
|
+
case 2: ch += *source++; ch <<= 6;
|
149
|
+
case 1: ch += *source++; ch <<= 6;
|
150
|
+
case 0: ch += *source++;
|
151
|
+
}
|
152
|
+
ch -= offsetsFromUTF8[extraBytesToRead];
|
153
|
+
|
154
|
+
if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
|
155
|
+
/* UTF-16 surrogate values are illegal in UTF-32 */
|
156
|
+
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
|
157
|
+
#if UNI_STRICT_CONVERSION
|
158
|
+
source -= (extraBytesToRead+1); /* return to the illegal value itself */
|
159
|
+
rb_raise(rb_path2class("JSON::GeneratorError"),
|
160
|
+
"source sequence is illegal/malformed utf-8");
|
161
|
+
#else
|
162
|
+
unicode_escape_to_buffer(buffer, buf, UNI_REPLACEMENT_CHAR);
|
163
|
+
#endif
|
164
|
+
} else {
|
165
|
+
/* normal case */
|
166
|
+
if (ch >= 0x20 && ch <= 0x7f) {
|
167
|
+
switch (ch) {
|
168
|
+
case '\\':
|
169
|
+
fbuffer_append(buffer, "\\\\", 2);
|
170
|
+
break;
|
171
|
+
case '"':
|
172
|
+
fbuffer_append(buffer, "\\\"", 2);
|
173
|
+
break;
|
174
|
+
default:
|
175
|
+
fbuffer_append_char(buffer, (char)ch);
|
176
|
+
break;
|
177
|
+
}
|
178
|
+
} else {
|
179
|
+
switch (ch) {
|
180
|
+
case '\n':
|
181
|
+
fbuffer_append(buffer, "\\n", 2);
|
182
|
+
break;
|
183
|
+
case '\r':
|
184
|
+
fbuffer_append(buffer, "\\r", 2);
|
185
|
+
break;
|
186
|
+
case '\t':
|
187
|
+
fbuffer_append(buffer, "\\t", 2);
|
188
|
+
break;
|
189
|
+
case '\f':
|
190
|
+
fbuffer_append(buffer, "\\f", 2);
|
191
|
+
break;
|
192
|
+
case '\b':
|
193
|
+
fbuffer_append(buffer, "\\b", 2);
|
194
|
+
break;
|
195
|
+
default:
|
196
|
+
unicode_escape_to_buffer(buffer, buf, (UTF16) ch);
|
197
|
+
break;
|
198
|
+
}
|
199
|
+
}
|
200
|
+
}
|
201
|
+
} else if (ch > UNI_MAX_UTF16) {
|
202
|
+
#if UNI_STRICT_CONVERSION
|
203
|
+
source -= (extraBytesToRead+1); /* return to the start */
|
204
|
+
rb_raise(rb_path2class("JSON::GeneratorError"),
|
205
|
+
"source sequence is illegal/malformed utf8");
|
206
|
+
#else
|
207
|
+
unicode_escape_to_buffer(buffer, buf, UNI_REPLACEMENT_CHAR);
|
208
|
+
#endif
|
209
|
+
} else {
|
210
|
+
/* target is a character in range 0xFFFF - 0x10FFFF. */
|
211
|
+
ch -= halfBase;
|
212
|
+
unicode_escape_to_buffer(buffer, buf, (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START));
|
213
|
+
unicode_escape_to_buffer(buffer, buf, (UTF16)((ch & halfMask) + UNI_SUR_LOW_START));
|
214
|
+
}
|
89
215
|
}
|
90
|
-
|
91
|
-
|
216
|
+
}
|
217
|
+
|
218
|
+
/* Converts string to a JSON string in FBuffer buffer, where only the
|
219
|
+
* characters required by the JSON standard are JSON escaped. The remaining
|
220
|
+
* characters (should be UTF8) are just passed through and appended to the
|
221
|
+
* result. */
|
222
|
+
static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
|
223
|
+
{
|
224
|
+
const char *ptr = RSTRING_PTR(string), *p;
|
225
|
+
int len = RSTRING_LEN(string), start = 0, end = 0;
|
226
|
+
const char *escape = NULL;
|
227
|
+
int escape_len;
|
228
|
+
unsigned char c;
|
229
|
+
char buf[6] = { '\\', 'u' };
|
230
|
+
|
231
|
+
for (start = 0, end = 0; end < len;) {
|
232
|
+
p = ptr + end;
|
233
|
+
c = (unsigned char) *p;
|
234
|
+
if (c < 0x20) {
|
235
|
+
switch (c) {
|
236
|
+
case '\n':
|
237
|
+
escape = "\\n";
|
238
|
+
escape_len = 2;
|
239
|
+
break;
|
240
|
+
case '\r':
|
241
|
+
escape = "\\r";
|
242
|
+
escape_len = 2;
|
243
|
+
break;
|
244
|
+
case '\t':
|
245
|
+
escape = "\\t";
|
246
|
+
escape_len = 2;
|
247
|
+
break;
|
248
|
+
case '\f':
|
249
|
+
escape = "\\f";
|
250
|
+
escape_len = 2;
|
251
|
+
break;
|
252
|
+
case '\b':
|
253
|
+
escape = "\\b";
|
254
|
+
escape_len = 2;
|
255
|
+
break;
|
256
|
+
default:
|
257
|
+
unicode_escape(buf, (UTF16) *p);
|
258
|
+
escape = buf;
|
259
|
+
escape_len = 6;
|
260
|
+
break;
|
261
|
+
}
|
262
|
+
} else {
|
263
|
+
switch (c) {
|
264
|
+
case '\\':
|
265
|
+
escape = "\\\\";
|
266
|
+
escape_len = 2;
|
267
|
+
break;
|
268
|
+
case '"':
|
269
|
+
escape = "\\\"";
|
270
|
+
escape_len = 2;
|
271
|
+
break;
|
272
|
+
default:
|
273
|
+
end++;
|
274
|
+
continue;
|
275
|
+
break;
|
276
|
+
}
|
277
|
+
}
|
278
|
+
fbuffer_append(buffer, ptr + start, end - start);
|
279
|
+
fbuffer_append(buffer, escape, escape_len);
|
280
|
+
start = ++end;
|
281
|
+
escape = NULL;
|
92
282
|
}
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
283
|
+
fbuffer_append(buffer, ptr + start, end - start);
|
284
|
+
}
|
285
|
+
|
286
|
+
static char *fstrndup(const char *ptr, int len) {
|
287
|
+
char *result;
|
288
|
+
if (len <= 0) return NULL;
|
289
|
+
result = ALLOC_N(char, len);
|
290
|
+
memccpy(result, ptr, 0, len);
|
291
|
+
return result;
|
292
|
+
}
|
293
|
+
|
294
|
+
/* fbuffer implementation */
|
295
|
+
|
296
|
+
static FBuffer *fbuffer_alloc()
|
297
|
+
{
|
298
|
+
FBuffer *fb = ALLOC(FBuffer);
|
299
|
+
memset((void *) fb, 0, sizeof(FBuffer));
|
300
|
+
fb->initial_length = FBUFFER_INITIAL_LENGTH;
|
301
|
+
return fb;
|
302
|
+
}
|
303
|
+
|
304
|
+
static FBuffer *fbuffer_alloc_with_length(unsigned int initial_length)
|
305
|
+
{
|
306
|
+
FBuffer *fb;
|
307
|
+
assert(initial_length > 0);
|
308
|
+
fb = ALLOC(FBuffer);
|
309
|
+
memset((void *) fb, 0, sizeof(FBuffer));
|
310
|
+
fb->initial_length = initial_length;
|
311
|
+
return fb;
|
312
|
+
}
|
313
|
+
|
314
|
+
static void fbuffer_free(FBuffer *fb)
|
315
|
+
{
|
316
|
+
if (fb->ptr) ruby_xfree(fb->ptr);
|
317
|
+
ruby_xfree(fb);
|
318
|
+
}
|
319
|
+
|
320
|
+
static void fbuffer_free_only_buffer(FBuffer *fb)
|
321
|
+
{
|
322
|
+
ruby_xfree(fb);
|
323
|
+
}
|
324
|
+
|
325
|
+
static void fbuffer_clear(FBuffer *fb)
|
326
|
+
{
|
327
|
+
fb->len = 0;
|
328
|
+
}
|
329
|
+
|
330
|
+
static void fbuffer_inc_capa(FBuffer *fb, unsigned int requested)
|
331
|
+
{
|
332
|
+
unsigned int required;
|
333
|
+
|
334
|
+
if (!fb->ptr) {
|
335
|
+
fb->ptr = ALLOC_N(char, fb->initial_length);
|
336
|
+
fb->capa = fb->initial_length;
|
99
337
|
}
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
OBJ_INFECT(buf, json);
|
107
|
-
state->depth = Vdepth;
|
108
|
-
state->memo = buf;
|
109
|
-
return ST_CONTINUE;
|
110
|
-
}
|
111
|
-
|
112
|
-
inline static VALUE mHash_json_transfrom(VALUE self, VALUE Vstate, VALUE Vdepth) {
|
113
|
-
long depth, len = RHASH_SIZE(self);
|
114
|
-
VALUE result;
|
115
|
-
GET_STATE(Vstate);
|
116
|
-
|
117
|
-
depth = 1 + FIX2LONG(Vdepth);
|
118
|
-
result = rb_str_buf_new(len);
|
119
|
-
state->memo = result;
|
120
|
-
state->depth = LONG2FIX(depth);
|
121
|
-
state->flag = 0;
|
122
|
-
rb_str_buf_cat2(result, "{");
|
123
|
-
if (RSTRING_LEN(state->object_nl)) rb_str_buf_append(result, state->object_nl);
|
124
|
-
rb_hash_foreach(self, hash_to_json_state_i, Vstate);
|
125
|
-
if (RSTRING_LEN(state->object_nl)) rb_str_buf_append(result, state->object_nl);
|
126
|
-
if (RSTRING_LEN(state->object_nl)) {
|
127
|
-
rb_str_buf_append(result, rb_str_times(state->indent, Vdepth));
|
338
|
+
|
339
|
+
for (required = fb->capa; requested > required - fb->len; required <<= 1);
|
340
|
+
|
341
|
+
if (required > fb->capa) {
|
342
|
+
fb->ptr = (char *) REALLOC_N((long*) fb->ptr, char, required);
|
343
|
+
fb->capa = required;
|
128
344
|
}
|
129
|
-
rb_str_buf_cat2(result, "}");
|
130
|
-
return result;
|
131
345
|
}
|
132
346
|
|
133
|
-
static
|
347
|
+
static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned int len)
|
134
348
|
{
|
135
|
-
|
349
|
+
if (len > 0) {
|
350
|
+
fbuffer_inc_capa(fb, len);
|
351
|
+
MEMCPY(fb->ptr + fb->len, newstr, char, len);
|
352
|
+
fb->len += len;
|
353
|
+
}
|
354
|
+
}
|
136
355
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
rb_str_buf_cat2(buf, ":");
|
144
|
-
tmp = rb_funcall(value, i_to_json, 0);
|
145
|
-
Check_Type(tmp, T_STRING);
|
146
|
-
rb_str_buf_append(buf, tmp);
|
147
|
-
OBJ_INFECT(buf, tmp);
|
356
|
+
static void fbuffer_append_char(FBuffer *fb, char newchr)
|
357
|
+
{
|
358
|
+
fbuffer_inc_capa(fb, 1);
|
359
|
+
*(fb->ptr + fb->len) = newchr;
|
360
|
+
fb->len++;
|
361
|
+
}
|
148
362
|
|
149
|
-
|
363
|
+
static void freverse(char *start, char *end)
|
364
|
+
{
|
365
|
+
char c;
|
366
|
+
|
367
|
+
while (end > start) {
|
368
|
+
c = *end, *end-- = *start, *start++ = c;
|
369
|
+
}
|
370
|
+
}
|
371
|
+
|
372
|
+
static int fltoa(long number, char *buf)
|
373
|
+
{
|
374
|
+
static char digits[] = "0123456789";
|
375
|
+
long sign = number;
|
376
|
+
char* tmp = buf;
|
377
|
+
|
378
|
+
if (sign < 0) number = -number;
|
379
|
+
do *tmp++ = digits[number % 10]; while (number /= 10);
|
380
|
+
if (sign < 0) *tmp++ = '-';
|
381
|
+
freverse(buf, tmp - 1);
|
382
|
+
return tmp - buf;
|
150
383
|
}
|
151
384
|
|
385
|
+
static void fbuffer_append_long(FBuffer *fb, long number)
|
386
|
+
{
|
387
|
+
char buf[20];
|
388
|
+
int len = fltoa(number, buf);
|
389
|
+
fbuffer_append(fb, buf, len);
|
390
|
+
}
|
391
|
+
|
392
|
+
static FBuffer *fbuffer_dup(FBuffer *fb)
|
393
|
+
{
|
394
|
+
int len = fb->len;
|
395
|
+
FBuffer *result;
|
396
|
+
|
397
|
+
if (len > 0) {
|
398
|
+
result = fbuffer_alloc_with_length(len);
|
399
|
+
fbuffer_append(result, FBUFFER_PAIR(fb));
|
400
|
+
} else {
|
401
|
+
result = fbuffer_alloc();
|
402
|
+
}
|
403
|
+
return result;
|
404
|
+
}
|
405
|
+
|
406
|
+
/*
|
407
|
+
* Document-module: JSON::Ext::Generator
|
408
|
+
*
|
409
|
+
* This is the JSON generator implemented as a C extension. It can be
|
410
|
+
* configured to be used by setting
|
411
|
+
*
|
412
|
+
* JSON.generator = JSON::Ext::Generator
|
413
|
+
*
|
414
|
+
* with the method generator= in JSON.
|
415
|
+
*
|
416
|
+
*/
|
417
|
+
|
152
418
|
/*
|
153
419
|
* call-seq: to_json(state = nil, depth = 0)
|
154
420
|
*
|
155
|
-
* Returns a JSON string containing a JSON object, that is
|
421
|
+
* Returns a JSON string containing a JSON object, that is generated from
|
156
422
|
* this Hash instance.
|
157
423
|
* _state_ is a JSON::State object, that can also be used to configure the
|
158
424
|
* produced JSON string output further.
|
@@ -160,134 +426,27 @@ static int hash_to_json_i(VALUE key, VALUE value, VALUE buf)
|
|
160
426
|
*/
|
161
427
|
static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
|
162
428
|
{
|
163
|
-
VALUE
|
164
|
-
long depth;
|
165
|
-
|
166
|
-
rb_scan_args(argc, argv, "02", &Vstate, &Vdepth);
|
167
|
-
depth = NIL_P(Vdepth) ? 0 : FIX2LONG(Vdepth);
|
168
|
-
if (NIL_P(Vstate)) {
|
169
|
-
long len = RHASH_SIZE(self);
|
170
|
-
result = rb_str_buf_new(len);
|
171
|
-
rb_str_buf_cat2(result, "{");
|
172
|
-
rb_hash_foreach(self, hash_to_json_i, result);
|
173
|
-
rb_str_buf_cat2(result, "}");
|
174
|
-
} else {
|
175
|
-
GET_STATE(Vstate);
|
176
|
-
check_max_nesting(state, depth);
|
177
|
-
if (state->check_circular) {
|
178
|
-
VALUE self_id = rb_obj_id(self);
|
179
|
-
if (RTEST(rb_hash_aref(state->seen, self_id))) {
|
180
|
-
rb_raise(eCircularDatastructure,
|
181
|
-
"circular data structures not supported!");
|
182
|
-
}
|
183
|
-
rb_hash_aset(state->seen, self_id, Qtrue);
|
184
|
-
result = mHash_json_transfrom(self, Vstate, LONG2FIX(depth));
|
185
|
-
rb_hash_delete(state->seen, self_id);
|
186
|
-
} else {
|
187
|
-
result = mHash_json_transfrom(self, Vstate, LONG2FIX(depth));
|
188
|
-
}
|
189
|
-
}
|
190
|
-
OBJ_INFECT(result, self);
|
191
|
-
FORCE_UTF8(result);
|
192
|
-
return result;
|
193
|
-
}
|
429
|
+
VALUE state, depth;
|
194
430
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
long depth = NIL_P(Vdepth) ? 0 : FIX2LONG(Vdepth);
|
199
|
-
VALUE delim = rb_str_new2(",");
|
200
|
-
GET_STATE(Vstate);
|
201
|
-
|
202
|
-
check_max_nesting(state, depth);
|
203
|
-
if (state->check_circular) {
|
204
|
-
VALUE self_id = rb_obj_id(self);
|
205
|
-
rb_hash_aset(state->seen, self_id, Qtrue);
|
206
|
-
result = rb_str_buf_new(len);
|
207
|
-
if (RSTRING_LEN(state->array_nl)) rb_str_append(delim, state->array_nl);
|
208
|
-
shift = rb_str_times(state->indent, LONG2FIX(depth + 1));
|
209
|
-
|
210
|
-
rb_str_buf_cat2(result, "[");
|
211
|
-
OBJ_INFECT(result, self);
|
212
|
-
rb_str_buf_append(result, state->array_nl);
|
213
|
-
for (i = 0; i < len; i++) {
|
214
|
-
VALUE element = RARRAY_PTR(self)[i];
|
215
|
-
if (RTEST(rb_hash_aref(state->seen, rb_obj_id(element)))) {
|
216
|
-
rb_raise(eCircularDatastructure,
|
217
|
-
"circular data structures not supported!");
|
218
|
-
}
|
219
|
-
OBJ_INFECT(result, element);
|
220
|
-
if (i > 0) rb_str_buf_append(result, delim);
|
221
|
-
rb_str_buf_append(result, shift);
|
222
|
-
element = rb_funcall(element, i_to_json, 2, Vstate, LONG2FIX(depth + 1));
|
223
|
-
Check_Type(element, T_STRING);
|
224
|
-
rb_str_buf_append(result, element);
|
225
|
-
}
|
226
|
-
if (RSTRING_LEN(state->array_nl)) {
|
227
|
-
rb_str_buf_append(result, state->array_nl);
|
228
|
-
rb_str_buf_append(result, rb_str_times(state->indent, LONG2FIX(depth)));
|
229
|
-
}
|
230
|
-
rb_str_buf_cat2(result, "]");
|
231
|
-
rb_hash_delete(state->seen, self_id);
|
232
|
-
} else {
|
233
|
-
result = rb_str_buf_new(len);
|
234
|
-
OBJ_INFECT(result, self);
|
235
|
-
if (RSTRING_LEN(state->array_nl)) rb_str_append(delim, state->array_nl);
|
236
|
-
shift = rb_str_times(state->indent, LONG2FIX(depth + 1));
|
237
|
-
|
238
|
-
rb_str_buf_cat2(result, "[");
|
239
|
-
rb_str_buf_append(result, state->array_nl);
|
240
|
-
for (i = 0; i < len; i++) {
|
241
|
-
VALUE element = RARRAY_PTR(self)[i];
|
242
|
-
OBJ_INFECT(result, element);
|
243
|
-
if (i > 0) rb_str_buf_append(result, delim);
|
244
|
-
rb_str_buf_append(result, shift);
|
245
|
-
element = rb_funcall(element, i_to_json, 2, Vstate, LONG2FIX(depth + 1));
|
246
|
-
Check_Type(element, T_STRING);
|
247
|
-
rb_str_buf_append(result, element);
|
248
|
-
}
|
249
|
-
rb_str_buf_append(result, state->array_nl);
|
250
|
-
if (RSTRING_LEN(state->array_nl)) {
|
251
|
-
rb_str_buf_append(result, rb_str_times(state->indent, LONG2FIX(depth)));
|
252
|
-
}
|
253
|
-
rb_str_buf_cat2(result, "]");
|
254
|
-
}
|
255
|
-
return result;
|
431
|
+
rb_scan_args(argc, argv, "02", &state, &depth);
|
432
|
+
state = cState_from_state_s(cState, state);
|
433
|
+
return cState_partial_generate(state, self, depth);
|
256
434
|
}
|
257
435
|
|
258
436
|
/*
|
259
437
|
* call-seq: to_json(state = nil, depth = 0)
|
260
438
|
*
|
261
|
-
* Returns a JSON string containing a JSON array, that is
|
439
|
+
* Returns a JSON string containing a JSON array, that is generated from
|
262
440
|
* this Array instance.
|
263
441
|
* _state_ is a JSON::State object, that can also be used to configure the
|
264
442
|
* produced JSON string output further.
|
265
443
|
* _depth_ is used to find out nesting depth, to indent accordingly.
|
266
444
|
*/
|
267
445
|
static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
|
268
|
-
VALUE
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
long i, len = RARRAY_LEN(self);
|
273
|
-
result = rb_str_buf_new(2 + 2 * len);
|
274
|
-
rb_str_buf_cat2(result, "[");
|
275
|
-
OBJ_INFECT(result, self);
|
276
|
-
for (i = 0; i < len; i++) {
|
277
|
-
VALUE element = RARRAY_PTR(self)[i];
|
278
|
-
OBJ_INFECT(result, element);
|
279
|
-
if (i > 0) rb_str_buf_cat2(result, ",");
|
280
|
-
element = rb_funcall(element, i_to_json, 0);
|
281
|
-
Check_Type(element, T_STRING);
|
282
|
-
rb_str_buf_append(result, element);
|
283
|
-
}
|
284
|
-
rb_str_buf_cat2(result, "]");
|
285
|
-
} else {
|
286
|
-
result = mArray_json_transfrom(self, Vstate, Vdepth);
|
287
|
-
}
|
288
|
-
OBJ_INFECT(result, self);
|
289
|
-
FORCE_UTF8(result);
|
290
|
-
return result;
|
446
|
+
VALUE state, depth;
|
447
|
+
rb_scan_args(argc, argv, "02", &state, &depth);
|
448
|
+
state = cState_from_state_s(cState, state);
|
449
|
+
return cState_partial_generate(state, self, depth);
|
291
450
|
}
|
292
451
|
|
293
452
|
/*
|
@@ -297,9 +456,10 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
|
|
297
456
|
*/
|
298
457
|
static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
|
299
458
|
{
|
300
|
-
VALUE
|
301
|
-
|
302
|
-
|
459
|
+
VALUE state, depth;
|
460
|
+
rb_scan_args(argc, argv, "02", &state, &depth);
|
461
|
+
state = cState_from_state_s(cState, state);
|
462
|
+
return cState_partial_generate(state, self, depth);
|
303
463
|
}
|
304
464
|
|
305
465
|
/*
|
@@ -309,30 +469,10 @@ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
|
|
309
469
|
*/
|
310
470
|
static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
|
311
471
|
{
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
if (!NIL_P(Vstate)) Data_Get_Struct(Vstate, JSON_Generator_State, state);
|
317
|
-
if (isinf(value)) {
|
318
|
-
if (!state || state->allow_nan) {
|
319
|
-
result = rb_funcall(self, i_to_s, 0);
|
320
|
-
} else {
|
321
|
-
tmp = rb_funcall(self, i_to_s, 0);
|
322
|
-
rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
|
323
|
-
}
|
324
|
-
} else if (isnan(value)) {
|
325
|
-
if (!state || state->allow_nan) {
|
326
|
-
result = rb_funcall(self, i_to_s, 0);
|
327
|
-
} else {
|
328
|
-
tmp = rb_funcall(self, i_to_s, 0);
|
329
|
-
rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
|
330
|
-
}
|
331
|
-
} else {
|
332
|
-
result = rb_funcall(self, i_to_s, 0);
|
333
|
-
}
|
334
|
-
FORCE_UTF8(result);
|
335
|
-
return result;
|
472
|
+
VALUE state, depth;
|
473
|
+
rb_scan_args(argc, argv, "02", &state, &depth);
|
474
|
+
state = cState_from_state_s(cState, state);
|
475
|
+
return cState_partial_generate(state, self, depth);
|
336
476
|
}
|
337
477
|
|
338
478
|
/*
|
@@ -342,7 +482,6 @@ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
|
|
342
482
|
*/
|
343
483
|
static VALUE mString_included_s(VALUE self, VALUE modul) {
|
344
484
|
VALUE result = rb_funcall(modul, i_extend, 1, mString_Extend);
|
345
|
-
FORCE_UTF8(result);
|
346
485
|
return result;
|
347
486
|
}
|
348
487
|
|
@@ -355,29 +494,27 @@ static VALUE mString_included_s(VALUE self, VALUE modul) {
|
|
355
494
|
*/
|
356
495
|
static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
|
357
496
|
{
|
358
|
-
VALUE
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
FORCE_UTF8(result);
|
363
|
-
return result;
|
497
|
+
VALUE state, depth;
|
498
|
+
rb_scan_args(argc, argv, "02", &state, &depth);
|
499
|
+
state = cState_from_state_s(cState, state);
|
500
|
+
return cState_partial_generate(state, self, depth);
|
364
501
|
}
|
365
502
|
|
366
503
|
/*
|
367
504
|
* call-seq: to_json_raw_object()
|
368
505
|
*
|
369
506
|
* This method creates a raw object hash, that can be nested into
|
370
|
-
* other data structures and will be
|
507
|
+
* other data structures and will be generated as a raw string. This
|
371
508
|
* method should be used, if you want to convert raw strings to JSON
|
372
509
|
* instead of UTF-8 strings, e. g. binary data.
|
373
510
|
*/
|
374
|
-
static VALUE mString_to_json_raw_object(VALUE self)
|
511
|
+
static VALUE mString_to_json_raw_object(VALUE self)
|
512
|
+
{
|
375
513
|
VALUE ary;
|
376
514
|
VALUE result = rb_hash_new();
|
377
515
|
rb_hash_aset(result, rb_funcall(mJSON, i_create_id, 0), rb_class_name(rb_obj_class(self)));
|
378
516
|
ary = rb_funcall(self, i_unpack, 1, rb_str_new2("C*"));
|
379
517
|
rb_hash_aset(result, rb_str_new2("raw"), ary);
|
380
|
-
FORCE_UTF8(result);
|
381
518
|
return result;
|
382
519
|
}
|
383
520
|
|
@@ -387,12 +524,11 @@ static VALUE mString_to_json_raw_object(VALUE self) {
|
|
387
524
|
* This method creates a JSON text from the result of a call to
|
388
525
|
* to_json_raw_object of this String.
|
389
526
|
*/
|
390
|
-
static VALUE mString_to_json_raw(int argc, VALUE *argv, VALUE self)
|
391
|
-
|
527
|
+
static VALUE mString_to_json_raw(int argc, VALUE *argv, VALUE self)
|
528
|
+
{
|
529
|
+
VALUE obj = mString_to_json_raw_object(self);
|
392
530
|
Check_Type(obj, T_HASH);
|
393
|
-
|
394
|
-
FORCE_UTF8(result);
|
395
|
-
return result;
|
531
|
+
return mHash_to_json(argc, argv, obj);
|
396
532
|
}
|
397
533
|
|
398
534
|
/*
|
@@ -401,7 +537,8 @@ static VALUE mString_to_json_raw(int argc, VALUE *argv, VALUE self) {
|
|
401
537
|
* Raw Strings are JSON Objects (the raw bytes are stored in an array for the
|
402
538
|
* key "raw"). The Ruby String can be created by this module method.
|
403
539
|
*/
|
404
|
-
static VALUE mString_Extend_json_create(VALUE self, VALUE o)
|
540
|
+
static VALUE mString_Extend_json_create(VALUE self, VALUE o)
|
541
|
+
{
|
405
542
|
VALUE ary;
|
406
543
|
Check_Type(o, T_HASH);
|
407
544
|
ary = rb_hash_aref(o, rb_str_new2("raw"));
|
@@ -409,38 +546,41 @@ static VALUE mString_Extend_json_create(VALUE self, VALUE o) {
|
|
409
546
|
}
|
410
547
|
|
411
548
|
/*
|
412
|
-
* call-seq: to_json(
|
549
|
+
* call-seq: to_json(*)
|
413
550
|
*
|
414
551
|
* Returns a JSON string for true: 'true'.
|
415
552
|
*/
|
416
553
|
static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
|
417
554
|
{
|
418
|
-
VALUE
|
419
|
-
|
420
|
-
|
555
|
+
VALUE state, depth;
|
556
|
+
rb_scan_args(argc, argv, "02", &state, &depth);
|
557
|
+
state = cState_from_state_s(cState, state);
|
558
|
+
return cState_partial_generate(state, self, depth);
|
421
559
|
}
|
422
560
|
|
423
561
|
/*
|
424
|
-
* call-seq: to_json(
|
562
|
+
* call-seq: to_json(*)
|
425
563
|
*
|
426
564
|
* Returns a JSON string for false: 'false'.
|
427
565
|
*/
|
428
566
|
static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
|
429
567
|
{
|
430
|
-
VALUE
|
431
|
-
|
432
|
-
|
568
|
+
VALUE state, depth;
|
569
|
+
rb_scan_args(argc, argv, "02", &state, &depth);
|
570
|
+
state = cState_from_state_s(cState, state);
|
571
|
+
return cState_partial_generate(state, self, depth);
|
433
572
|
}
|
434
573
|
|
435
574
|
/*
|
436
|
-
* call-seq: to_json(
|
575
|
+
* call-seq: to_json(*)
|
437
576
|
*
|
438
577
|
*/
|
439
578
|
static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
|
440
579
|
{
|
441
|
-
VALUE
|
442
|
-
|
443
|
-
|
580
|
+
VALUE state, depth;
|
581
|
+
rb_scan_args(argc, argv, "02", &state, &depth);
|
582
|
+
state = cState_from_state_s(cState, state);
|
583
|
+
return cState_partial_generate(state, self, depth);
|
444
584
|
}
|
445
585
|
|
446
586
|
/*
|
@@ -452,30 +592,25 @@ static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
|
|
452
592
|
*/
|
453
593
|
static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
|
454
594
|
{
|
455
|
-
VALUE
|
595
|
+
VALUE state, depth;
|
596
|
+
VALUE string = rb_funcall(self, i_to_s, 0);
|
597
|
+
rb_scan_args(argc, argv, "02", &state, &depth);
|
456
598
|
Check_Type(string, T_STRING);
|
457
|
-
|
458
|
-
|
459
|
-
return result;
|
599
|
+
state = cState_from_state_s(cState, state);
|
600
|
+
return cState_partial_generate(state, string, depth);
|
460
601
|
}
|
461
602
|
|
462
|
-
|
463
|
-
* Document-class: JSON::Ext::Generator::State
|
464
|
-
*
|
465
|
-
* This class is used to create State instances, that are use to hold data
|
466
|
-
* while generating a JSON text from a a Ruby data structure.
|
467
|
-
*/
|
468
|
-
|
469
|
-
static void State_mark(JSON_Generator_State *state)
|
603
|
+
static void State_free(JSON_Generator_State *state)
|
470
604
|
{
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
605
|
+
if (state->indent) ruby_xfree(state->indent);
|
606
|
+
if (state->space) ruby_xfree(state->space);
|
607
|
+
if (state->space_before) ruby_xfree(state->space_before);
|
608
|
+
if (state->object_nl) ruby_xfree(state->object_nl);
|
609
|
+
if (state->array_nl) ruby_xfree(state->array_nl);
|
610
|
+
if (state->array_delim) fbuffer_free(state->array_delim);
|
611
|
+
if (state->object_delim) fbuffer_free(state->object_delim);
|
612
|
+
if (state->object_delim2) fbuffer_free(state->object_delim2);
|
613
|
+
ruby_xfree(state);
|
479
614
|
}
|
480
615
|
|
481
616
|
static JSON_Generator_State *State_allocate()
|
@@ -487,7 +622,7 @@ static JSON_Generator_State *State_allocate()
|
|
487
622
|
static VALUE cState_s_allocate(VALUE klass)
|
488
623
|
{
|
489
624
|
JSON_Generator_State *state = State_allocate();
|
490
|
-
return Data_Wrap_Struct(klass,
|
625
|
+
return Data_Wrap_Struct(klass, NULL, State_free, state);
|
491
626
|
}
|
492
627
|
|
493
628
|
/*
|
@@ -508,39 +643,47 @@ static VALUE cState_configure(VALUE self, VALUE opts)
|
|
508
643
|
opts = tmp;
|
509
644
|
tmp = rb_hash_aref(opts, ID2SYM(i_indent));
|
510
645
|
if (RTEST(tmp)) {
|
646
|
+
int len;
|
511
647
|
Check_Type(tmp, T_STRING);
|
512
|
-
|
648
|
+
len = RSTRING_LEN(tmp);
|
649
|
+
state->indent = fstrndup(RSTRING_PTR(tmp), len);
|
650
|
+
state->indent_len = len;
|
513
651
|
}
|
514
652
|
tmp = rb_hash_aref(opts, ID2SYM(i_space));
|
515
653
|
if (RTEST(tmp)) {
|
654
|
+
int len;
|
516
655
|
Check_Type(tmp, T_STRING);
|
517
|
-
|
656
|
+
len = RSTRING_LEN(tmp);
|
657
|
+
state->space = fstrndup(RSTRING_PTR(tmp), len);
|
658
|
+
state->space_len = len;
|
518
659
|
}
|
519
660
|
tmp = rb_hash_aref(opts, ID2SYM(i_space_before));
|
520
661
|
if (RTEST(tmp)) {
|
662
|
+
int len;
|
521
663
|
Check_Type(tmp, T_STRING);
|
522
|
-
|
664
|
+
len = RSTRING_LEN(tmp);
|
665
|
+
state->space_before = fstrndup(RSTRING_PTR(tmp), len);
|
666
|
+
state->space_before_len = len;
|
523
667
|
}
|
524
668
|
tmp = rb_hash_aref(opts, ID2SYM(i_array_nl));
|
525
669
|
if (RTEST(tmp)) {
|
670
|
+
int len;
|
526
671
|
Check_Type(tmp, T_STRING);
|
527
|
-
|
672
|
+
len = RSTRING_LEN(tmp);
|
673
|
+
state->array_nl = fstrndup(RSTRING_PTR(tmp), len);
|
674
|
+
state->array_nl_len = len;
|
528
675
|
}
|
529
676
|
tmp = rb_hash_aref(opts, ID2SYM(i_object_nl));
|
530
677
|
if (RTEST(tmp)) {
|
678
|
+
int len;
|
531
679
|
Check_Type(tmp, T_STRING);
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
|
536
|
-
tmp = rb_hash_aref(opts, ID2SYM(i_check_circular));
|
537
|
-
state->check_circular = RTEST(tmp);
|
538
|
-
} else {
|
539
|
-
state->check_circular = 1;
|
680
|
+
len = RSTRING_LEN(tmp);
|
681
|
+
state->object_nl = fstrndup(RSTRING_PTR(tmp), len);
|
682
|
+
state->object_nl_len = len;
|
540
683
|
}
|
541
684
|
tmp = ID2SYM(i_max_nesting);
|
542
685
|
state->max_nesting = 19;
|
543
|
-
if (
|
686
|
+
if (option_given_p(opts, tmp)) {
|
544
687
|
VALUE max_nesting = rb_hash_aref(opts, tmp);
|
545
688
|
if (RTEST(max_nesting)) {
|
546
689
|
Check_Type(max_nesting, T_FIXNUM);
|
@@ -551,6 +694,8 @@ static VALUE cState_configure(VALUE self, VALUE opts)
|
|
551
694
|
}
|
552
695
|
tmp = rb_hash_aref(opts, ID2SYM(i_allow_nan));
|
553
696
|
state->allow_nan = RTEST(tmp);
|
697
|
+
tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
|
698
|
+
state->ascii_only = RTEST(tmp);
|
554
699
|
return self;
|
555
700
|
}
|
556
701
|
|
@@ -564,17 +709,242 @@ static VALUE cState_to_h(VALUE self)
|
|
564
709
|
{
|
565
710
|
VALUE result = rb_hash_new();
|
566
711
|
GET_STATE(self);
|
567
|
-
rb_hash_aset(result, ID2SYM(i_indent), state->indent);
|
568
|
-
rb_hash_aset(result, ID2SYM(i_space), state->space);
|
569
|
-
rb_hash_aset(result, ID2SYM(i_space_before), state->space_before);
|
570
|
-
rb_hash_aset(result, ID2SYM(i_object_nl), state->object_nl);
|
571
|
-
rb_hash_aset(result, ID2SYM(i_array_nl), state->array_nl);
|
572
|
-
rb_hash_aset(result, ID2SYM(i_check_circular), state->check_circular ? Qtrue : Qfalse);
|
712
|
+
rb_hash_aset(result, ID2SYM(i_indent), rb_str_new(state->indent, state->indent_len));
|
713
|
+
rb_hash_aset(result, ID2SYM(i_space), rb_str_new(state->space, state->space_len));
|
714
|
+
rb_hash_aset(result, ID2SYM(i_space_before), rb_str_new(state->space_before, state->space_before_len));
|
715
|
+
rb_hash_aset(result, ID2SYM(i_object_nl), rb_str_new(state->object_nl, state->object_nl_len));
|
716
|
+
rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len));
|
573
717
|
rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
|
718
|
+
rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
|
574
719
|
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
|
575
720
|
return result;
|
576
721
|
}
|
577
722
|
|
723
|
+
/*
|
724
|
+
* call-seq: [](name)
|
725
|
+
*
|
726
|
+
* Return the value returned by method +name+.
|
727
|
+
*/
|
728
|
+
static VALUE cState_aref(VALUE self, VALUE name)
|
729
|
+
{
|
730
|
+
GET_STATE(self);
|
731
|
+
if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
|
732
|
+
return rb_funcall(self, i_send, 1, name);
|
733
|
+
} else {
|
734
|
+
return Qnil;
|
735
|
+
}
|
736
|
+
}
|
737
|
+
|
738
|
+
static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth)
|
739
|
+
{
|
740
|
+
VALUE tmp;
|
741
|
+
switch (TYPE(obj)) {
|
742
|
+
case T_HASH:
|
743
|
+
{
|
744
|
+
char *object_nl = state->object_nl;
|
745
|
+
long object_nl_len = state->object_nl_len;
|
746
|
+
char *indent = state->indent;
|
747
|
+
long indent_len = state->indent_len;
|
748
|
+
long max_nesting = state->max_nesting;
|
749
|
+
char *delim = FBUFFER_PTR(state->object_delim);
|
750
|
+
long delim_len = FBUFFER_LEN(state->object_delim);
|
751
|
+
char *delim2 = FBUFFER_PTR(state->object_delim2);
|
752
|
+
long delim2_len = FBUFFER_LEN(state->object_delim2);
|
753
|
+
int i, j;
|
754
|
+
VALUE key, key_to_s, keys;
|
755
|
+
depth++;
|
756
|
+
if (max_nesting != 0 && depth > max_nesting) {
|
757
|
+
fbuffer_free(buffer);
|
758
|
+
rb_raise(eNestingError, "nesting of %ld is too deep", depth);
|
759
|
+
}
|
760
|
+
fbuffer_append_char(buffer, '{');
|
761
|
+
keys = rb_funcall(obj, rb_intern("keys"), 0);
|
762
|
+
for(i = 0; i < RARRAY_LEN(keys); i++) {
|
763
|
+
if (i > 0) fbuffer_append(buffer, delim, delim_len);
|
764
|
+
if (object_nl) {
|
765
|
+
fbuffer_append(buffer, object_nl, object_nl_len);
|
766
|
+
}
|
767
|
+
if (indent) {
|
768
|
+
for (j = 0; j < depth; j++) {
|
769
|
+
fbuffer_append(buffer, indent, indent_len);
|
770
|
+
}
|
771
|
+
}
|
772
|
+
key = rb_ary_entry(keys, i);
|
773
|
+
key_to_s = rb_funcall(key, i_to_s, 0);
|
774
|
+
Check_Type(key_to_s, T_STRING);
|
775
|
+
generate_json(buffer, Vstate, state, key_to_s, depth);
|
776
|
+
fbuffer_append(buffer, delim2, delim2_len);
|
777
|
+
generate_json(buffer, Vstate, state, rb_hash_aref(obj, key), depth);
|
778
|
+
}
|
779
|
+
depth--;
|
780
|
+
if (object_nl) {
|
781
|
+
fbuffer_append(buffer, object_nl, object_nl_len);
|
782
|
+
if (indent) {
|
783
|
+
for (j = 0; j < depth; j++) {
|
784
|
+
fbuffer_append(buffer, indent, indent_len);
|
785
|
+
}
|
786
|
+
}
|
787
|
+
}
|
788
|
+
fbuffer_append_char(buffer, '}');
|
789
|
+
}
|
790
|
+
break;
|
791
|
+
case T_ARRAY:
|
792
|
+
{
|
793
|
+
char *array_nl = state->array_nl;
|
794
|
+
long array_nl_len = state->array_nl_len;
|
795
|
+
char *indent = state->indent;
|
796
|
+
long indent_len = state->indent_len;
|
797
|
+
long max_nesting = state->max_nesting;
|
798
|
+
char *delim = FBUFFER_PTR(state->array_delim);
|
799
|
+
long delim_len = FBUFFER_LEN(state->array_delim);
|
800
|
+
int i, j;
|
801
|
+
depth++;
|
802
|
+
if (max_nesting != 0 && depth > max_nesting) {
|
803
|
+
fbuffer_free(buffer);
|
804
|
+
rb_raise(eNestingError, "nesting of %ld is too deep", depth);
|
805
|
+
}
|
806
|
+
fbuffer_append_char(buffer, '[');
|
807
|
+
if (array_nl) fbuffer_append(buffer, array_nl, array_nl_len);
|
808
|
+
for(i = 0; i < RARRAY_LEN(obj); i++) {
|
809
|
+
if (i > 0) fbuffer_append(buffer, delim, delim_len);
|
810
|
+
if (indent) {
|
811
|
+
for (j = 0; j < depth; j++) {
|
812
|
+
fbuffer_append(buffer, indent, indent_len);
|
813
|
+
}
|
814
|
+
}
|
815
|
+
generate_json(buffer, Vstate, state, rb_ary_entry(obj, i), depth);
|
816
|
+
}
|
817
|
+
depth--;
|
818
|
+
if (array_nl) {
|
819
|
+
fbuffer_append(buffer, array_nl, array_nl_len);
|
820
|
+
if (indent) {
|
821
|
+
for (j = 0; j < depth; j++) {
|
822
|
+
fbuffer_append(buffer, indent, indent_len);
|
823
|
+
}
|
824
|
+
}
|
825
|
+
}
|
826
|
+
fbuffer_append_char(buffer, ']');
|
827
|
+
}
|
828
|
+
break;
|
829
|
+
case T_STRING:
|
830
|
+
fbuffer_append_char(buffer, '"');
|
831
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
832
|
+
obj = rb_funcall(obj, i_encode, 1, CEncoding_UTF_8);
|
833
|
+
#endif
|
834
|
+
if (state->ascii_only) {
|
835
|
+
convert_UTF8_to_JSON_ASCII(buffer, obj);
|
836
|
+
} else {
|
837
|
+
convert_UTF8_to_JSON(buffer, obj);
|
838
|
+
}
|
839
|
+
fbuffer_append_char(buffer, '"');
|
840
|
+
break;
|
841
|
+
case T_NIL:
|
842
|
+
fbuffer_append(buffer, "null", 4);
|
843
|
+
break;
|
844
|
+
case T_FALSE:
|
845
|
+
fbuffer_append(buffer, "false", 5);
|
846
|
+
break;
|
847
|
+
case T_TRUE:
|
848
|
+
fbuffer_append(buffer, "true", 4);
|
849
|
+
break;
|
850
|
+
case T_FIXNUM:
|
851
|
+
fbuffer_append_long(buffer, FIX2LONG(obj));
|
852
|
+
break;
|
853
|
+
case T_BIGNUM:
|
854
|
+
tmp = rb_funcall(obj, i_to_s, 0);
|
855
|
+
fbuffer_append(buffer, RSTRING_PAIR(tmp));
|
856
|
+
break;
|
857
|
+
case T_FLOAT:
|
858
|
+
{
|
859
|
+
double value = RFLOAT_VALUE(obj);
|
860
|
+
char allow_nan = state->allow_nan;
|
861
|
+
tmp = rb_funcall(obj, i_to_s, 0);
|
862
|
+
if (!allow_nan) {
|
863
|
+
if (isinf(value)) {
|
864
|
+
fbuffer_free(buffer);
|
865
|
+
rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
|
866
|
+
} else if (isnan(value)) {
|
867
|
+
fbuffer_free(buffer);
|
868
|
+
rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
|
869
|
+
}
|
870
|
+
}
|
871
|
+
fbuffer_append(buffer, RSTRING_PAIR(tmp));
|
872
|
+
}
|
873
|
+
break;
|
874
|
+
default:
|
875
|
+
if (rb_respond_to(obj, i_to_json)) {
|
876
|
+
tmp = rb_funcall(obj, i_to_json, 2, Vstate, INT2FIX(depth + 1));
|
877
|
+
Check_Type(tmp, T_STRING);
|
878
|
+
fbuffer_append(buffer, RSTRING_PAIR(tmp));
|
879
|
+
} else {
|
880
|
+
tmp = rb_funcall(obj, i_to_s, 0);
|
881
|
+
Check_Type(tmp, T_STRING);
|
882
|
+
generate_json(buffer, Vstate, state, tmp, depth + 1);
|
883
|
+
}
|
884
|
+
break;
|
885
|
+
}
|
886
|
+
}
|
887
|
+
|
888
|
+
/*
|
889
|
+
* call-seq: partial_generate(obj)
|
890
|
+
*
|
891
|
+
* Generates a part of a JSON document from object +obj+ and returns the
|
892
|
+
* result.
|
893
|
+
*/
|
894
|
+
static VALUE cState_partial_generate(VALUE self, VALUE obj, VALUE depth)
|
895
|
+
{
|
896
|
+
VALUE result;
|
897
|
+
FBuffer *buffer = fbuffer_alloc();
|
898
|
+
GET_STATE(self);
|
899
|
+
|
900
|
+
if (state->object_delim) {
|
901
|
+
fbuffer_clear(state->object_delim);
|
902
|
+
} else {
|
903
|
+
state->object_delim = fbuffer_alloc_with_length(16);
|
904
|
+
}
|
905
|
+
fbuffer_append_char(state->object_delim, ',');
|
906
|
+
if (state->object_delim2) {
|
907
|
+
fbuffer_clear(state->object_delim2);
|
908
|
+
} else {
|
909
|
+
state->object_delim2 = fbuffer_alloc_with_length(16);
|
910
|
+
}
|
911
|
+
fbuffer_append_char(state->object_delim2, ':');
|
912
|
+
if (state->space) fbuffer_append(state->object_delim2, state->space, state->space_len);
|
913
|
+
|
914
|
+
if (state->array_delim) {
|
915
|
+
fbuffer_clear(state->array_delim);
|
916
|
+
} else {
|
917
|
+
state->array_delim = fbuffer_alloc_with_length(16);
|
918
|
+
}
|
919
|
+
fbuffer_append_char(state->array_delim, ',');
|
920
|
+
if (state->array_nl) fbuffer_append(state->array_delim, state->array_nl, state->array_nl_len);
|
921
|
+
|
922
|
+
generate_json(buffer, self, state, obj, NIL_P(depth) ? 0 : FIX2INT(depth));
|
923
|
+
result = rb_str_new(FBUFFER_PAIR(buffer));
|
924
|
+
fbuffer_free(buffer);
|
925
|
+
FORCE_UTF8(result);
|
926
|
+
return result;
|
927
|
+
}
|
928
|
+
|
929
|
+
/*
|
930
|
+
* call-seq: generate(obj)
|
931
|
+
*
|
932
|
+
* Generates a valid JSON document from object +obj+ and returns the
|
933
|
+
* result. If no valid JSON document can be created this method raises a
|
934
|
+
* GeneratorError exception.
|
935
|
+
*/
|
936
|
+
static VALUE cState_generate(VALUE self, VALUE obj)
|
937
|
+
{
|
938
|
+
VALUE result = cState_partial_generate(self, obj, Qnil);
|
939
|
+
VALUE re, args[2];
|
940
|
+
args[0] = rb_str_new2("\\A\\s*(?:\\[.*\\]|\\{.*\\})\\s*\\Z");
|
941
|
+
args[1] = CRegexp_MULTILINE;
|
942
|
+
re = rb_class_new_instance(2, args, rb_cRegexp);
|
943
|
+
if (NIL_P(rb_funcall(re, i_match, 1, result))) {
|
944
|
+
rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed");
|
945
|
+
}
|
946
|
+
return result;
|
947
|
+
}
|
578
948
|
|
579
949
|
/*
|
580
950
|
* call-seq: new(opts = {})
|
@@ -588,8 +958,6 @@ static VALUE cState_to_h(VALUE self)
|
|
588
958
|
* * *space_before*: a string that is put before a : pair delimiter (default: ''),
|
589
959
|
* * *object_nl*: a string that is put at the end of a JSON object (default: ''),
|
590
960
|
* * *array_nl*: a string that is put at the end of a JSON array (default: ''),
|
591
|
-
* * *check_circular*: true if checking for circular data structures
|
592
|
-
* should be done, false (the default) otherwise.
|
593
961
|
* * *allow_nan*: true if NaN, Infinity, and -Infinity should be
|
594
962
|
* generated, otherwise an exception is thrown, if these values are
|
595
963
|
* encountered. This options defaults to false.
|
@@ -598,26 +966,39 @@ static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
|
|
598
966
|
{
|
599
967
|
VALUE opts;
|
600
968
|
GET_STATE(self);
|
601
|
-
|
969
|
+
MEMZERO(state, JSON_Generator_State, 1);
|
970
|
+
state->max_nesting = 19;
|
602
971
|
rb_scan_args(argc, argv, "01", &opts);
|
603
|
-
|
604
|
-
state->space = rb_str_new2("");
|
605
|
-
state->space_before = rb_str_new2("");
|
606
|
-
state->array_nl = rb_str_new2("");
|
607
|
-
state->object_nl = rb_str_new2("");
|
608
|
-
if (NIL_P(opts)) {
|
609
|
-
state->check_circular = 1;
|
610
|
-
state->allow_nan = 0;
|
611
|
-
state->max_nesting = 19;
|
612
|
-
} else {
|
613
|
-
cState_configure(self, opts);
|
614
|
-
}
|
615
|
-
state->seen = rb_hash_new();
|
616
|
-
state->memo = Qnil;
|
617
|
-
state->depth = INT2FIX(0);
|
972
|
+
if (!NIL_P(opts)) cState_configure(self, opts);
|
618
973
|
return self;
|
619
974
|
}
|
620
975
|
|
976
|
+
/*
|
977
|
+
* call-seq: initialize_copy(orig)
|
978
|
+
*
|
979
|
+
* Initializes this object from orig if it to be duplicated/cloned and returns
|
980
|
+
* it.
|
981
|
+
*/
|
982
|
+
static VALUE cState_init_copy(VALUE obj, VALUE orig)
|
983
|
+
{
|
984
|
+
JSON_Generator_State *objState, *origState;
|
985
|
+
|
986
|
+
Data_Get_Struct(obj, JSON_Generator_State, objState);
|
987
|
+
Data_Get_Struct(orig, JSON_Generator_State, origState);
|
988
|
+
if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State");
|
989
|
+
|
990
|
+
MEMCPY(objState, origState, JSON_Generator_State, 1);
|
991
|
+
objState->indent = fstrndup(origState->indent, origState->indent_len);
|
992
|
+
objState->space = fstrndup(origState->space, origState->space_len);
|
993
|
+
objState->space_before = fstrndup(origState->space_before, origState->space_before_len);
|
994
|
+
objState->object_nl = fstrndup(origState->object_nl, origState->object_nl_len);
|
995
|
+
objState->array_nl = fstrndup(origState->array_nl, origState->array_nl_len);
|
996
|
+
if (origState->array_delim) objState->array_delim = fbuffer_dup(origState->array_delim);
|
997
|
+
if (origState->object_delim) objState->object_delim = fbuffer_dup(origState->object_delim);
|
998
|
+
if (origState->object_delim2) objState->object_delim2 = fbuffer_dup(origState->object_delim2);
|
999
|
+
return obj;
|
1000
|
+
}
|
1001
|
+
|
621
1002
|
/*
|
622
1003
|
* call-seq: from_state(opts)
|
623
1004
|
*
|
@@ -632,7 +1013,10 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
|
|
632
1013
|
} else if (rb_obj_is_kind_of(opts, rb_cHash)) {
|
633
1014
|
return rb_funcall(self, i_new, 1, opts);
|
634
1015
|
} else {
|
635
|
-
|
1016
|
+
if (NIL_P(CJSON_SAFE_STATE_PROTOTYPE)) {
|
1017
|
+
CJSON_SAFE_STATE_PROTOTYPE = rb_const_get(mJSON, rb_intern("SAFE_STATE_PROTOTYPE"));
|
1018
|
+
}
|
1019
|
+
return CJSON_SAFE_STATE_PROTOTYPE;
|
636
1020
|
}
|
637
1021
|
}
|
638
1022
|
|
@@ -644,7 +1028,7 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
|
|
644
1028
|
static VALUE cState_indent(VALUE self)
|
645
1029
|
{
|
646
1030
|
GET_STATE(self);
|
647
|
-
return state->indent;
|
1031
|
+
return state->indent ? rb_str_new2(state->indent) : rb_str_new2("");
|
648
1032
|
}
|
649
1033
|
|
650
1034
|
/*
|
@@ -656,7 +1040,16 @@ static VALUE cState_indent_set(VALUE self, VALUE indent)
|
|
656
1040
|
{
|
657
1041
|
GET_STATE(self);
|
658
1042
|
Check_Type(indent, T_STRING);
|
659
|
-
|
1043
|
+
if (RSTRING_LEN(indent) == 0) {
|
1044
|
+
if (state->indent) {
|
1045
|
+
ruby_xfree(state->indent);
|
1046
|
+
state->indent = NULL;
|
1047
|
+
}
|
1048
|
+
} else {
|
1049
|
+
if (state->indent) ruby_xfree(state->indent);
|
1050
|
+
state->indent = strdup(RSTRING_PTR(indent));
|
1051
|
+
}
|
1052
|
+
return Qnil;
|
660
1053
|
}
|
661
1054
|
|
662
1055
|
/*
|
@@ -668,7 +1061,7 @@ static VALUE cState_indent_set(VALUE self, VALUE indent)
|
|
668
1061
|
static VALUE cState_space(VALUE self)
|
669
1062
|
{
|
670
1063
|
GET_STATE(self);
|
671
|
-
return state->space;
|
1064
|
+
return state->space ? rb_str_new2(state->space) : rb_str_new2("");
|
672
1065
|
}
|
673
1066
|
|
674
1067
|
/*
|
@@ -681,7 +1074,16 @@ static VALUE cState_space_set(VALUE self, VALUE space)
|
|
681
1074
|
{
|
682
1075
|
GET_STATE(self);
|
683
1076
|
Check_Type(space, T_STRING);
|
684
|
-
|
1077
|
+
if (RSTRING_LEN(space) == 0) {
|
1078
|
+
if (state->space) {
|
1079
|
+
ruby_xfree(state->space);
|
1080
|
+
state->space = NULL;
|
1081
|
+
}
|
1082
|
+
} else {
|
1083
|
+
if (state->space) ruby_xfree(state->space);
|
1084
|
+
state->space = strdup(RSTRING_PTR(space));
|
1085
|
+
}
|
1086
|
+
return Qnil;
|
685
1087
|
}
|
686
1088
|
|
687
1089
|
/*
|
@@ -692,7 +1094,7 @@ static VALUE cState_space_set(VALUE self, VALUE space)
|
|
692
1094
|
static VALUE cState_space_before(VALUE self)
|
693
1095
|
{
|
694
1096
|
GET_STATE(self);
|
695
|
-
return state->space_before;
|
1097
|
+
return state->space_before ? rb_str_new2(state->space_before) : rb_str_new2("");
|
696
1098
|
}
|
697
1099
|
|
698
1100
|
/*
|
@@ -704,7 +1106,16 @@ static VALUE cState_space_before_set(VALUE self, VALUE space_before)
|
|
704
1106
|
{
|
705
1107
|
GET_STATE(self);
|
706
1108
|
Check_Type(space_before, T_STRING);
|
707
|
-
|
1109
|
+
if (RSTRING_LEN(space_before) == 0) {
|
1110
|
+
if (state->space_before) {
|
1111
|
+
ruby_xfree(state->space_before);
|
1112
|
+
state->space_before = NULL;
|
1113
|
+
}
|
1114
|
+
} else {
|
1115
|
+
if (state->space_before) ruby_xfree(state->space_before);
|
1116
|
+
state->space_before = strdup(RSTRING_PTR(space_before));
|
1117
|
+
}
|
1118
|
+
return Qnil;
|
708
1119
|
}
|
709
1120
|
|
710
1121
|
/*
|
@@ -716,7 +1127,7 @@ static VALUE cState_space_before_set(VALUE self, VALUE space_before)
|
|
716
1127
|
static VALUE cState_object_nl(VALUE self)
|
717
1128
|
{
|
718
1129
|
GET_STATE(self);
|
719
|
-
return state->object_nl;
|
1130
|
+
return state->object_nl ? rb_str_new2(state->object_nl) : rb_str_new2("");
|
720
1131
|
}
|
721
1132
|
|
722
1133
|
/*
|
@@ -729,7 +1140,16 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
|
|
729
1140
|
{
|
730
1141
|
GET_STATE(self);
|
731
1142
|
Check_Type(object_nl, T_STRING);
|
732
|
-
|
1143
|
+
if (RSTRING_LEN(object_nl) == 0) {
|
1144
|
+
if (state->object_nl) {
|
1145
|
+
ruby_xfree(state->object_nl);
|
1146
|
+
state->object_nl = NULL;
|
1147
|
+
}
|
1148
|
+
} else {
|
1149
|
+
if (state->object_nl) ruby_xfree(state->object_nl);
|
1150
|
+
state->object_nl = strdup(RSTRING_PTR(object_nl));
|
1151
|
+
}
|
1152
|
+
return Qnil;
|
733
1153
|
}
|
734
1154
|
|
735
1155
|
/*
|
@@ -740,7 +1160,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
|
|
740
1160
|
static VALUE cState_array_nl(VALUE self)
|
741
1161
|
{
|
742
1162
|
GET_STATE(self);
|
743
|
-
return state->array_nl;
|
1163
|
+
return state->array_nl ? rb_str_new2(state->array_nl) : rb_str_new2("");
|
744
1164
|
}
|
745
1165
|
|
746
1166
|
/*
|
@@ -752,19 +1172,29 @@ static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
|
|
752
1172
|
{
|
753
1173
|
GET_STATE(self);
|
754
1174
|
Check_Type(array_nl, T_STRING);
|
755
|
-
|
1175
|
+
if (RSTRING_LEN(array_nl) == 0) {
|
1176
|
+
if (state->array_nl) {
|
1177
|
+
ruby_xfree(state->array_nl);
|
1178
|
+
state->array_nl = NULL;
|
1179
|
+
}
|
1180
|
+
} else {
|
1181
|
+
if (state->array_nl) ruby_xfree(state->array_nl);
|
1182
|
+
state->array_nl = strdup(RSTRING_PTR(array_nl));
|
1183
|
+
}
|
1184
|
+
return Qnil;
|
756
1185
|
}
|
757
1186
|
|
1187
|
+
|
758
1188
|
/*
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
1189
|
+
* call-seq: check_circular?
|
1190
|
+
*
|
1191
|
+
* Returns true, if circular data structures should be checked,
|
1192
|
+
* otherwise returns false.
|
1193
|
+
*/
|
764
1194
|
static VALUE cState_check_circular_p(VALUE self)
|
765
1195
|
{
|
766
1196
|
GET_STATE(self);
|
767
|
-
return state->
|
1197
|
+
return state->max_nesting ? Qtrue : Qfalse;
|
768
1198
|
}
|
769
1199
|
|
770
1200
|
/*
|
@@ -789,8 +1219,7 @@ static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
|
|
789
1219
|
{
|
790
1220
|
GET_STATE(self);
|
791
1221
|
Check_Type(depth, T_FIXNUM);
|
792
|
-
state->max_nesting = FIX2LONG(depth);
|
793
|
-
return Qnil;
|
1222
|
+
return state->max_nesting = FIX2LONG(depth);
|
794
1223
|
}
|
795
1224
|
|
796
1225
|
/*
|
@@ -806,37 +1235,15 @@ static VALUE cState_allow_nan_p(VALUE self)
|
|
806
1235
|
}
|
807
1236
|
|
808
1237
|
/*
|
809
|
-
* call-seq:
|
810
|
-
*
|
811
|
-
* Returns _true_, if _object_ was already seen during this generating run.
|
812
|
-
*/
|
813
|
-
static VALUE cState_seen_p(VALUE self, VALUE object)
|
814
|
-
{
|
815
|
-
GET_STATE(self);
|
816
|
-
return rb_hash_aref(state->seen, rb_obj_id(object));
|
817
|
-
}
|
818
|
-
|
819
|
-
/*
|
820
|
-
* call-seq: remember(object)
|
1238
|
+
* call-seq: ascii_only?
|
821
1239
|
*
|
822
|
-
*
|
823
|
-
*
|
824
|
-
*/
|
825
|
-
static VALUE cState_remember(VALUE self, VALUE object)
|
826
|
-
{
|
827
|
-
GET_STATE(self);
|
828
|
-
return rb_hash_aset(state->seen, rb_obj_id(object), Qtrue);
|
829
|
-
}
|
830
|
-
|
831
|
-
/*
|
832
|
-
* call-seq: forget(object)
|
833
|
-
*
|
834
|
-
* Forget _object_ for this generating run.
|
1240
|
+
* Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
|
1241
|
+
* returns false.
|
835
1242
|
*/
|
836
|
-
static VALUE
|
1243
|
+
static VALUE cState_ascii_only_p(VALUE self)
|
837
1244
|
{
|
838
1245
|
GET_STATE(self);
|
839
|
-
return
|
1246
|
+
return state->ascii_only ? Qtrue : Qfalse;
|
840
1247
|
}
|
841
1248
|
|
842
1249
|
/*
|
@@ -845,17 +1252,19 @@ static VALUE cState_forget(VALUE self, VALUE object)
|
|
845
1252
|
void Init_generator()
|
846
1253
|
{
|
847
1254
|
rb_require("json/common");
|
1255
|
+
|
848
1256
|
mJSON = rb_define_module("JSON");
|
849
1257
|
mExt = rb_define_module_under(mJSON, "Ext");
|
850
1258
|
mGenerator = rb_define_module_under(mExt, "Generator");
|
1259
|
+
|
851
1260
|
eGeneratorError = rb_path2class("JSON::GeneratorError");
|
852
|
-
eCircularDatastructure = rb_path2class("JSON::CircularDatastructure");
|
853
1261
|
eNestingError = rb_path2class("JSON::NestingError");
|
1262
|
+
|
854
1263
|
cState = rb_define_class_under(mGenerator, "State", rb_cObject);
|
855
1264
|
rb_define_alloc_func(cState, cState_s_allocate);
|
856
1265
|
rb_define_singleton_method(cState, "from_state", cState_from_state_s, 1);
|
857
1266
|
rb_define_method(cState, "initialize", cState_initialize, -1);
|
858
|
-
|
1267
|
+
rb_define_method(cState, "initialize_copy", cState_init_copy, 1);
|
859
1268
|
rb_define_method(cState, "indent", cState_indent, 0);
|
860
1269
|
rb_define_method(cState, "indent=", cState_indent_set, 1);
|
861
1270
|
rb_define_method(cState, "space", cState_space, 0);
|
@@ -866,15 +1275,16 @@ void Init_generator()
|
|
866
1275
|
rb_define_method(cState, "object_nl=", cState_object_nl_set, 1);
|
867
1276
|
rb_define_method(cState, "array_nl", cState_array_nl, 0);
|
868
1277
|
rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
|
869
|
-
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
|
870
1278
|
rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
|
871
1279
|
rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
|
1280
|
+
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
|
872
1281
|
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
|
873
|
-
rb_define_method(cState, "
|
874
|
-
rb_define_method(cState, "remember", cState_remember, 1);
|
875
|
-
rb_define_method(cState, "forget", cState_forget, 1);
|
1282
|
+
rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
|
876
1283
|
rb_define_method(cState, "configure", cState_configure, 1);
|
877
1284
|
rb_define_method(cState, "to_h", cState_to_h, 0);
|
1285
|
+
rb_define_method(cState, "[]", cState_aref, 1);
|
1286
|
+
rb_define_method(cState, "generate", cState_generate, 1);
|
1287
|
+
rb_define_method(cState, "partial_generate", cState_partial_generate, 1);
|
878
1288
|
|
879
1289
|
mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
|
880
1290
|
mObject = rb_define_module_under(mGeneratorMethods, "Object");
|
@@ -901,6 +1311,7 @@ void Init_generator()
|
|
901
1311
|
mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
|
902
1312
|
rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
|
903
1313
|
|
1314
|
+
CRegexp_MULTILINE = rb_const_get(rb_cRegexp, rb_intern("MULTILINE"));
|
904
1315
|
i_to_s = rb_intern("to_s");
|
905
1316
|
i_to_json = rb_intern("to_json");
|
906
1317
|
i_new = rb_intern("new");
|
@@ -909,11 +1320,22 @@ void Init_generator()
|
|
909
1320
|
i_space_before = rb_intern("space_before");
|
910
1321
|
i_object_nl = rb_intern("object_nl");
|
911
1322
|
i_array_nl = rb_intern("array_nl");
|
912
|
-
i_check_circular = rb_intern("check_circular");
|
913
1323
|
i_max_nesting = rb_intern("max_nesting");
|
914
1324
|
i_allow_nan = rb_intern("allow_nan");
|
1325
|
+
i_ascii_only = rb_intern("ascii_only");
|
915
1326
|
i_pack = rb_intern("pack");
|
916
1327
|
i_unpack = rb_intern("unpack");
|
917
1328
|
i_create_id = rb_intern("create_id");
|
918
1329
|
i_extend = rb_intern("extend");
|
1330
|
+
i_key_p = rb_intern("key?");
|
1331
|
+
i_aref = rb_intern("[]");
|
1332
|
+
i_send = rb_intern("__send__");
|
1333
|
+
i_respond_to_p = rb_intern("respond_to?");
|
1334
|
+
i_match = rb_intern("match");
|
1335
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
1336
|
+
CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
|
1337
|
+
i_encoding = rb_intern("encoding");
|
1338
|
+
i_encode = rb_intern("encode");
|
1339
|
+
#endif
|
1340
|
+
CJSON_SAFE_STATE_PROTOTYPE = Qnil;
|
919
1341
|
}
|