json 1.2.4 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of json might be problematic. Click here for more details.

@@ -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 500
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 100
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 100
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 100
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 500
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 1000
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
@@ -74,9 +78,10 @@ class ParserBenchmarkPure < Bullshit::RepeatCase
74
78
  include ParserBenchmarkCommon
75
79
 
76
80
  warmup yes
77
- iterations 1000
81
+ iterations 400
78
82
 
79
83
  truncate_data do
84
+ enabled false
80
85
  alpha_level 0.05
81
86
  window_size 50
82
87
  slope_angle 0.1
@@ -108,9 +113,10 @@ end
108
113
 
109
114
  class ParserBenchmarkYAML < Bullshit::RepeatCase
110
115
  warmup yes
111
- iterations 1000
116
+ iterations 400
112
117
 
113
118
  truncate_data do
119
+ enabled false
114
120
  alpha_level 0.05
115
121
  window_size 50
116
122
  slope_angle 0.1
@@ -144,9 +150,10 @@ end
144
150
 
145
151
  class ParserBenchmarkRails < Bullshit::RepeatCase
146
152
  warmup yes
147
- iterations 1000
153
+ iterations 400
148
154
 
149
155
  truncate_data do
156
+ enabled false
150
157
  alpha_level 0.05
151
158
  window_size 50
152
159
  slope_angle 0.1
@@ -178,6 +185,43 @@ class ParserBenchmarkRails < Bullshit::RepeatCase
178
185
  end
179
186
  end
180
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
+
181
225
  if $0 == __FILE__
182
226
  Bullshit::Case.autorun false
183
227
 
@@ -190,6 +234,8 @@ if $0 == __FILE__
190
234
  ParserBenchmarkYAML.run
191
235
  when 'rails'
192
236
  ParserBenchmarkRails.run
237
+ when 'yajl'
238
+ ParserBenchmarkYajl.run
193
239
  else
194
240
  system "#{RAKE_PATH} clean"
195
241
  system "#{RUBY_PATH} #$0 yaml"
@@ -197,6 +243,7 @@ if $0 == __FILE__
197
243
  system "#{RUBY_PATH} #$0 pure"
198
244
  system "#{RAKE_PATH} compile_ext"
199
245
  system "#{RUBY_PATH} #$0 ext"
246
+ system "#{RUBY_PATH} #$0 yajl"
200
247
  Bullshit.compare do
201
248
  output_filename File.join(File.dirname(__FILE__), 'data', 'ParserBenchmarkComparison.log')
202
249
 
@@ -206,6 +253,7 @@ if $0 == __FILE__
206
253
  benchmark ParserBenchmarkPure, :parser_symbolic, :load => yes
207
254
  benchmark ParserBenchmarkYAML, :parser, :load => yes
208
255
  benchmark ParserBenchmarkRails, :parser, :load => yes
256
+ benchmark ParserBenchmarkYajl, :parser, :load => yes
209
257
  end
210
258
  end
211
259
  end
@@ -0,0 +1,16 @@
1
+ require 'mkmf'
2
+ require 'rbconfig'
3
+
4
+ unless $CFLAGS.gsub!(/ -O[\dsz]?/, ' -O3')
5
+ $CFLAGS << ' -O3'
6
+ end
7
+ if CONFIG['CC'] =~ /gcc/
8
+ $CFLAGS << ' -Wall'
9
+ #unless $CFLAGS.gsub!(/ -O[\dsz]?/, ' -O0 -ggdb')
10
+ # $CFLAGS << ' -O0 -ggdb'
11
+ #end
12
+ end
13
+
14
+ have_header("ruby/re.h") || have_header("re.h")
15
+ have_header("ruby/encoding.h")
16
+ create_makefile 'generator'
@@ -0,0 +1,15 @@
1
+ require 'mkmf'
2
+ require 'rbconfig'
3
+
4
+ unless $CFLAGS.gsub!(/ -O[\dsz]?/, ' -O3')
5
+ $CFLAGS << ' -O3'
6
+ end
7
+ if CONFIG['CC'] =~ /gcc/
8
+ $CFLAGS << ' -Wall'
9
+ #unless $CFLAGS.gsub!(/ -O[\dsz]?/, ' -O0 -ggdb')
10
+ # $CFLAGS << ' -O0 -ggdb'
11
+ #end
12
+ end
13
+
14
+ have_header("re.h")
15
+ create_makefile 'parser'
@@ -0,0 +1,1334 @@
1
+ #include "generator.h"
2
+
3
+ #ifdef HAVE_RUBY_ENCODING_H
4
+ static VALUE CEncoding_UTF_8;
5
+ static ID i_encoding, i_encode;
6
+ #endif
7
+
8
+ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
9
+ mHash, mArray, mInteger, mFloat, mString, mString_Extend,
10
+ mTrueClass, mFalseClass, mNilClass, eGeneratorError,
11
+ eNestingError, CRegexp_MULTILINE, CJSON_SAFE_STATE_PROTOTYPE;
12
+
13
+ static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
14
+ i_object_nl, i_array_nl, i_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;
17
+
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.
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";
106
+
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)
117
+ {
118
+ unicode_escape(buf, character);
119
+ fbuffer_append(buffer, buf, 6);
120
+ }
121
+
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, 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
+ }
215
+ }
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;
282
+ }
283
+ fbuffer_append(buffer, ptr + start, end - start);
284
+ }
285
+
286
+ static char *fstrndup(const char *ptr, int len) {
287
+ if (len <= 0) return NULL;
288
+ char *result = ALLOC_N(char, len);
289
+ memccpy(result, ptr, 0, len);
290
+ return result;
291
+ }
292
+
293
+ /* fbuffer implementation */
294
+
295
+ static FBuffer *fbuffer_alloc()
296
+ {
297
+ FBuffer *fb = ALLOC(FBuffer);
298
+ memset((void *) fb, 0, sizeof(FBuffer));
299
+ fb->initial_length = FBUFFER_INITIAL_LENGTH;
300
+ return fb;
301
+ }
302
+
303
+ static FBuffer *fbuffer_alloc_with_length(unsigned int initial_length)
304
+ {
305
+ assert(initial_length > 0);
306
+ FBuffer *fb = ALLOC(FBuffer);
307
+ memset((void *) fb, 0, sizeof(FBuffer));
308
+ fb->initial_length = initial_length;
309
+ return fb;
310
+ }
311
+
312
+ static void fbuffer_free(FBuffer *fb)
313
+ {
314
+ if (fb->ptr) ruby_xfree(fb->ptr);
315
+ ruby_xfree(fb);
316
+ }
317
+
318
+ static void fbuffer_free_only_buffer(FBuffer *fb)
319
+ {
320
+ ruby_xfree(fb);
321
+ }
322
+
323
+ static void fbuffer_clear(FBuffer *fb)
324
+ {
325
+ fb->len = 0;
326
+ }
327
+
328
+ static void fbuffer_inc_capa(FBuffer *fb, unsigned int requested)
329
+ {
330
+ unsigned int required;
331
+
332
+ if (!fb->ptr) {
333
+ fb->ptr = ALLOC_N(char, fb->initial_length);
334
+ fb->capa = fb->initial_length;
335
+ }
336
+
337
+ for (required = fb->capa; requested > required - fb->len; required <<= 1);
338
+
339
+ if (required > fb->capa) {
340
+ fb->ptr = (char *) REALLOC_N((long*) fb->ptr, char, required);
341
+ fb->capa = required;
342
+ }
343
+ }
344
+
345
+ static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned int len)
346
+ {
347
+ if (len > 0) {
348
+ fbuffer_inc_capa(fb, len);
349
+ MEMCPY(fb->ptr + fb->len, newstr, char, len);
350
+ fb->len += len;
351
+ }
352
+ }
353
+
354
+ static void fbuffer_append_char(FBuffer *fb, char newchr)
355
+ {
356
+ fbuffer_inc_capa(fb, 1);
357
+ *(fb->ptr + fb->len) = newchr;
358
+ fb->len++;
359
+ }
360
+
361
+ static void freverse(char *start, char *end)
362
+ {
363
+ char c;
364
+
365
+ while (end > start) {
366
+ c = *end, *end-- = *start, *start++ = c;
367
+ }
368
+ }
369
+
370
+ static int fitoa(int number, char *buf)
371
+ {
372
+ static char digits[] = "0123456789";
373
+ int sign = number;
374
+ char* tmp = buf;
375
+
376
+ if (sign < 0) number = -number;
377
+ do *tmp++ = digits[number % 10]; while (number /= 10);
378
+ if (sign < 0) *tmp++ = '-';
379
+ freverse(buf, tmp - 1);
380
+ return tmp - buf;
381
+ }
382
+
383
+ static void fbuffer_append_integer(FBuffer *fb, int number)
384
+ {
385
+ char buf[12];
386
+ int len = fitoa(number, buf);
387
+ fbuffer_append(fb, buf, len);
388
+ }
389
+
390
+ static FBuffer *fbuffer_dup(FBuffer *fb)
391
+ {
392
+ int len = fb->len;
393
+ FBuffer *result;
394
+
395
+ if (len > 0) {
396
+ result = fbuffer_alloc_with_length(len);
397
+ fbuffer_append(result, FBUFFER_PAIR(fb));
398
+ } else {
399
+ result = fbuffer_alloc();
400
+ }
401
+ return result;
402
+ }
403
+
404
+ /*
405
+ * Document-module: JSON::Ext::Generator
406
+ *
407
+ * This is the JSON generator implemented as a C extension. It can be
408
+ * configured to be used by setting
409
+ *
410
+ * JSON.generator = JSON::Ext::Generator
411
+ *
412
+ * with the method generator= in JSON.
413
+ *
414
+ */
415
+
416
+ /*
417
+ * call-seq: to_json(state = nil, depth = 0)
418
+ *
419
+ * Returns a JSON string containing a JSON object, that is generated from
420
+ * this Hash instance.
421
+ * _state_ is a JSON::State object, that can also be used to configure the
422
+ * produced JSON string output further.
423
+ * _depth_ is used to find out nesting depth, to indent accordingly.
424
+ */
425
+ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
426
+ {
427
+ VALUE state, depth;
428
+
429
+ rb_scan_args(argc, argv, "02", &state, &depth);
430
+ state = cState_from_state_s(cState, state);
431
+ return cState_partial_generate(state, self, depth);
432
+ }
433
+
434
+ /*
435
+ * call-seq: to_json(state = nil, depth = 0)
436
+ *
437
+ * Returns a JSON string containing a JSON array, that is generated from
438
+ * this Array instance.
439
+ * _state_ is a JSON::State object, that can also be used to configure the
440
+ * produced JSON string output further.
441
+ * _depth_ is used to find out nesting depth, to indent accordingly.
442
+ */
443
+ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
444
+ VALUE state, depth;
445
+ rb_scan_args(argc, argv, "02", &state, &depth);
446
+ state = cState_from_state_s(cState, state);
447
+ return cState_partial_generate(state, self, depth);
448
+ }
449
+
450
+ /*
451
+ * call-seq: to_json(*)
452
+ *
453
+ * Returns a JSON string representation for this Integer number.
454
+ */
455
+ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
456
+ {
457
+ VALUE state, depth;
458
+ rb_scan_args(argc, argv, "02", &state, &depth);
459
+ state = cState_from_state_s(cState, state);
460
+ return cState_partial_generate(state, self, depth);
461
+ }
462
+
463
+ /*
464
+ * call-seq: to_json(*)
465
+ *
466
+ * Returns a JSON string representation for this Float number.
467
+ */
468
+ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
469
+ {
470
+ VALUE state, depth;
471
+ rb_scan_args(argc, argv, "02", &state, &depth);
472
+ state = cState_from_state_s(cState, state);
473
+ return cState_partial_generate(state, self, depth);
474
+ }
475
+
476
+ /*
477
+ * call-seq: String.included(modul)
478
+ *
479
+ * Extends _modul_ with the String::Extend module.
480
+ */
481
+ static VALUE mString_included_s(VALUE self, VALUE modul) {
482
+ VALUE result = rb_funcall(modul, i_extend, 1, mString_Extend);
483
+ return result;
484
+ }
485
+
486
+ /*
487
+ * call-seq: to_json(*)
488
+ *
489
+ * This string should be encoded with UTF-8 A call to this method
490
+ * returns a JSON string encoded with UTF16 big endian characters as
491
+ * \u????.
492
+ */
493
+ static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
494
+ {
495
+ VALUE state, depth;
496
+ rb_scan_args(argc, argv, "02", &state, &depth);
497
+ state = cState_from_state_s(cState, state);
498
+ return cState_partial_generate(state, self, depth);
499
+ }
500
+
501
+ /*
502
+ * call-seq: to_json_raw_object()
503
+ *
504
+ * This method creates a raw object hash, that can be nested into
505
+ * other data structures and will be generated as a raw string. This
506
+ * method should be used, if you want to convert raw strings to JSON
507
+ * instead of UTF-8 strings, e. g. binary data.
508
+ */
509
+ static VALUE mString_to_json_raw_object(VALUE self)
510
+ {
511
+ VALUE ary;
512
+ VALUE result = rb_hash_new();
513
+ rb_hash_aset(result, rb_funcall(mJSON, i_create_id, 0), rb_class_name(rb_obj_class(self)));
514
+ ary = rb_funcall(self, i_unpack, 1, rb_str_new2("C*"));
515
+ rb_hash_aset(result, rb_str_new2("raw"), ary);
516
+ return result;
517
+ }
518
+
519
+ /*
520
+ * call-seq: to_json_raw(*args)
521
+ *
522
+ * This method creates a JSON text from the result of a call to
523
+ * to_json_raw_object of this String.
524
+ */
525
+ static VALUE mString_to_json_raw(int argc, VALUE *argv, VALUE self)
526
+ {
527
+ VALUE obj = mString_to_json_raw_object(self);
528
+ Check_Type(obj, T_HASH);
529
+ return mHash_to_json(argc, argv, obj);
530
+ }
531
+
532
+ /*
533
+ * call-seq: json_create(o)
534
+ *
535
+ * Raw Strings are JSON Objects (the raw bytes are stored in an array for the
536
+ * key "raw"). The Ruby String can be created by this module method.
537
+ */
538
+ static VALUE mString_Extend_json_create(VALUE self, VALUE o)
539
+ {
540
+ VALUE ary;
541
+ Check_Type(o, T_HASH);
542
+ ary = rb_hash_aref(o, rb_str_new2("raw"));
543
+ return rb_funcall(ary, i_pack, 1, rb_str_new2("C*"));
544
+ }
545
+
546
+ /*
547
+ * call-seq: to_json(*)
548
+ *
549
+ * Returns a JSON string for true: 'true'.
550
+ */
551
+ static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
552
+ {
553
+ VALUE state, depth;
554
+ rb_scan_args(argc, argv, "02", &state, &depth);
555
+ state = cState_from_state_s(cState, state);
556
+ return cState_partial_generate(state, self, depth);
557
+ }
558
+
559
+ /*
560
+ * call-seq: to_json(*)
561
+ *
562
+ * Returns a JSON string for false: 'false'.
563
+ */
564
+ static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
565
+ {
566
+ VALUE state, depth;
567
+ rb_scan_args(argc, argv, "02", &state, &depth);
568
+ state = cState_from_state_s(cState, state);
569
+ return cState_partial_generate(state, self, depth);
570
+ }
571
+
572
+ /*
573
+ * call-seq: to_json(*)
574
+ *
575
+ */
576
+ static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
577
+ {
578
+ VALUE state, depth;
579
+ rb_scan_args(argc, argv, "02", &state, &depth);
580
+ state = cState_from_state_s(cState, state);
581
+ return cState_partial_generate(state, self, depth);
582
+ }
583
+
584
+ /*
585
+ * call-seq: to_json(*)
586
+ *
587
+ * Converts this object to a string (calling #to_s), converts
588
+ * it to a JSON string, and returns the result. This is a fallback, if no
589
+ * special method #to_json was defined for some object.
590
+ */
591
+ static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
592
+ {
593
+ VALUE state, depth;
594
+ VALUE string = rb_funcall(self, i_to_s, 0);
595
+ rb_scan_args(argc, argv, "02", &state, &depth);
596
+ Check_Type(string, T_STRING);
597
+ state = cState_from_state_s(cState, state);
598
+ return cState_partial_generate(state, string, depth);
599
+ }
600
+
601
+ static void State_free(JSON_Generator_State *state)
602
+ {
603
+ if (state->indent) ruby_xfree(state->indent);
604
+ if (state->space) ruby_xfree(state->space);
605
+ if (state->space_before) ruby_xfree(state->space_before);
606
+ if (state->object_nl) ruby_xfree(state->object_nl);
607
+ if (state->array_nl) ruby_xfree(state->array_nl);
608
+ if (state->array_delim) fbuffer_free(state->array_delim);
609
+ if (state->object_delim) fbuffer_free(state->object_delim);
610
+ if (state->object_delim2) fbuffer_free(state->object_delim2);
611
+ ruby_xfree(state);
612
+ }
613
+
614
+ static JSON_Generator_State *State_allocate()
615
+ {
616
+ JSON_Generator_State *state = ALLOC(JSON_Generator_State);
617
+ return state;
618
+ }
619
+
620
+ static VALUE cState_s_allocate(VALUE klass)
621
+ {
622
+ JSON_Generator_State *state = State_allocate();
623
+ return Data_Wrap_Struct(klass, NULL, State_free, state);
624
+ }
625
+
626
+ /*
627
+ * call-seq: configure(opts)
628
+ *
629
+ * Configure this State instance with the Hash _opts_, and return
630
+ * itself.
631
+ */
632
+ static VALUE cState_configure(VALUE self, VALUE opts)
633
+ {
634
+ VALUE tmp;
635
+ GET_STATE(self);
636
+ tmp = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
637
+ if (NIL_P(tmp)) tmp = rb_convert_type(opts, T_HASH, "Hash", "to_h");
638
+ if (NIL_P(tmp)) {
639
+ rb_raise(rb_eArgError, "opts has to be hash like or convertable into a hash");
640
+ }
641
+ opts = tmp;
642
+ tmp = rb_hash_aref(opts, ID2SYM(i_indent));
643
+ if (RTEST(tmp)) {
644
+ Check_Type(tmp, T_STRING);
645
+ int len = RSTRING_LEN(tmp);
646
+ state->indent = fstrndup(RSTRING_PTR(tmp), len);
647
+ state->indent_len = len;
648
+ }
649
+ tmp = rb_hash_aref(opts, ID2SYM(i_space));
650
+ if (RTEST(tmp)) {
651
+ Check_Type(tmp, T_STRING);
652
+ int len = RSTRING_LEN(tmp);
653
+ state->space = fstrndup(RSTRING_PTR(tmp), len);
654
+ state->space_len = len;
655
+ }
656
+ tmp = rb_hash_aref(opts, ID2SYM(i_space_before));
657
+ if (RTEST(tmp)) {
658
+ Check_Type(tmp, T_STRING);
659
+ int len = RSTRING_LEN(tmp);
660
+ state->space_before = fstrndup(RSTRING_PTR(tmp), len);
661
+ state->space_before_len = len;
662
+ }
663
+ tmp = rb_hash_aref(opts, ID2SYM(i_array_nl));
664
+ if (RTEST(tmp)) {
665
+ Check_Type(tmp, T_STRING);
666
+ int len = RSTRING_LEN(tmp);
667
+ state->array_nl = fstrndup(RSTRING_PTR(tmp), len);
668
+ state->array_nl_len = len;
669
+ }
670
+ tmp = rb_hash_aref(opts, ID2SYM(i_object_nl));
671
+ if (RTEST(tmp)) {
672
+ Check_Type(tmp, T_STRING);
673
+ int len = RSTRING_LEN(tmp);
674
+ state->object_nl = fstrndup(RSTRING_PTR(tmp), len);
675
+ state->object_nl_len = len;
676
+ }
677
+ tmp = ID2SYM(i_max_nesting);
678
+ state->max_nesting = 19;
679
+ if (option_given_p(opts, tmp)) {
680
+ VALUE max_nesting = rb_hash_aref(opts, tmp);
681
+ if (RTEST(max_nesting)) {
682
+ Check_Type(max_nesting, T_FIXNUM);
683
+ state->max_nesting = FIX2LONG(max_nesting);
684
+ } else {
685
+ state->max_nesting = 0;
686
+ }
687
+ }
688
+ tmp = rb_hash_aref(opts, ID2SYM(i_allow_nan));
689
+ state->allow_nan = RTEST(tmp);
690
+ tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
691
+ state->ascii_only = RTEST(tmp);
692
+ return self;
693
+ }
694
+
695
+ /*
696
+ * call-seq: to_h
697
+ *
698
+ * Returns the configuration instance variables as a hash, that can be
699
+ * passed to the configure method.
700
+ */
701
+ static VALUE cState_to_h(VALUE self)
702
+ {
703
+ VALUE result = rb_hash_new();
704
+ GET_STATE(self);
705
+ rb_hash_aset(result, ID2SYM(i_indent), rb_str_new(state->indent, state->indent_len));
706
+ rb_hash_aset(result, ID2SYM(i_space), rb_str_new(state->space, state->space_len));
707
+ rb_hash_aset(result, ID2SYM(i_space_before), rb_str_new(state->space_before, state->space_before_len));
708
+ rb_hash_aset(result, ID2SYM(i_object_nl), rb_str_new(state->object_nl, state->object_nl_len));
709
+ rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len));
710
+ rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
711
+ rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
712
+ rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
713
+ return result;
714
+ }
715
+
716
+ /*
717
+ * call-seq: [](name)
718
+ *
719
+ * Return the value returned by method +name+.
720
+ */
721
+ static VALUE cState_aref(VALUE self, VALUE name)
722
+ {
723
+ GET_STATE(self);
724
+ if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
725
+ return rb_funcall(self, i_send, 1, name);
726
+ } else {
727
+ return Qnil;
728
+ }
729
+ }
730
+
731
+ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj, long depth)
732
+ {
733
+ VALUE tmp;
734
+ switch (TYPE(obj)) {
735
+ case T_HASH:
736
+ {
737
+ char *object_nl = state->object_nl;
738
+ long object_nl_len = state->object_nl_len;
739
+ char *indent = state->indent;
740
+ long indent_len = state->indent_len;
741
+ long max_nesting = state->max_nesting;
742
+ char *delim = FBUFFER_PTR(state->object_delim);
743
+ long delim_len = FBUFFER_LEN(state->object_delim);
744
+ char *delim2 = FBUFFER_PTR(state->object_delim2);
745
+ long delim2_len = FBUFFER_LEN(state->object_delim2);
746
+ int i, j;
747
+ depth++;
748
+ if (max_nesting != 0 && depth > max_nesting) {
749
+ fbuffer_free(buffer);
750
+ rb_raise(eNestingError, "nesting of %ld is too deep", depth);
751
+ }
752
+ fbuffer_append_char(buffer, '{');
753
+ VALUE keys = rb_funcall(obj, rb_intern("keys"), 0);
754
+ VALUE key, key_to_s;
755
+ for(i = 0; i < RARRAY_LEN(keys); i++) {
756
+ if (i > 0) fbuffer_append(buffer, delim, delim_len);
757
+ if (object_nl) {
758
+ fbuffer_append(buffer, object_nl, object_nl_len);
759
+ }
760
+ if (indent) {
761
+ for (j = 0; j < depth; j++) {
762
+ fbuffer_append(buffer, indent, indent_len);
763
+ }
764
+ }
765
+ key = rb_ary_entry(keys, i);
766
+ key_to_s = rb_funcall(key, i_to_s, 0);
767
+ Check_Type(key_to_s, T_STRING);
768
+ generate_json(buffer, Vstate, state, key_to_s, depth);
769
+ fbuffer_append(buffer, delim2, delim2_len);
770
+ generate_json(buffer, Vstate, state, rb_hash_aref(obj, key), depth);
771
+ }
772
+ depth--;
773
+ if (object_nl) {
774
+ fbuffer_append(buffer, object_nl, object_nl_len);
775
+ if (indent) {
776
+ for (j = 0; j < depth; j++) {
777
+ fbuffer_append(buffer, indent, indent_len);
778
+ }
779
+ }
780
+ }
781
+ fbuffer_append_char(buffer, '}');
782
+ }
783
+ break;
784
+ case T_ARRAY:
785
+ {
786
+ char *array_nl = state->array_nl;
787
+ long array_nl_len = state->array_nl_len;
788
+ char *indent = state->indent;
789
+ long indent_len = state->indent_len;
790
+ long max_nesting = state->max_nesting;
791
+ char *delim = FBUFFER_PTR(state->array_delim);
792
+ long delim_len = FBUFFER_LEN(state->array_delim);
793
+ int i, j;
794
+ depth++;
795
+ if (max_nesting != 0 && depth > max_nesting) {
796
+ fbuffer_free(buffer);
797
+ rb_raise(eNestingError, "nesting of %ld is too deep", depth);
798
+ }
799
+ fbuffer_append_char(buffer, '[');
800
+ if (array_nl) fbuffer_append(buffer, array_nl, array_nl_len);
801
+ for(i = 0; i < RARRAY_LEN(obj); i++) {
802
+ if (i > 0) fbuffer_append(buffer, delim, delim_len);
803
+ if (indent) {
804
+ for (j = 0; j < depth; j++) {
805
+ fbuffer_append(buffer, indent, indent_len);
806
+ }
807
+ }
808
+ generate_json(buffer, Vstate, state, rb_ary_entry(obj, i), depth);
809
+ }
810
+ depth--;
811
+ if (array_nl) {
812
+ fbuffer_append(buffer, array_nl, array_nl_len);
813
+ if (indent) {
814
+ for (j = 0; j < depth; j++) {
815
+ fbuffer_append(buffer, indent, indent_len);
816
+ }
817
+ }
818
+ }
819
+ fbuffer_append_char(buffer, ']');
820
+ }
821
+ break;
822
+ case T_STRING:
823
+ fbuffer_append_char(buffer, '"');
824
+ #ifdef HAVE_RUBY_ENCODING_H
825
+ obj = rb_funcall(obj, i_encode, 1, CEncoding_UTF_8);
826
+ #endif
827
+ if (state->ascii_only) {
828
+ convert_UTF8_to_JSON_ASCII(buffer, obj);
829
+ } else {
830
+ convert_UTF8_to_JSON(buffer, obj);
831
+ }
832
+ fbuffer_append_char(buffer, '"');
833
+ break;
834
+ case T_NIL:
835
+ fbuffer_append(buffer, "null", 4);
836
+ break;
837
+ case T_FALSE:
838
+ fbuffer_append(buffer, "false", 5);
839
+ break;
840
+ case T_TRUE:
841
+ fbuffer_append(buffer, "true", 4);
842
+ break;
843
+ case T_FIXNUM:
844
+ fbuffer_append_integer(buffer, FIX2INT(obj));
845
+ break;
846
+ case T_BIGNUM:
847
+ tmp = rb_funcall(obj, i_to_s, 0);
848
+ fbuffer_append(buffer, RSTRING_PAIR(tmp));
849
+ break;
850
+ case T_FLOAT:
851
+ {
852
+ double value = RFLOAT_VALUE(obj);
853
+ char allow_nan = state->allow_nan;
854
+ tmp = rb_funcall(obj, i_to_s, 0);
855
+ if (!allow_nan) {
856
+ if (isinf(value)) {
857
+ fbuffer_free(buffer);
858
+ rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
859
+ } else if (isnan(value)) {
860
+ fbuffer_free(buffer);
861
+ rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
862
+ }
863
+ }
864
+ fbuffer_append(buffer, RSTRING_PAIR(tmp));
865
+ }
866
+ break;
867
+ default:
868
+ if (rb_respond_to(obj, i_to_json)) {
869
+ tmp = rb_funcall(obj, i_to_json, 2, Vstate, INT2FIX(depth + 1));
870
+ Check_Type(tmp, T_STRING);
871
+ fbuffer_append(buffer, RSTRING_PAIR(tmp));
872
+ } else {
873
+ tmp = rb_funcall(obj, i_to_s, 0);
874
+ Check_Type(tmp, T_STRING);
875
+ generate_json(buffer, Vstate, state, tmp, depth + 1);
876
+ }
877
+ break;
878
+ }
879
+ }
880
+
881
+ /*
882
+ * call-seq: partial_generate(obj)
883
+ *
884
+ * Generates a part of a JSON document from object +obj+ and returns the
885
+ * result.
886
+ */
887
+ static VALUE cState_partial_generate(VALUE self, VALUE obj, VALUE depth)
888
+ {
889
+ VALUE result;
890
+ FBuffer *buffer = fbuffer_alloc();
891
+ GET_STATE(self);
892
+
893
+ if (state->object_delim) {
894
+ fbuffer_clear(state->object_delim);
895
+ } else {
896
+ state->object_delim = fbuffer_alloc_with_length(16);
897
+ }
898
+ fbuffer_append_char(state->object_delim, ',');
899
+ if (state->object_delim2) {
900
+ fbuffer_clear(state->object_delim2);
901
+ } else {
902
+ state->object_delim2 = fbuffer_alloc_with_length(16);
903
+ }
904
+ fbuffer_append_char(state->object_delim2, ':');
905
+ if (state->space) fbuffer_append(state->object_delim2, state->space, state->space_len);
906
+
907
+ if (state->array_delim) {
908
+ fbuffer_clear(state->array_delim);
909
+ } else {
910
+ state->array_delim = fbuffer_alloc_with_length(16);
911
+ }
912
+ fbuffer_append_char(state->array_delim, ',');
913
+ if (state->array_nl) fbuffer_append(state->array_delim, state->array_nl, state->array_nl_len);
914
+
915
+ generate_json(buffer, self, state, obj, NIL_P(depth) ? 0 : FIX2INT(depth));
916
+ result = rb_str_new(FBUFFER_PAIR(buffer));
917
+ fbuffer_free_only_buffer(buffer);
918
+ FORCE_UTF8(result);
919
+ return result;
920
+ }
921
+
922
+ /*
923
+ * call-seq: generate(obj)
924
+ *
925
+ * Generates a valid JSON document from object +obj+ and returns the
926
+ * result. If no valid JSON document can be created this method raises a
927
+ * GeneratorError exception.
928
+ */
929
+ static VALUE cState_generate(VALUE self, VALUE obj)
930
+ {
931
+ VALUE result = cState_partial_generate(self, obj, Qnil);
932
+ VALUE re, args[2];
933
+ args[0] = rb_str_new2("\\A\\s*(?:\\[.*\\]|\\{.*\\})\\s*\\Z");
934
+ args[1] = CRegexp_MULTILINE;
935
+ re = rb_class_new_instance(2, args, rb_cRegexp);
936
+ if (NIL_P(rb_funcall(re, i_match, 1, result))) {
937
+ rb_raise(eGeneratorError, "only generation of JSON objects or arrays allowed");
938
+ }
939
+ return result;
940
+ }
941
+
942
+ /*
943
+ * call-seq: new(opts = {})
944
+ *
945
+ * Instantiates a new State object, configured by _opts_.
946
+ *
947
+ * _opts_ can have the following keys:
948
+ *
949
+ * * *indent*: a string used to indent levels (default: ''),
950
+ * * *space*: a string that is put after, a : or , delimiter (default: ''),
951
+ * * *space_before*: a string that is put before a : pair delimiter (default: ''),
952
+ * * *object_nl*: a string that is put at the end of a JSON object (default: ''),
953
+ * * *array_nl*: a string that is put at the end of a JSON array (default: ''),
954
+ * * *allow_nan*: true if NaN, Infinity, and -Infinity should be
955
+ * generated, otherwise an exception is thrown, if these values are
956
+ * encountered. This options defaults to false.
957
+ */
958
+ static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
959
+ {
960
+ VALUE opts;
961
+ GET_STATE(self);
962
+ MEMZERO(state, JSON_Generator_State, 1);
963
+ state->max_nesting = 19;
964
+ rb_scan_args(argc, argv, "01", &opts);
965
+ if (!NIL_P(opts)) cState_configure(self, opts);
966
+ return self;
967
+ }
968
+
969
+ /*
970
+ * call-seq: initialize_copy(orig)
971
+ *
972
+ * Initializes this object from orig if it to be duplicated/cloned and returns
973
+ * it.
974
+ */
975
+ static VALUE cState_init_copy(VALUE obj, VALUE orig)
976
+ {
977
+ JSON_Generator_State *objState, *origState;
978
+
979
+ Data_Get_Struct(obj, JSON_Generator_State, objState);
980
+ Data_Get_Struct(orig, JSON_Generator_State, origState);
981
+ if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State");
982
+
983
+ MEMCPY(objState, origState, JSON_Generator_State, 1);
984
+ objState->indent = fstrndup(origState->indent, origState->indent_len);
985
+ objState->space = fstrndup(origState->space, origState->space_len);
986
+ objState->space_before = fstrndup(origState->space_before, origState->space_before_len);
987
+ objState->object_nl = fstrndup(origState->object_nl, origState->object_nl_len);
988
+ objState->array_nl = fstrndup(origState->array_nl, origState->array_nl_len);
989
+ if (origState->array_delim) objState->array_delim = fbuffer_dup(origState->array_delim);
990
+ if (origState->object_delim) objState->object_delim = fbuffer_dup(origState->object_delim);
991
+ if (origState->object_delim2) objState->object_delim2 = fbuffer_dup(origState->object_delim2);
992
+ return obj;
993
+ }
994
+
995
+ /*
996
+ * call-seq: from_state(opts)
997
+ *
998
+ * Creates a State object from _opts_, which ought to be Hash to create a
999
+ * new State instance configured by _opts_, something else to create an
1000
+ * unconfigured instance. If _opts_ is a State object, it is just returned.
1001
+ */
1002
+ static VALUE cState_from_state_s(VALUE self, VALUE opts)
1003
+ {
1004
+ if (rb_obj_is_kind_of(opts, self)) {
1005
+ return opts;
1006
+ } else if (rb_obj_is_kind_of(opts, rb_cHash)) {
1007
+ return rb_funcall(self, i_new, 1, opts);
1008
+ } else {
1009
+ if (NIL_P(CJSON_SAFE_STATE_PROTOTYPE)) {
1010
+ CJSON_SAFE_STATE_PROTOTYPE = rb_const_get(mJSON, rb_intern("SAFE_STATE_PROTOTYPE"));
1011
+ }
1012
+ return CJSON_SAFE_STATE_PROTOTYPE;
1013
+ }
1014
+ }
1015
+
1016
+ /*
1017
+ * call-seq: indent()
1018
+ *
1019
+ * This string is used to indent levels in the JSON text.
1020
+ */
1021
+ static VALUE cState_indent(VALUE self)
1022
+ {
1023
+ GET_STATE(self);
1024
+ return state->indent ? rb_str_new2(state->indent) : rb_str_new2("");
1025
+ }
1026
+
1027
+ /*
1028
+ * call-seq: indent=(indent)
1029
+ *
1030
+ * This string is used to indent levels in the JSON text.
1031
+ */
1032
+ static VALUE cState_indent_set(VALUE self, VALUE indent)
1033
+ {
1034
+ GET_STATE(self);
1035
+ Check_Type(indent, T_STRING);
1036
+ if (RSTRING_LEN(indent) == 0) {
1037
+ if (state->indent) {
1038
+ ruby_xfree(state->indent);
1039
+ state->indent = NULL;
1040
+ }
1041
+ } else {
1042
+ if (state->indent) ruby_xfree(state->indent);
1043
+ state->indent = strdup(RSTRING_PTR(indent));
1044
+ }
1045
+ return Qnil;
1046
+ }
1047
+
1048
+ /*
1049
+ * call-seq: space()
1050
+ *
1051
+ * This string is used to insert a space between the tokens in a JSON
1052
+ * string.
1053
+ */
1054
+ static VALUE cState_space(VALUE self)
1055
+ {
1056
+ GET_STATE(self);
1057
+ return state->space ? rb_str_new2(state->space) : rb_str_new2("");
1058
+ }
1059
+
1060
+ /*
1061
+ * call-seq: space=(space)
1062
+ *
1063
+ * This string is used to insert a space between the tokens in a JSON
1064
+ * string.
1065
+ */
1066
+ static VALUE cState_space_set(VALUE self, VALUE space)
1067
+ {
1068
+ GET_STATE(self);
1069
+ Check_Type(space, T_STRING);
1070
+ if (RSTRING_LEN(space) == 0) {
1071
+ if (state->space) {
1072
+ ruby_xfree(state->space);
1073
+ state->space = NULL;
1074
+ }
1075
+ } else {
1076
+ if (state->space) ruby_xfree(state->space);
1077
+ state->space = strdup(RSTRING_PTR(space));
1078
+ }
1079
+ return Qnil;
1080
+ }
1081
+
1082
+ /*
1083
+ * call-seq: space_before()
1084
+ *
1085
+ * This string is used to insert a space before the ':' in JSON objects.
1086
+ */
1087
+ static VALUE cState_space_before(VALUE self)
1088
+ {
1089
+ GET_STATE(self);
1090
+ return state->space_before ? rb_str_new2(state->space_before) : rb_str_new2("");
1091
+ }
1092
+
1093
+ /*
1094
+ * call-seq: space_before=(space_before)
1095
+ *
1096
+ * This string is used to insert a space before the ':' in JSON objects.
1097
+ */
1098
+ static VALUE cState_space_before_set(VALUE self, VALUE space_before)
1099
+ {
1100
+ GET_STATE(self);
1101
+ Check_Type(space_before, T_STRING);
1102
+ if (RSTRING_LEN(space_before) == 0) {
1103
+ if (state->space_before) {
1104
+ ruby_xfree(state->space_before);
1105
+ state->space_before = NULL;
1106
+ }
1107
+ } else {
1108
+ if (state->space_before) ruby_xfree(state->space_before);
1109
+ state->space_before = strdup(RSTRING_PTR(space_before));
1110
+ }
1111
+ return Qnil;
1112
+ }
1113
+
1114
+ /*
1115
+ * call-seq: object_nl()
1116
+ *
1117
+ * This string is put at the end of a line that holds a JSON object (or
1118
+ * Hash).
1119
+ */
1120
+ static VALUE cState_object_nl(VALUE self)
1121
+ {
1122
+ GET_STATE(self);
1123
+ return state->object_nl ? rb_str_new2(state->object_nl) : rb_str_new2("");
1124
+ }
1125
+
1126
+ /*
1127
+ * call-seq: object_nl=(object_nl)
1128
+ *
1129
+ * This string is put at the end of a line that holds a JSON object (or
1130
+ * Hash).
1131
+ */
1132
+ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
1133
+ {
1134
+ GET_STATE(self);
1135
+ Check_Type(object_nl, T_STRING);
1136
+ if (RSTRING_LEN(object_nl) == 0) {
1137
+ if (state->object_nl) {
1138
+ ruby_xfree(state->object_nl);
1139
+ state->object_nl = NULL;
1140
+ }
1141
+ } else {
1142
+ if (state->object_nl) ruby_xfree(state->object_nl);
1143
+ state->object_nl = strdup(RSTRING_PTR(object_nl));
1144
+ }
1145
+ return Qnil;
1146
+ }
1147
+
1148
+ /*
1149
+ * call-seq: array_nl()
1150
+ *
1151
+ * This string is put at the end of a line that holds a JSON array.
1152
+ */
1153
+ static VALUE cState_array_nl(VALUE self)
1154
+ {
1155
+ GET_STATE(self);
1156
+ return state->array_nl ? rb_str_new2(state->array_nl) : rb_str_new2("");
1157
+ }
1158
+
1159
+ /*
1160
+ * call-seq: array_nl=(array_nl)
1161
+ *
1162
+ * This string is put at the end of a line that holds a JSON array.
1163
+ */
1164
+ static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
1165
+ {
1166
+ GET_STATE(self);
1167
+ Check_Type(array_nl, T_STRING);
1168
+ if (RSTRING_LEN(array_nl) == 0) {
1169
+ if (state->array_nl) {
1170
+ ruby_xfree(state->array_nl);
1171
+ state->array_nl = NULL;
1172
+ }
1173
+ } else {
1174
+ if (state->array_nl) ruby_xfree(state->array_nl);
1175
+ state->array_nl = strdup(RSTRING_PTR(array_nl));
1176
+ }
1177
+ return Qnil;
1178
+ }
1179
+
1180
+
1181
+ /*
1182
+ * call-seq: check_circular?
1183
+ *
1184
+ * Returns true, if circular data structures should be checked,
1185
+ * otherwise returns false.
1186
+ */
1187
+ static VALUE cState_check_circular_p(VALUE self)
1188
+ {
1189
+ GET_STATE(self);
1190
+ return state->max_nesting ? Qtrue : Qfalse;
1191
+ }
1192
+
1193
+ /*
1194
+ * call-seq: max_nesting
1195
+ *
1196
+ * This integer returns the maximum level of data structure nesting in
1197
+ * the generated JSON, max_nesting = 0 if no maximum is checked.
1198
+ */
1199
+ static VALUE cState_max_nesting(VALUE self)
1200
+ {
1201
+ GET_STATE(self);
1202
+ return LONG2FIX(state->max_nesting);
1203
+ }
1204
+
1205
+ /*
1206
+ * call-seq: max_nesting=(depth)
1207
+ *
1208
+ * This sets the maximum level of data structure nesting in the generated JSON
1209
+ * to the integer depth, max_nesting = 0 if no maximum should be checked.
1210
+ */
1211
+ static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
1212
+ {
1213
+ GET_STATE(self);
1214
+ Check_Type(depth, T_FIXNUM);
1215
+ return state->max_nesting = FIX2LONG(depth);
1216
+ }
1217
+
1218
+ /*
1219
+ * call-seq: allow_nan?
1220
+ *
1221
+ * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
1222
+ * returns false.
1223
+ */
1224
+ static VALUE cState_allow_nan_p(VALUE self)
1225
+ {
1226
+ GET_STATE(self);
1227
+ return state->allow_nan ? Qtrue : Qfalse;
1228
+ }
1229
+
1230
+ /*
1231
+ * call-seq: ascii_only?
1232
+ *
1233
+ * Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
1234
+ * returns false.
1235
+ */
1236
+ static VALUE cState_ascii_only_p(VALUE self)
1237
+ {
1238
+ GET_STATE(self);
1239
+ return state->ascii_only ? Qtrue : Qfalse;
1240
+ }
1241
+
1242
+ /*
1243
+ *
1244
+ */
1245
+ void Init_generator()
1246
+ {
1247
+ rb_require("json/common");
1248
+
1249
+ mJSON = rb_define_module("JSON");
1250
+ mExt = rb_define_module_under(mJSON, "Ext");
1251
+ mGenerator = rb_define_module_under(mExt, "Generator");
1252
+
1253
+ eGeneratorError = rb_path2class("JSON::GeneratorError");
1254
+ eNestingError = rb_path2class("JSON::NestingError");
1255
+
1256
+ cState = rb_define_class_under(mGenerator, "State", rb_cObject);
1257
+ rb_define_alloc_func(cState, cState_s_allocate);
1258
+ rb_define_singleton_method(cState, "from_state", cState_from_state_s, 1);
1259
+ rb_define_method(cState, "initialize", cState_initialize, -1);
1260
+ rb_define_method(cState, "initialize_copy", cState_init_copy, 1);
1261
+ rb_define_method(cState, "indent", cState_indent, 0);
1262
+ rb_define_method(cState, "indent=", cState_indent_set, 1);
1263
+ rb_define_method(cState, "space", cState_space, 0);
1264
+ rb_define_method(cState, "space=", cState_space_set, 1);
1265
+ rb_define_method(cState, "space_before", cState_space_before, 0);
1266
+ rb_define_method(cState, "space_before=", cState_space_before_set, 1);
1267
+ rb_define_method(cState, "object_nl", cState_object_nl, 0);
1268
+ rb_define_method(cState, "object_nl=", cState_object_nl_set, 1);
1269
+ rb_define_method(cState, "array_nl", cState_array_nl, 0);
1270
+ rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
1271
+ rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
1272
+ rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
1273
+ rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
1274
+ rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
1275
+ rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
1276
+ rb_define_method(cState, "configure", cState_configure, 1);
1277
+ rb_define_method(cState, "to_h", cState_to_h, 0);
1278
+ rb_define_method(cState, "[]", cState_aref, 1);
1279
+ rb_define_method(cState, "generate", cState_generate, 1);
1280
+ rb_define_method(cState, "partial_generate", cState_partial_generate, 1);
1281
+
1282
+ mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
1283
+ mObject = rb_define_module_under(mGeneratorMethods, "Object");
1284
+ rb_define_method(mObject, "to_json", mObject_to_json, -1);
1285
+ mHash = rb_define_module_under(mGeneratorMethods, "Hash");
1286
+ rb_define_method(mHash, "to_json", mHash_to_json, -1);
1287
+ mArray = rb_define_module_under(mGeneratorMethods, "Array");
1288
+ rb_define_method(mArray, "to_json", mArray_to_json, -1);
1289
+ mInteger = rb_define_module_under(mGeneratorMethods, "Integer");
1290
+ rb_define_method(mInteger, "to_json", mInteger_to_json, -1);
1291
+ mFloat = rb_define_module_under(mGeneratorMethods, "Float");
1292
+ rb_define_method(mFloat, "to_json", mFloat_to_json, -1);
1293
+ mString = rb_define_module_under(mGeneratorMethods, "String");
1294
+ rb_define_singleton_method(mString, "included", mString_included_s, 1);
1295
+ rb_define_method(mString, "to_json", mString_to_json, -1);
1296
+ rb_define_method(mString, "to_json_raw", mString_to_json_raw, -1);
1297
+ rb_define_method(mString, "to_json_raw_object", mString_to_json_raw_object, 0);
1298
+ mString_Extend = rb_define_module_under(mString, "Extend");
1299
+ rb_define_method(mString_Extend, "json_create", mString_Extend_json_create, 1);
1300
+ mTrueClass = rb_define_module_under(mGeneratorMethods, "TrueClass");
1301
+ rb_define_method(mTrueClass, "to_json", mTrueClass_to_json, -1);
1302
+ mFalseClass = rb_define_module_under(mGeneratorMethods, "FalseClass");
1303
+ rb_define_method(mFalseClass, "to_json", mFalseClass_to_json, -1);
1304
+ mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
1305
+ rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
1306
+
1307
+ CRegexp_MULTILINE = rb_const_get(rb_cRegexp, rb_intern("MULTILINE"));
1308
+ i_to_s = rb_intern("to_s");
1309
+ i_to_json = rb_intern("to_json");
1310
+ i_new = rb_intern("new");
1311
+ i_indent = rb_intern("indent");
1312
+ i_space = rb_intern("space");
1313
+ i_space_before = rb_intern("space_before");
1314
+ i_object_nl = rb_intern("object_nl");
1315
+ i_array_nl = rb_intern("array_nl");
1316
+ i_max_nesting = rb_intern("max_nesting");
1317
+ i_allow_nan = rb_intern("allow_nan");
1318
+ i_ascii_only = rb_intern("ascii_only");
1319
+ i_pack = rb_intern("pack");
1320
+ i_unpack = rb_intern("unpack");
1321
+ i_create_id = rb_intern("create_id");
1322
+ i_extend = rb_intern("extend");
1323
+ i_key_p = rb_intern("key?");
1324
+ i_aref = rb_intern("[]");
1325
+ i_send = rb_intern("__send__");
1326
+ i_respond_to_p = rb_intern("respond_to?");
1327
+ i_match = rb_intern("match");
1328
+ #ifdef HAVE_RUBY_ENCODING_H
1329
+ CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
1330
+ i_encoding = rb_intern("encoding");
1331
+ i_encode = rb_intern("encode");
1332
+ #endif
1333
+ CJSON_SAFE_STATE_PROTOTYPE = Qnil;
1334
+ }