mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* lib/json.rb, lib/json/*: moved to ext/json/lib.
-- M trunk/ChangeLog D trunk/lib/json D trunk/lib/json.rb A trunk/ext/json/lib A trunk/ext/json/lib/json A trunk/ext/json/lib/json.rb A trunk/ext/json/extconf.rb git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@14100 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									86f1cff0eb
								
							
						
					
					
						commit
						825ce503c0
					
				
					 21 changed files with 7 additions and 0 deletions
				
			
		
							
								
								
									
										235
									
								
								ext/json/lib/json.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								ext/json/lib/json.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,235 @@
 | 
			
		|||
require 'json/common'
 | 
			
		||||
# = json - JSON for Ruby
 | 
			
		||||
#
 | 
			
		||||
# == Description
 | 
			
		||||
#
 | 
			
		||||
# This is a implementation of the JSON specification according to RFC 4627
 | 
			
		||||
# (http://www.ietf.org/rfc/rfc4627.txt). Starting from version 1.0.0 on there
 | 
			
		||||
# will be two variants available:
 | 
			
		||||
#
 | 
			
		||||
# * A pure ruby variant, that relies on the iconv and the stringscan
 | 
			
		||||
#   extensions, which are both part of the ruby standard library.
 | 
			
		||||
# * The quite a bit faster C extension variant, which is in parts implemented
 | 
			
		||||
#   in C and comes with its own unicode conversion functions and a parser
 | 
			
		||||
#   generated by the ragel state machine compiler
 | 
			
		||||
#   (http://www.cs.queensu.ca/~thurston/ragel).
 | 
			
		||||
#
 | 
			
		||||
# Both variants of the JSON generator escape all non-ASCII an control
 | 
			
		||||
# characters with \uXXXX escape sequences, and support UTF-16 surrogate pairs
 | 
			
		||||
# in order to be able to generate the whole range of unicode code points. This
 | 
			
		||||
# means that generated JSON text is encoded as UTF-8 (because ASCII is a subset
 | 
			
		||||
# of UTF-8) and at the same time avoids decoding problems for receiving
 | 
			
		||||
# endpoints, that don't expect UTF-8 encoded texts. On the negative side this
 | 
			
		||||
# may lead to a bit longer strings than necessarry.
 | 
			
		||||
#
 | 
			
		||||
# All strings, that are to be encoded as JSON strings, should be UTF-8 byte
 | 
			
		||||
# sequences on the Ruby side. To encode raw binary strings, that aren't UTF-8
 | 
			
		||||
# encoded, please use the to_json_raw_object method of String (which produces
 | 
			
		||||
# an object, that contains a byte array) and decode the result on the receiving
 | 
			
		||||
# endpoint.
 | 
			
		||||
#
 | 
			
		||||
# == Author
 | 
			
		||||
#
 | 
			
		||||
# Florian Frank <mailto:flori@ping.de>
 | 
			
		||||
#
 | 
			
		||||
# == License
 | 
			
		||||
#
 | 
			
		||||
# This software is distributed under the same license as Ruby itself, see
 | 
			
		||||
# http://www.ruby-lang.org/en/LICENSE.txt.
 | 
			
		||||
#
 | 
			
		||||
# == Download
 | 
			
		||||
#
 | 
			
		||||
# The latest version of this library can be downloaded at
 | 
			
		||||
#
 | 
			
		||||
# * http://rubyforge.org/frs?group_id=953
 | 
			
		||||
#
 | 
			
		||||
# Online Documentation should be located at
 | 
			
		||||
#
 | 
			
		||||
# * http://json.rubyforge.org
 | 
			
		||||
#
 | 
			
		||||
# == Usage
 | 
			
		||||
# 
 | 
			
		||||
# To use JSON you can
 | 
			
		||||
#   require 'json'
 | 
			
		||||
# to load the installed variant (either the extension 'json' or the pure
 | 
			
		||||
# variant 'json_pure'). If you have installed the extension variant, you can
 | 
			
		||||
# pick either the extension variant or the pure variant by typing
 | 
			
		||||
#   require 'json/ext'
 | 
			
		||||
# or
 | 
			
		||||
#   require 'json/pure'
 | 
			
		||||
#
 | 
			
		||||
# You can choose to load a set of common additions to ruby core's objects if
 | 
			
		||||
# you
 | 
			
		||||
#   require 'json/add/core'
 | 
			
		||||
#
 | 
			
		||||
# After requiring this you can, e. g., serialise/deserialise Ruby ranges:
 | 
			
		||||
#
 | 
			
		||||
#   JSON JSON(1..10) # => 1..10
 | 
			
		||||
#
 | 
			
		||||
# To find out how to add JSON support to other or your own classes, read the
 | 
			
		||||
# Examples section below.
 | 
			
		||||
#
 | 
			
		||||
# To get the best compatibility to rails' JSON implementation, you can
 | 
			
		||||
#   require 'json/add/rails'
 | 
			
		||||
#
 | 
			
		||||
# Both of the additions attempt to require 'json' (like above) first, if it has
 | 
			
		||||
# not been required yet.
 | 
			
		||||
#
 | 
			
		||||
# == Speed Comparisons
 | 
			
		||||
#
 | 
			
		||||
# I have created some benchmark results (see the benchmarks subdir of the
 | 
			
		||||
# package) for the JSON-Parser to estimate the speed up in the C extension:
 | 
			
		||||
#
 | 
			
		||||
# JSON::Pure::Parser::  28.90  calls/second
 | 
			
		||||
# JSON::Ext::Parser::  505.50 calls/second
 | 
			
		||||
#
 | 
			
		||||
# This is ca. <b>17.5</b> times the speed of the pure Ruby implementation.
 | 
			
		||||
#
 | 
			
		||||
# I have benchmarked the JSON-Generator as well. This generates a few more
 | 
			
		||||
# values, because there are different modes, that also influence the achieved
 | 
			
		||||
# speed:
 | 
			
		||||
#
 | 
			
		||||
# * JSON::Pure::Generator:
 | 
			
		||||
#   generate::        35.06 calls/second
 | 
			
		||||
#   pretty_generate:: 34.00 calls/second
 | 
			
		||||
#   fast_generate::   41.06 calls/second
 | 
			
		||||
#
 | 
			
		||||
# * JSON::Ext::Generator:
 | 
			
		||||
#   generate::        492.11 calls/second
 | 
			
		||||
#   pretty_generate:: 348.85 calls/second
 | 
			
		||||
#   fast_generate::   541.60 calls/second
 | 
			
		||||
#
 | 
			
		||||
# * Speedup Ext/Pure:
 | 
			
		||||
#   generate safe::   14.0 times
 | 
			
		||||
#   generate pretty:: 10.3 times
 | 
			
		||||
#   generate fast::   13.2 times
 | 
			
		||||
#
 | 
			
		||||
# The rails framework includes a generator as well, also it seems to be rather
 | 
			
		||||
# slow: I measured only 23.87 calls/second which is slower than any of my pure
 | 
			
		||||
# generator results. Here a comparison of the different speedups with the Rails
 | 
			
		||||
# measurement as the divisor:
 | 
			
		||||
#
 | 
			
		||||
# * Speedup Pure/Rails:
 | 
			
		||||
#   generate safe::   1.5 times
 | 
			
		||||
#   generate pretty:: 1.4 times
 | 
			
		||||
#   generate fast::   1.7 times
 | 
			
		||||
#
 | 
			
		||||
# * Speedup Ext/Rails:
 | 
			
		||||
#   generate safe::   20.6 times
 | 
			
		||||
#   generate pretty:: 14.6 times
 | 
			
		||||
#   generate fast::   22.7 times
 | 
			
		||||
#
 | 
			
		||||
# To achieve the fastest JSON text output, you can use the
 | 
			
		||||
# fast_generate/fast_unparse methods. Beware, that this will disable the
 | 
			
		||||
# checking for circular Ruby data structures, which may cause JSON to go into
 | 
			
		||||
# an infinite loop.
 | 
			
		||||
#
 | 
			
		||||
# == Examples
 | 
			
		||||
#
 | 
			
		||||
# To create a JSON text from a ruby data structure, you
 | 
			
		||||
# can call JSON.generate (or JSON.unparse) like that:
 | 
			
		||||
#
 | 
			
		||||
#  json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
 | 
			
		||||
#  # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
 | 
			
		||||
#
 | 
			
		||||
# To create a valid JSON text you have to make sure, that the output is
 | 
			
		||||
# embedded in either a JSON array [] or a JSON object {}. The easiest way to do
 | 
			
		||||
# this, is by putting your values in a Ruby Array or Hash instance.
 | 
			
		||||
#
 | 
			
		||||
# To get back a ruby data structure from a JSON text, you have to call
 | 
			
		||||
# JSON.parse on it:
 | 
			
		||||
#
 | 
			
		||||
#  JSON.parse json
 | 
			
		||||
#  # => [1, 2, {"a"=>3.141}, false, true, nil, "4..10"]
 | 
			
		||||
# 
 | 
			
		||||
# Note, that the range from the original data structure is a simple
 | 
			
		||||
# string now. The reason for this is, that JSON doesn't support ranges
 | 
			
		||||
# or arbitrary classes. In this case the json library falls back to call
 | 
			
		||||
# Object#to_json, which is the same as #to_s.to_json.
 | 
			
		||||
#
 | 
			
		||||
# It's possible to add JSON support serialization to arbitrary classes by
 | 
			
		||||
# simply implementing a more specialized version of the #to_json method, that
 | 
			
		||||
# should return a JSON object (a hash converted to JSON with #to_json) like
 | 
			
		||||
# this (don't forget the *a for all the arguments):
 | 
			
		||||
#
 | 
			
		||||
#  class Range
 | 
			
		||||
#    def to_json(*a)
 | 
			
		||||
#      {
 | 
			
		||||
#        'json_class'   => self.class.name, # = 'Range'
 | 
			
		||||
#        'data'         => [ first, last, exclude_end? ]
 | 
			
		||||
#      }.to_json(*a)
 | 
			
		||||
#    end
 | 
			
		||||
#  end
 | 
			
		||||
#
 | 
			
		||||
# The hash key 'json_class' is the class, that will be asked to deserialise the
 | 
			
		||||
# JSON representation later. In this case it's 'Range', but any namespace of
 | 
			
		||||
# the form 'A::B' or '::A::B' will do. All other keys are arbitrary and can be
 | 
			
		||||
# used to store the necessary data to configure the object to be deserialised.
 | 
			
		||||
#
 | 
			
		||||
# If a the key 'json_class' is found in a JSON object, the JSON parser checks
 | 
			
		||||
# if the given class responds to the json_create class method. If so, it is
 | 
			
		||||
# called with the JSON object converted to a Ruby hash. So a range can
 | 
			
		||||
# be deserialised by implementing Range.json_create like this:
 | 
			
		||||
# 
 | 
			
		||||
#  class Range
 | 
			
		||||
#    def self.json_create(o)
 | 
			
		||||
#      new(*o['data'])
 | 
			
		||||
#    end
 | 
			
		||||
#  end
 | 
			
		||||
#
 | 
			
		||||
# Now it possible to serialise/deserialise ranges as well:
 | 
			
		||||
#
 | 
			
		||||
#  json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
 | 
			
		||||
#  # => "[1,2,{\"a\":3.141},false,true,null,{\"json_class\":\"Range\",\"data\":[4,10,false]}]"
 | 
			
		||||
#  JSON.parse json
 | 
			
		||||
#  # => [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
 | 
			
		||||
#
 | 
			
		||||
# JSON.generate always creates the shortest possible string representation of a
 | 
			
		||||
# ruby data structure in one line. This good for data storage or network
 | 
			
		||||
# protocols, but not so good for humans to read. Fortunately there's also
 | 
			
		||||
# JSON.pretty_generate (or JSON.pretty_generate) that creates a more
 | 
			
		||||
# readable output:
 | 
			
		||||
#
 | 
			
		||||
#  puts JSON.pretty_generate([1, 2, {"a"=>3.141}, false, true, nil, 4..10])
 | 
			
		||||
#  [
 | 
			
		||||
#    1,
 | 
			
		||||
#    2,
 | 
			
		||||
#    {
 | 
			
		||||
#      "a": 3.141
 | 
			
		||||
#    },
 | 
			
		||||
#    false,
 | 
			
		||||
#    true,
 | 
			
		||||
#    null,
 | 
			
		||||
#    {
 | 
			
		||||
#      "json_class": "Range",
 | 
			
		||||
#      "data": [
 | 
			
		||||
#        4,
 | 
			
		||||
#        10,
 | 
			
		||||
#        false
 | 
			
		||||
#      ]
 | 
			
		||||
#    }
 | 
			
		||||
#  ]
 | 
			
		||||
#
 | 
			
		||||
# There are also the methods Kernel#j for unparse, and Kernel#jj for
 | 
			
		||||
# pretty_unparse output to the console, that work analogous to Core Ruby's p
 | 
			
		||||
# and the pp library's pp methods.
 | 
			
		||||
#
 | 
			
		||||
# The script tools/server.rb contains a small example if you want to test, how
 | 
			
		||||
# receiving a JSON object from a webrick server in your browser with the
 | 
			
		||||
# javasript prototype library (http://www.prototypejs.org) works.
 | 
			
		||||
#
 | 
			
		||||
module JSON
 | 
			
		||||
  require 'json/version'
 | 
			
		||||
 | 
			
		||||
  if VARIANT_BINARY
 | 
			
		||||
    require 'json/ext'
 | 
			
		||||
  else
 | 
			
		||||
    begin
 | 
			
		||||
      require 'json/ext'
 | 
			
		||||
    rescue LoadError
 | 
			
		||||
      require 'json/pure'
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  JSON_LOADED = true
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										21
									
								
								ext/json/lib/json/Array.xpm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								ext/json/lib/json/Array.xpm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
/* XPM */
 | 
			
		||||
static char * Array_xpm[] = {
 | 
			
		||||
"16 16 2 1",
 | 
			
		||||
" 	c None",
 | 
			
		||||
".	c #000000",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"   ..........   ",
 | 
			
		||||
"   .        .   ",
 | 
			
		||||
"   .        .   ",
 | 
			
		||||
"   .        .   ",
 | 
			
		||||
"   .        .   ",
 | 
			
		||||
"   .        .   ",
 | 
			
		||||
"   .        .   ",
 | 
			
		||||
"   .        .   ",
 | 
			
		||||
"   .        .   ",
 | 
			
		||||
"   ..........   ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                "};
 | 
			
		||||
							
								
								
									
										21
									
								
								ext/json/lib/json/FalseClass.xpm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								ext/json/lib/json/FalseClass.xpm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
/* XPM */
 | 
			
		||||
static char * False_xpm[] = {
 | 
			
		||||
"16 16 2 1",
 | 
			
		||||
" 	c None",
 | 
			
		||||
".	c #FF0000",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"     ......     ",
 | 
			
		||||
"     .          ",
 | 
			
		||||
"     .          ",
 | 
			
		||||
"     .          ",
 | 
			
		||||
"     ......     ",
 | 
			
		||||
"     .          ",
 | 
			
		||||
"     .          ",
 | 
			
		||||
"     .          ",
 | 
			
		||||
"     .          ",
 | 
			
		||||
"     .          ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                "};
 | 
			
		||||
							
								
								
									
										21
									
								
								ext/json/lib/json/Hash.xpm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								ext/json/lib/json/Hash.xpm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
/* XPM */
 | 
			
		||||
static char * Hash_xpm[] = {
 | 
			
		||||
"16 16 2 1",
 | 
			
		||||
" 	c None",
 | 
			
		||||
".	c #000000",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"       .  .     ",
 | 
			
		||||
"       .  .     ",
 | 
			
		||||
"       .  .     ",
 | 
			
		||||
"    .........   ",
 | 
			
		||||
"      .  .      ",
 | 
			
		||||
"      .  .      ",
 | 
			
		||||
"   .........    ",
 | 
			
		||||
"     .  .       ",
 | 
			
		||||
"     .  .       ",
 | 
			
		||||
"     .  .       ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                "};
 | 
			
		||||
							
								
								
									
										73
									
								
								ext/json/lib/json/Key.xpm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								ext/json/lib/json/Key.xpm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,73 @@
 | 
			
		|||
/* XPM */
 | 
			
		||||
static char * Key_xpm[] = {
 | 
			
		||||
"16 16 54 1",
 | 
			
		||||
" 	c None",
 | 
			
		||||
".	c #110007",
 | 
			
		||||
"+	c #0E0900",
 | 
			
		||||
"@	c #000013",
 | 
			
		||||
"#	c #070600",
 | 
			
		||||
"$	c #F6F006",
 | 
			
		||||
"%	c #ECE711",
 | 
			
		||||
"&	c #E5EE00",
 | 
			
		||||
"*	c #16021E",
 | 
			
		||||
"=	c #120900",
 | 
			
		||||
"-	c #EDF12B",
 | 
			
		||||
";	c #000033",
 | 
			
		||||
">	c #0F0000",
 | 
			
		||||
",	c #FFFE03",
 | 
			
		||||
"'	c #E6E500",
 | 
			
		||||
")	c #16021B",
 | 
			
		||||
"!	c #F7F502",
 | 
			
		||||
"~	c #000E00",
 | 
			
		||||
"{	c #130000",
 | 
			
		||||
"]	c #FFF000",
 | 
			
		||||
"^	c #FFE711",
 | 
			
		||||
"/	c #140005",
 | 
			
		||||
"(	c #190025",
 | 
			
		||||
"_	c #E9DD27",
 | 
			
		||||
":	c #E7DC04",
 | 
			
		||||
"<	c #FFEC09",
 | 
			
		||||
"[	c #FFE707",
 | 
			
		||||
"}	c #FFDE10",
 | 
			
		||||
"|	c #150021",
 | 
			
		||||
"1	c #160700",
 | 
			
		||||
"2	c #FAF60E",
 | 
			
		||||
"3	c #EFE301",
 | 
			
		||||
"4	c #FEF300",
 | 
			
		||||
"5	c #E7E000",
 | 
			
		||||
"6	c #FFFF08",
 | 
			
		||||
"7	c #0E0206",
 | 
			
		||||
"8	c #040000",
 | 
			
		||||
"9	c #03052E",
 | 
			
		||||
"0	c #041212",
 | 
			
		||||
"a	c #070300",
 | 
			
		||||
"b	c #F2E713",
 | 
			
		||||
"c	c #F9DE13",
 | 
			
		||||
"d	c #36091E",
 | 
			
		||||
"e	c #00001C",
 | 
			
		||||
"f	c #1F0010",
 | 
			
		||||
"g	c #FFF500",
 | 
			
		||||
"h	c #DEDE00",
 | 
			
		||||
"i	c #050A00",
 | 
			
		||||
"j	c #FAF14A",
 | 
			
		||||
"k	c #F5F200",
 | 
			
		||||
"l	c #040404",
 | 
			
		||||
"m	c #1A0D00",
 | 
			
		||||
"n	c #EDE43D",
 | 
			
		||||
"o	c #ECE007",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"    .+@         ",
 | 
			
		||||
"   #$%&*        ",
 | 
			
		||||
"  =-;>,')       ",
 | 
			
		||||
"  >!~{]^/       ",
 | 
			
		||||
"  (_:<[}|       ",
 | 
			
		||||
"   1234567      ",
 | 
			
		||||
"    890abcd     ",
 | 
			
		||||
"       efghi    ",
 | 
			
		||||
"         >jkl   ",
 | 
			
		||||
"          mnol  ",
 | 
			
		||||
"           >kl  ",
 | 
			
		||||
"            ll  ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                "};
 | 
			
		||||
							
								
								
									
										21
									
								
								ext/json/lib/json/NilClass.xpm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								ext/json/lib/json/NilClass.xpm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
/* XPM */
 | 
			
		||||
static char * False_xpm[] = {
 | 
			
		||||
"16 16 2 1",
 | 
			
		||||
" 	c None",
 | 
			
		||||
".	c #000000",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"       ...      ",
 | 
			
		||||
"      .   .     ",
 | 
			
		||||
"     .     .    ",
 | 
			
		||||
"     .     .    ",
 | 
			
		||||
"     .     .    ",
 | 
			
		||||
"     .     .    ",
 | 
			
		||||
"     .     .    ",
 | 
			
		||||
"     .     .    ",
 | 
			
		||||
"      .   .     ",
 | 
			
		||||
"       ...      ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                "};
 | 
			
		||||
							
								
								
									
										28
									
								
								ext/json/lib/json/Numeric.xpm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								ext/json/lib/json/Numeric.xpm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
/* XPM */
 | 
			
		||||
static char * Numeric_xpm[] = {
 | 
			
		||||
"16 16 9 1",
 | 
			
		||||
" 	c None",
 | 
			
		||||
".	c #FF0000",
 | 
			
		||||
"+	c #0000FF",
 | 
			
		||||
"@	c #0023DB",
 | 
			
		||||
"#	c #00EA14",
 | 
			
		||||
"$	c #00FF00",
 | 
			
		||||
"%	c #004FAF",
 | 
			
		||||
"&	c #0028D6",
 | 
			
		||||
"*	c #00F20C",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
" ... +++@#$$$$  ",
 | 
			
		||||
"   .+   %&   $$ ",
 | 
			
		||||
"   .     +    $ ",
 | 
			
		||||
"   .     +   $$ ",
 | 
			
		||||
"   .    ++$$$$  ",
 | 
			
		||||
"   .    +    $$ ",
 | 
			
		||||
"   .   +      $ ",
 | 
			
		||||
"   .  +       $ ",
 | 
			
		||||
"   . +  $    $$ ",
 | 
			
		||||
" .....++++*$$   ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                "};
 | 
			
		||||
							
								
								
									
										96
									
								
								ext/json/lib/json/String.xpm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								ext/json/lib/json/String.xpm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,96 @@
 | 
			
		|||
/* XPM */
 | 
			
		||||
static char * String_xpm[] = {
 | 
			
		||||
"16 16 77 1",
 | 
			
		||||
" 	c None",
 | 
			
		||||
".	c #000000",
 | 
			
		||||
"+	c #040404",
 | 
			
		||||
"@	c #080806",
 | 
			
		||||
"#	c #090606",
 | 
			
		||||
"$	c #EEEAE1",
 | 
			
		||||
"%	c #E7E3DA",
 | 
			
		||||
"&	c #E0DBD1",
 | 
			
		||||
"*	c #D4B46F",
 | 
			
		||||
"=	c #0C0906",
 | 
			
		||||
"-	c #E3C072",
 | 
			
		||||
";	c #E4C072",
 | 
			
		||||
">	c #060505",
 | 
			
		||||
",	c #0B0A08",
 | 
			
		||||
"'	c #D5B264",
 | 
			
		||||
")	c #D3AF5A",
 | 
			
		||||
"!	c #080602",
 | 
			
		||||
"~	c #E1B863",
 | 
			
		||||
"{	c #DDB151",
 | 
			
		||||
"]	c #DBAE4A",
 | 
			
		||||
"^	c #DDB152",
 | 
			
		||||
"/	c #DDB252",
 | 
			
		||||
"(	c #070705",
 | 
			
		||||
"_	c #0C0A07",
 | 
			
		||||
":	c #D3A33B",
 | 
			
		||||
"<	c #020201",
 | 
			
		||||
"[	c #DAAA41",
 | 
			
		||||
"}	c #040302",
 | 
			
		||||
"|	c #E4D9BF",
 | 
			
		||||
"1	c #0B0907",
 | 
			
		||||
"2	c #030201",
 | 
			
		||||
"3	c #020200",
 | 
			
		||||
"4	c #C99115",
 | 
			
		||||
"5	c #080704",
 | 
			
		||||
"6	c #DBC8A2",
 | 
			
		||||
"7	c #E7D7B4",
 | 
			
		||||
"8	c #E0CD9E",
 | 
			
		||||
"9	c #080601",
 | 
			
		||||
"0	c #040400",
 | 
			
		||||
"a	c #010100",
 | 
			
		||||
"b	c #0B0B08",
 | 
			
		||||
"c	c #DCBF83",
 | 
			
		||||
"d	c #DCBC75",
 | 
			
		||||
"e	c #DEB559",
 | 
			
		||||
"f	c #040301",
 | 
			
		||||
"g	c #BC8815",
 | 
			
		||||
"h	c #120E07",
 | 
			
		||||
"i	c #060402",
 | 
			
		||||
"j	c #0A0804",
 | 
			
		||||
"k	c #D4A747",
 | 
			
		||||
"l	c #D6A12F",
 | 
			
		||||
"m	c #0E0C05",
 | 
			
		||||
"n	c #C8C1B0",
 | 
			
		||||
"o	c #1D1B15",
 | 
			
		||||
"p	c #D7AD51",
 | 
			
		||||
"q	c #070502",
 | 
			
		||||
"r	c #080804",
 | 
			
		||||
"s	c #BC953B",
 | 
			
		||||
"t	c #C4BDAD",
 | 
			
		||||
"u	c #0B0807",
 | 
			
		||||
"v	c #DBAC47",
 | 
			
		||||
"w	c #1B150A",
 | 
			
		||||
"x	c #B78A2C",
 | 
			
		||||
"y	c #D8A83C",
 | 
			
		||||
"z	c #D4A338",
 | 
			
		||||
"A	c #0F0B03",
 | 
			
		||||
"B	c #181105",
 | 
			
		||||
"C	c #C59325",
 | 
			
		||||
"D	c #C18E1F",
 | 
			
		||||
"E	c #060600",
 | 
			
		||||
"F	c #CC992D",
 | 
			
		||||
"G	c #B98B25",
 | 
			
		||||
"H	c #B3831F",
 | 
			
		||||
"I	c #C08C1C",
 | 
			
		||||
"J	c #060500",
 | 
			
		||||
"K	c #0E0C03",
 | 
			
		||||
"L	c #0D0A00",
 | 
			
		||||
"                ",
 | 
			
		||||
"   .+@#         ",
 | 
			
		||||
"  .$%&*=        ",
 | 
			
		||||
" .-;>,')!       ",
 | 
			
		||||
" .~.  .{].      ",
 | 
			
		||||
" .^/. (_:<      ",
 | 
			
		||||
"  .[.}|$12      ",
 | 
			
		||||
"   345678}90    ",
 | 
			
		||||
"    a2bcdefgh   ",
 | 
			
		||||
"      ijkl.mno  ",
 | 
			
		||||
"      <pq. rstu ",
 | 
			
		||||
"      .]v.  wx= ",
 | 
			
		||||
"       .yzABCDE ",
 | 
			
		||||
"        .FGHIJ  ",
 | 
			
		||||
"         0KL0   ",
 | 
			
		||||
"                "};
 | 
			
		||||
							
								
								
									
										21
									
								
								ext/json/lib/json/TrueClass.xpm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								ext/json/lib/json/TrueClass.xpm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
/* XPM */
 | 
			
		||||
static char * TrueClass_xpm[] = {
 | 
			
		||||
"16 16 2 1",
 | 
			
		||||
" 	c None",
 | 
			
		||||
".	c #0BF311",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"   .........    ",
 | 
			
		||||
"       .        ",
 | 
			
		||||
"       .        ",
 | 
			
		||||
"       .        ",
 | 
			
		||||
"       .        ",
 | 
			
		||||
"       .        ",
 | 
			
		||||
"       .        ",
 | 
			
		||||
"       .        ",
 | 
			
		||||
"       .        ",
 | 
			
		||||
"       .        ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                ",
 | 
			
		||||
"                "};
 | 
			
		||||
							
								
								
									
										120
									
								
								ext/json/lib/json/add/core.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								ext/json/lib/json/add/core.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,120 @@
 | 
			
		|||
# This file contains implementations of ruby core's custom objects for
 | 
			
		||||
# serialisation/deserialisation.
 | 
			
		||||
 | 
			
		||||
unless Object.const_defined?(:JSON) and ::JSON.const_defined?(:JSON_LOADED) and
 | 
			
		||||
  ::JSON::JSON_LOADED
 | 
			
		||||
  require 'json'
 | 
			
		||||
end
 | 
			
		||||
require 'date'
 | 
			
		||||
 | 
			
		||||
class Time
 | 
			
		||||
  def self.json_create(object)
 | 
			
		||||
    at(*object.values_at('s', 'u'))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def to_json(*args)
 | 
			
		||||
    {
 | 
			
		||||
      'json_class' => self.class.name.to_s,
 | 
			
		||||
      's' => tv_sec,
 | 
			
		||||
      'u' => tv_usec,
 | 
			
		||||
    }.to_json(*args)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Date
 | 
			
		||||
  def self.json_create(object)
 | 
			
		||||
    civil(*object.values_at('y', 'm', 'd', 'sg'))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def to_json(*args)
 | 
			
		||||
    {
 | 
			
		||||
      'json_class' => self.class.name.to_s,
 | 
			
		||||
      'y' => year,
 | 
			
		||||
      'm' => month,
 | 
			
		||||
      'd' => day,
 | 
			
		||||
      'sg' => @sg,
 | 
			
		||||
    }.to_json(*args)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class DateTime
 | 
			
		||||
  def self.json_create(object)
 | 
			
		||||
    args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
 | 
			
		||||
    of_a, of_b = object['of'].split('/')
 | 
			
		||||
    args << Rational(of_a.to_i, of_b.to_i)
 | 
			
		||||
    args << object['sg']
 | 
			
		||||
    civil(*args)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def to_json(*args)
 | 
			
		||||
    {
 | 
			
		||||
      'json_class' => self.class.name.to_s,
 | 
			
		||||
      'y' => year,
 | 
			
		||||
      'm' => month,
 | 
			
		||||
      'd' => day,
 | 
			
		||||
      'H' => hour,
 | 
			
		||||
      'M' => min,
 | 
			
		||||
      'S' => sec,
 | 
			
		||||
      'of' => offset.to_s,
 | 
			
		||||
      'sg' => @sg,
 | 
			
		||||
    }.to_json(*args)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Range
 | 
			
		||||
  def self.json_create(object)
 | 
			
		||||
    new(*object['a'])
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def to_json(*args)
 | 
			
		||||
    {
 | 
			
		||||
      'json_class'   => self.class.name.to_s,
 | 
			
		||||
      'a'         => [ first, last, exclude_end? ]
 | 
			
		||||
    }.to_json(*args)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Struct
 | 
			
		||||
  def self.json_create(object)
 | 
			
		||||
    new(*object['v'])
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def to_json(*args)
 | 
			
		||||
    klass = self.class.name.to_s
 | 
			
		||||
    klass.empty? and raise JSON::JSONError, "Only named structs are supported!"
 | 
			
		||||
    {
 | 
			
		||||
      'json_class' => klass,
 | 
			
		||||
      'v'     => values,
 | 
			
		||||
    }.to_json(*args)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Exception
 | 
			
		||||
  def self.json_create(object)
 | 
			
		||||
    result = new(object['m'])
 | 
			
		||||
    result.set_backtrace object['b']
 | 
			
		||||
    result
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def to_json(*args)
 | 
			
		||||
    {
 | 
			
		||||
      'json_class' => self.class.name.to_s,
 | 
			
		||||
      'm'   => message,
 | 
			
		||||
      'b' => backtrace,
 | 
			
		||||
    }.to_json(*args)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Regexp
 | 
			
		||||
  def self.json_create(object)
 | 
			
		||||
    new(object['s'], object['o'])
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def to_json(*)
 | 
			
		||||
    {
 | 
			
		||||
      'json_class' => self.class.name.to_s,
 | 
			
		||||
      'o' => options,
 | 
			
		||||
      's' => source,
 | 
			
		||||
    }.to_json
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										58
									
								
								ext/json/lib/json/add/rails.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								ext/json/lib/json/add/rails.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,58 @@
 | 
			
		|||
# This file contains implementations of rails custom objects for
 | 
			
		||||
# serialisation/deserialisation.
 | 
			
		||||
 | 
			
		||||
unless Object.const_defined?(:JSON) and ::JSON.const_defined?(:JSON_LOADED) and
 | 
			
		||||
  ::JSON::JSON_LOADED
 | 
			
		||||
  require 'json'
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Object
 | 
			
		||||
  def self.json_create(object)
 | 
			
		||||
    obj = new
 | 
			
		||||
    for key, value in object
 | 
			
		||||
      next if key == 'json_class'
 | 
			
		||||
      instance_variable_set "@#{key}", value
 | 
			
		||||
    end
 | 
			
		||||
    obj
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def to_json(*a)
 | 
			
		||||
    result = {
 | 
			
		||||
      'json_class' => self.class.name
 | 
			
		||||
    }
 | 
			
		||||
    instance_variables.inject(result) do |r, name|
 | 
			
		||||
      r[name[1..-1]] = instance_variable_get name
 | 
			
		||||
      r
 | 
			
		||||
    end
 | 
			
		||||
    result.to_json(*a)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Symbol
 | 
			
		||||
  def to_json(*a)
 | 
			
		||||
    to_s.to_json(*a)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
module Enumerable
 | 
			
		||||
  def to_json(*a)
 | 
			
		||||
    to_a.to_json(*a)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# class Regexp
 | 
			
		||||
#   def to_json(*)
 | 
			
		||||
#     inspect
 | 
			
		||||
#   end
 | 
			
		||||
# end
 | 
			
		||||
#
 | 
			
		||||
# The above rails definition has some problems:
 | 
			
		||||
#
 | 
			
		||||
# 1. { 'foo' => /bar/ }.to_json # => "{foo: /bar/}"
 | 
			
		||||
#    This isn't valid JSON, because the regular expression syntax is not
 | 
			
		||||
#    defined in RFC 4627. (And unquoted strings are disallowed there, too.)
 | 
			
		||||
#    Though it is valid Javascript.
 | 
			
		||||
#
 | 
			
		||||
# 2. { 'foo' => /bar/mix }.to_json # => "{foo: /bar/mix}"
 | 
			
		||||
#    This isn't even valid Javascript.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										354
									
								
								ext/json/lib/json/common.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										354
									
								
								ext/json/lib/json/common.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,354 @@
 | 
			
		|||
require 'json/version'
 | 
			
		||||
 | 
			
		||||
module JSON
 | 
			
		||||
  class << self
 | 
			
		||||
    # If _object_ is string like parse the string and return the parsed result
 | 
			
		||||
    # as a Ruby data structure. Otherwise generate a JSON text from the Ruby
 | 
			
		||||
    # data structure object and return it.
 | 
			
		||||
    #
 | 
			
		||||
    # The _opts_ argument is passed through to generate/parse respectively, see
 | 
			
		||||
    # generate and parse for their documentation.
 | 
			
		||||
    def [](object, opts = {})
 | 
			
		||||
      if object.respond_to? :to_str
 | 
			
		||||
        JSON.parse(object.to_str, opts => {})
 | 
			
		||||
      else
 | 
			
		||||
        JSON.generate(object, opts => {})
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the JSON parser class, that is used by JSON. This might be either
 | 
			
		||||
    # JSON::Ext::Parser or JSON::Pure::Parser.
 | 
			
		||||
    attr_reader :parser
 | 
			
		||||
 | 
			
		||||
    # Set the JSON parser class _parser_ to be used by JSON.
 | 
			
		||||
    def parser=(parser) # :nodoc:
 | 
			
		||||
      @parser = parser
 | 
			
		||||
      remove_const :Parser if const_defined? :Parser
 | 
			
		||||
      const_set :Parser, parser
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Return the constant located at _path_. The format of _path_ has to be
 | 
			
		||||
    # either ::A::B::C or A::B::C. In any case A has to be located at the top
 | 
			
		||||
    # level (absolute namespace path?). If there doesn't exist a constant at
 | 
			
		||||
    # the given path, an ArgumentError is raised.
 | 
			
		||||
    def deep_const_get(path) # :nodoc:
 | 
			
		||||
      path = path.to_s
 | 
			
		||||
      path.split(/::/).inject(Object) do |p, c|
 | 
			
		||||
        case
 | 
			
		||||
        when c.empty?             then p
 | 
			
		||||
        when p.const_defined?(c)  then p.const_get(c)
 | 
			
		||||
        else                      raise ArgumentError, "can't find const #{path}"
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Set the module _generator_ to be used by JSON.
 | 
			
		||||
    def generator=(generator) # :nodoc:
 | 
			
		||||
      @generator = generator
 | 
			
		||||
      generator_methods = generator::GeneratorMethods
 | 
			
		||||
      for const in generator_methods.constants
 | 
			
		||||
        klass = deep_const_get(const)
 | 
			
		||||
        modul = generator_methods.const_get(const)
 | 
			
		||||
        klass.class_eval do
 | 
			
		||||
          instance_methods(false).each do |m|
 | 
			
		||||
            m.to_s == 'to_json' and remove_method m
 | 
			
		||||
          end
 | 
			
		||||
          include modul
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
      self.state = generator::State
 | 
			
		||||
      const_set :State, self.state
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Returns the JSON generator modul, that is used by JSON. This might be
 | 
			
		||||
    # either JSON::Ext::Generator or JSON::Pure::Generator.
 | 
			
		||||
    attr_reader :generator
 | 
			
		||||
 | 
			
		||||
    # Returns the JSON generator state class, that is used by JSON. This might
 | 
			
		||||
    # be either JSON::Ext::Generator::State or JSON::Pure::Generator::State.
 | 
			
		||||
    attr_accessor :state
 | 
			
		||||
 | 
			
		||||
    # This is create identifier, that is used to decide, if the _json_create_
 | 
			
		||||
    # hook of a class should be called. It defaults to 'json_class'.
 | 
			
		||||
    attr_accessor :create_id
 | 
			
		||||
  end
 | 
			
		||||
  self.create_id = 'json_class'
 | 
			
		||||
 | 
			
		||||
  NaN           = (-1.0) ** 0.5
 | 
			
		||||
 | 
			
		||||
  Infinity      = 1.0/0
 | 
			
		||||
 | 
			
		||||
  MinusInfinity = -Infinity
 | 
			
		||||
 | 
			
		||||
  # The base exception for JSON errors.
 | 
			
		||||
  class JSONError < StandardError; end
 | 
			
		||||
 | 
			
		||||
  # This exception is raised, if a parser error occurs.
 | 
			
		||||
  class ParserError < JSONError; end
 | 
			
		||||
 | 
			
		||||
  # This exception is raised, if the nesting of parsed datastructures is too
 | 
			
		||||
  # deep.
 | 
			
		||||
  class NestingError < ParserError; end
 | 
			
		||||
 | 
			
		||||
  # This exception is raised, if a generator or unparser error occurs.
 | 
			
		||||
  class GeneratorError < JSONError; end
 | 
			
		||||
  # For backwards compatibility
 | 
			
		||||
  UnparserError = GeneratorError
 | 
			
		||||
 | 
			
		||||
  # If a circular data structure is encountered while unparsing
 | 
			
		||||
  # this exception is raised.
 | 
			
		||||
  class CircularDatastructure < GeneratorError; end
 | 
			
		||||
 | 
			
		||||
  # This exception is raised, if the required unicode support is missing on the
 | 
			
		||||
  # system. Usually this means, that the iconv library is not installed.
 | 
			
		||||
  class MissingUnicodeSupport < JSONError; end
 | 
			
		||||
 | 
			
		||||
  module_function
 | 
			
		||||
 | 
			
		||||
  # Parse the JSON string _source_ into a Ruby data structure and return it.
 | 
			
		||||
  #
 | 
			
		||||
  # _opts_ can have the following
 | 
			
		||||
  # keys:
 | 
			
		||||
  # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
 | 
			
		||||
  #   structures. Disable depth checking with :max_nesting => false, it defaults
 | 
			
		||||
  #   to 19.
 | 
			
		||||
  # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
 | 
			
		||||
  #   defiance of RFC 4627 to be parsed by the Parser. This option defaults
 | 
			
		||||
  #   to false.
 | 
			
		||||
  # * *create_additions*: If set to false, the Parser doesn't create
 | 
			
		||||
  #   additions even if a matchin class and create_id was found. This option
 | 
			
		||||
  #   defaults to true.
 | 
			
		||||
  def parse(source, opts = {})
 | 
			
		||||
    JSON.parser.new(source, opts).parse
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Parse the JSON string _source_ into a Ruby data structure and return it.
 | 
			
		||||
  # The bang version of the parse method, defaults to the more dangerous values
 | 
			
		||||
  # for the _opts_ hash, so be sure only to parse trusted _source_ strings.
 | 
			
		||||
  #
 | 
			
		||||
  # _opts_ can have the following keys:
 | 
			
		||||
  # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
 | 
			
		||||
  #   structures. Enable depth checking with :max_nesting => anInteger. The parse!
 | 
			
		||||
  #   methods defaults to not doing max depth checking: This can be dangerous,
 | 
			
		||||
  #   if someone wants to fill up your stack.
 | 
			
		||||
  # * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in
 | 
			
		||||
  #   defiance of RFC 4627 to be parsed by the Parser. This option defaults
 | 
			
		||||
  #   to true.
 | 
			
		||||
  # * *create_additions*: If set to false, the Parser doesn't create
 | 
			
		||||
  #   additions even if a matchin class and create_id was found. This option
 | 
			
		||||
  #   defaults to true.
 | 
			
		||||
  def parse!(source, opts = {})
 | 
			
		||||
    opts = {
 | 
			
		||||
      :max_nesting => false,
 | 
			
		||||
      :allow_nan => true
 | 
			
		||||
    }.update(opts)
 | 
			
		||||
    JSON.parser.new(source, opts).parse
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Unparse the Ruby data structure _obj_ into a single line JSON string and
 | 
			
		||||
  # return it. _state_ is
 | 
			
		||||
  # * a JSON::State object,
 | 
			
		||||
  # * or a Hash like object (responding to to_hash),
 | 
			
		||||
  # * an object convertible into a hash by a to_h method,
 | 
			
		||||
  # that is used as or to configure a State object.
 | 
			
		||||
  #
 | 
			
		||||
  # It defaults to a state object, that creates the shortest possible JSON text
 | 
			
		||||
  # in one line, checks for circular data structures and doesn't allow NaN,
 | 
			
		||||
  # Infinity, and -Infinity.
 | 
			
		||||
  #
 | 
			
		||||
  # A _state_ hash can have the following keys:
 | 
			
		||||
  # * *indent*: a string used to indent levels (default: ''),
 | 
			
		||||
  # * *space*: a string that is put after, a : or , delimiter (default: ''),
 | 
			
		||||
  # * *space_before*: a string that is put before a : pair delimiter (default: ''),
 | 
			
		||||
  # * *object_nl*: a string that is put at the end of a JSON object (default: ''), 
 | 
			
		||||
  # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
 | 
			
		||||
  # * *check_circular*: true if checking for circular data structures
 | 
			
		||||
  #   should be done (the default), false otherwise.
 | 
			
		||||
  # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
 | 
			
		||||
  #   generated, otherwise an exception is thrown, if these values are
 | 
			
		||||
  #   encountered. This options defaults to false.
 | 
			
		||||
  # * *max_nesting*: The maximum depth of nesting allowed in the data
 | 
			
		||||
  #   structures from which JSON is to be generated. Disable depth checking
 | 
			
		||||
  #   with :max_nesting => false, it defaults to 19.
 | 
			
		||||
  #
 | 
			
		||||
  # See also the fast_generate for the fastest creation method with the least
 | 
			
		||||
  # amount of sanity checks, and the pretty_generate method for some
 | 
			
		||||
  # defaults for a pretty output.
 | 
			
		||||
  def generate(obj, state = nil)
 | 
			
		||||
    if state
 | 
			
		||||
      state = State.from_state(state)
 | 
			
		||||
    else
 | 
			
		||||
      state = State.new
 | 
			
		||||
    end
 | 
			
		||||
    obj.to_json(state)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # :stopdoc:
 | 
			
		||||
  # I want to deprecate these later, so I'll first be silent about them, and later delete them.
 | 
			
		||||
  alias unparse generate
 | 
			
		||||
  module_function :unparse
 | 
			
		||||
  # :startdoc:
 | 
			
		||||
 | 
			
		||||
  # Unparse the Ruby data structure _obj_ into a single line JSON string and
 | 
			
		||||
  # return it. This method disables the checks for circles in Ruby objects, and
 | 
			
		||||
  # also generates NaN, Infinity, and, -Infinity float values.
 | 
			
		||||
  #
 | 
			
		||||
  # *WARNING*: Be careful not to pass any Ruby data structures with circles as
 | 
			
		||||
  # _obj_ argument, because this will cause JSON to go into an infinite loop.
 | 
			
		||||
  def fast_generate(obj)
 | 
			
		||||
    obj.to_json(nil)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # :stopdoc:
 | 
			
		||||
  # I want to deprecate these later, so I'll first be silent about them, and later delete them.
 | 
			
		||||
  alias fast_unparse fast_generate
 | 
			
		||||
  module_function :fast_unparse
 | 
			
		||||
  # :startdoc:
 | 
			
		||||
 | 
			
		||||
  # Unparse the Ruby data structure _obj_ into a JSON string and return it. The
 | 
			
		||||
  # returned string is a prettier form of the string returned by #unparse.
 | 
			
		||||
  #
 | 
			
		||||
  # The _opts_ argument can be used to configure the generator, see the
 | 
			
		||||
  # generate method for a more detailed explanation.
 | 
			
		||||
  def pretty_generate(obj, opts = nil)
 | 
			
		||||
    state = JSON.state.new(
 | 
			
		||||
      :indent     => '  ',
 | 
			
		||||
      :space      => ' ',
 | 
			
		||||
      :object_nl  => "\n",
 | 
			
		||||
      :array_nl   => "\n",
 | 
			
		||||
      :check_circular => true
 | 
			
		||||
    )
 | 
			
		||||
    if opts
 | 
			
		||||
      if opts.respond_to? :to_hash
 | 
			
		||||
        opts = opts.to_hash
 | 
			
		||||
      elsif opts.respond_to? :to_h
 | 
			
		||||
        opts = opts.to_h
 | 
			
		||||
      else
 | 
			
		||||
        raise TypeError, "can't convert #{opts.class} into Hash"
 | 
			
		||||
      end
 | 
			
		||||
      state.configure(opts)
 | 
			
		||||
    end
 | 
			
		||||
    obj.to_json(state)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # :stopdoc:
 | 
			
		||||
  # I want to deprecate these later, so I'll first be silent about them, and later delete them.
 | 
			
		||||
  alias pretty_unparse pretty_generate
 | 
			
		||||
  module_function :pretty_unparse
 | 
			
		||||
  # :startdoc:
 | 
			
		||||
 | 
			
		||||
  # Load a ruby data structure from a JSON _source_ and return it. A source can
 | 
			
		||||
  # either be a string like object, an IO like object, or an object responding
 | 
			
		||||
  # to the read method. If _proc_ was given, it will be called with any nested
 | 
			
		||||
  # Ruby object as an argument recursively in depth first order.
 | 
			
		||||
  #
 | 
			
		||||
  # This method is part of the implementation of the load/dump interface of
 | 
			
		||||
  # Marshal and YAML.
 | 
			
		||||
  def load(source, proc = nil)
 | 
			
		||||
    if source.respond_to? :to_str
 | 
			
		||||
      source = source.to_str
 | 
			
		||||
    elsif source.respond_to? :to_io
 | 
			
		||||
      source = source.to_io.read
 | 
			
		||||
    else
 | 
			
		||||
      source = source.read
 | 
			
		||||
    end
 | 
			
		||||
    result = parse(source, :max_nesting => false, :allow_nan => true)
 | 
			
		||||
    recurse_proc(result, &proc) if proc
 | 
			
		||||
    result
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def recurse_proc(result, &proc)
 | 
			
		||||
    case result
 | 
			
		||||
    when Array
 | 
			
		||||
      result.each { |x| recurse_proc x, &proc }
 | 
			
		||||
      proc.call result
 | 
			
		||||
    when Hash
 | 
			
		||||
      result.each { |x, y| recurse_proc x, &proc; recurse_proc y, &proc }
 | 
			
		||||
      proc.call result
 | 
			
		||||
    else
 | 
			
		||||
      proc.call result
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  private :recurse_proc
 | 
			
		||||
  module_function :recurse_proc
 | 
			
		||||
 | 
			
		||||
  alias restore load
 | 
			
		||||
  module_function :restore
 | 
			
		||||
 | 
			
		||||
  # Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns
 | 
			
		||||
  # the result.
 | 
			
		||||
  #
 | 
			
		||||
  # If anIO (an IO like object or an object that responds to the write method)
 | 
			
		||||
  # was given, the resulting JSON is written to it.
 | 
			
		||||
  #
 | 
			
		||||
  # If the number of nested arrays or objects exceeds _limit_ an ArgumentError
 | 
			
		||||
  # exception is raised. This argument is similar (but not exactly the
 | 
			
		||||
  # same!) to the _limit_ argument in Marshal.dump.
 | 
			
		||||
  #
 | 
			
		||||
  # This method is part of the implementation of the load/dump interface of
 | 
			
		||||
  # Marshal and YAML.
 | 
			
		||||
  def dump(obj, anIO = nil, limit = nil)
 | 
			
		||||
    if anIO and limit.nil?
 | 
			
		||||
      anIO = anIO.to_io if anIO.respond_to?(:to_io)
 | 
			
		||||
      unless anIO.respond_to?(:write)
 | 
			
		||||
        limit = anIO
 | 
			
		||||
        anIO = nil
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    limit ||= 0
 | 
			
		||||
    result = generate(obj, :allow_nan => true, :max_nesting => limit)
 | 
			
		||||
    if anIO
 | 
			
		||||
      anIO.write result
 | 
			
		||||
      anIO
 | 
			
		||||
    else
 | 
			
		||||
      result
 | 
			
		||||
    end
 | 
			
		||||
  rescue JSON::NestingError
 | 
			
		||||
    raise ArgumentError, "exceed depth limit"
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
module ::Kernel
 | 
			
		||||
  # Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in
 | 
			
		||||
  # one line.
 | 
			
		||||
  def j(*objs)
 | 
			
		||||
    objs.each do |obj|
 | 
			
		||||
      puts JSON::generate(obj, :allow_nan => true, :max_nesting => false)
 | 
			
		||||
    end
 | 
			
		||||
    nil
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Ouputs _objs_ to STDOUT as JSON strings in a pretty format, with
 | 
			
		||||
  # indentation and over many lines.
 | 
			
		||||
  def jj(*objs)
 | 
			
		||||
    objs.each do |obj|
 | 
			
		||||
      puts JSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false)
 | 
			
		||||
    end
 | 
			
		||||
    nil
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # If _object_ is string like parse the string and return the parsed result as
 | 
			
		||||
  # a Ruby data structure. Otherwise generate a JSON text from the Ruby data
 | 
			
		||||
  # structure object and return it.
 | 
			
		||||
  #
 | 
			
		||||
  # The _opts_ argument is passed through to generate/parse respectively, see
 | 
			
		||||
  # generate and parse for their documentation.
 | 
			
		||||
  def JSON(object, opts = {})
 | 
			
		||||
    if object.respond_to? :to_str
 | 
			
		||||
      JSON.parse(object.to_str, opts)
 | 
			
		||||
    else
 | 
			
		||||
      JSON.generate(object, opts)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class ::Class
 | 
			
		||||
  # Returns true, if this class can be used to create an instance
 | 
			
		||||
  # from a serialised JSON string. The class has to implement a class
 | 
			
		||||
  # method _json_create_ that expects a hash as first parameter, which includes
 | 
			
		||||
  # the required data.
 | 
			
		||||
  def json_creatable?
 | 
			
		||||
    respond_to?(:json_create)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
  # vim: set et sw=2 ts=2:
 | 
			
		||||
							
								
								
									
										1363
									
								
								ext/json/lib/json/editor.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1363
									
								
								ext/json/lib/json/editor.rb
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										13
									
								
								ext/json/lib/json/ext.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								ext/json/lib/json/ext.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
require 'json/common'
 | 
			
		||||
 | 
			
		||||
module JSON
 | 
			
		||||
  # This module holds all the modules/classes that implement JSON's
 | 
			
		||||
  # functionality as C extensions.
 | 
			
		||||
  module Ext
 | 
			
		||||
    require 'json/ext/parser'
 | 
			
		||||
    require 'json/ext/generator'
 | 
			
		||||
    $DEBUG and warn "Using c extension for JSON."
 | 
			
		||||
    JSON.parser = Parser
 | 
			
		||||
    JSON.generator = Generator
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										1499
									
								
								ext/json/lib/json/json.xpm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1499
									
								
								ext/json/lib/json/json.xpm
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										75
									
								
								ext/json/lib/json/pure.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								ext/json/lib/json/pure.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,75 @@
 | 
			
		|||
require 'json/common'
 | 
			
		||||
require 'json/pure/parser'
 | 
			
		||||
require 'json/pure/generator'
 | 
			
		||||
 | 
			
		||||
module JSON
 | 
			
		||||
  begin
 | 
			
		||||
    require 'iconv'
 | 
			
		||||
    # An iconv instance to convert from UTF8 to UTF16 Big Endian.
 | 
			
		||||
    UTF16toUTF8 = Iconv.new('utf-8', 'utf-16be') # :nodoc:
 | 
			
		||||
    # An iconv instance to convert from UTF16 Big Endian to UTF8.
 | 
			
		||||
    UTF8toUTF16 = Iconv.new('utf-16be', 'utf-8') # :nodoc:
 | 
			
		||||
    UTF8toUTF16.iconv('no bom')
 | 
			
		||||
  rescue Errno::EINVAL, Iconv::InvalidEncoding
 | 
			
		||||
    # Iconv doesn't support big endian utf-16. Let's try to hack this manually
 | 
			
		||||
    # into the converters.
 | 
			
		||||
    begin
 | 
			
		||||
      old_verbose, $VERBSOSE = $VERBOSE, nil
 | 
			
		||||
      # An iconv instance to convert from UTF8 to UTF16 Big Endian.
 | 
			
		||||
      UTF16toUTF8 = Iconv.new('utf-8', 'utf-16') # :nodoc:
 | 
			
		||||
      # An iconv instance to convert from UTF16 Big Endian to UTF8.
 | 
			
		||||
      UTF8toUTF16 = Iconv.new('utf-16', 'utf-8') # :nodoc:
 | 
			
		||||
      UTF8toUTF16.iconv('no bom')
 | 
			
		||||
      if UTF8toUTF16.iconv("\xe2\x82\xac") == "\xac\x20"
 | 
			
		||||
        swapper = Class.new do
 | 
			
		||||
          def initialize(iconv) # :nodoc:
 | 
			
		||||
            @iconv = iconv
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def iconv(string) # :nodoc:
 | 
			
		||||
            result = @iconv.iconv(string)
 | 
			
		||||
            JSON.swap!(result)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
        UTF8toUTF16 = swapper.new(UTF8toUTF16) # :nodoc:
 | 
			
		||||
      end
 | 
			
		||||
      if UTF16toUTF8.iconv("\xac\x20") == "\xe2\x82\xac"
 | 
			
		||||
        swapper = Class.new do
 | 
			
		||||
          def initialize(iconv) # :nodoc:
 | 
			
		||||
            @iconv = iconv
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def iconv(string) # :nodoc:
 | 
			
		||||
            string = JSON.swap!(string.dup)
 | 
			
		||||
            @iconv.iconv(string)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
        UTF16toUTF8 = swapper.new(UTF16toUTF8) # :nodoc:
 | 
			
		||||
      end
 | 
			
		||||
    rescue Errno::EINVAL, Iconv::InvalidEncoding
 | 
			
		||||
      raise MissingUnicodeSupport, "iconv doesn't seem to support UTF-8/UTF-16 conversions"
 | 
			
		||||
    ensure
 | 
			
		||||
      $VERBOSE = old_verbose
 | 
			
		||||
    end
 | 
			
		||||
  rescue LoadError
 | 
			
		||||
    raise MissingUnicodeSupport,
 | 
			
		||||
      "iconv couldn't be loaded, which is required for UTF-8/UTF-16 conversions"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Swap consecutive bytes of _string_ in place.
 | 
			
		||||
  def self.swap!(string) # :nodoc:
 | 
			
		||||
    0.upto(string.size / 2) do |i|
 | 
			
		||||
      break unless string[2 * i + 1]
 | 
			
		||||
      string[2 * i], string[2 * i + 1] = string[2 * i + 1], string[2 * i]
 | 
			
		||||
    end
 | 
			
		||||
    string
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # This module holds all the modules/classes that implement JSON's
 | 
			
		||||
  # functionality in pure ruby.
 | 
			
		||||
  module Pure
 | 
			
		||||
    $DEBUG and warn "Using pure library for JSON."
 | 
			
		||||
    JSON.parser = Parser
 | 
			
		||||
    JSON.generator = Generator
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										394
									
								
								ext/json/lib/json/pure/generator.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										394
									
								
								ext/json/lib/json/pure/generator.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,394 @@
 | 
			
		|||
module JSON
 | 
			
		||||
  MAP = {
 | 
			
		||||
    "\x0" => '\u0000',
 | 
			
		||||
    "\x1" => '\u0001',
 | 
			
		||||
    "\x2" => '\u0002',
 | 
			
		||||
    "\x3" => '\u0003',
 | 
			
		||||
    "\x4" => '\u0004',
 | 
			
		||||
    "\x5" => '\u0005',
 | 
			
		||||
    "\x6" => '\u0006',
 | 
			
		||||
    "\x7" => '\u0007',
 | 
			
		||||
    "\b"  =>  '\b',
 | 
			
		||||
    "\t"  =>  '\t',
 | 
			
		||||
    "\n"  =>  '\n',
 | 
			
		||||
    "\xb" => '\u000b',
 | 
			
		||||
    "\f"  =>  '\f',
 | 
			
		||||
    "\r"  =>  '\r',
 | 
			
		||||
    "\xe" => '\u000e',
 | 
			
		||||
    "\xf" => '\u000f',
 | 
			
		||||
    "\x10" => '\u0010',
 | 
			
		||||
    "\x11" => '\u0011',
 | 
			
		||||
    "\x12" => '\u0012',
 | 
			
		||||
    "\x13" => '\u0013',
 | 
			
		||||
    "\x14" => '\u0014',
 | 
			
		||||
    "\x15" => '\u0015',
 | 
			
		||||
    "\x16" => '\u0016',
 | 
			
		||||
    "\x17" => '\u0017',
 | 
			
		||||
    "\x18" => '\u0018',
 | 
			
		||||
    "\x19" => '\u0019',
 | 
			
		||||
    "\x1a" => '\u001a',
 | 
			
		||||
    "\x1b" => '\u001b',
 | 
			
		||||
    "\x1c" => '\u001c',
 | 
			
		||||
    "\x1d" => '\u001d',
 | 
			
		||||
    "\x1e" => '\u001e',
 | 
			
		||||
    "\x1f" => '\u001f',
 | 
			
		||||
    '"'   =>  '\"',
 | 
			
		||||
    '\\'  =>  '\\\\',
 | 
			
		||||
    '/'   =>  '\/',
 | 
			
		||||
  } # :nodoc:
 | 
			
		||||
 | 
			
		||||
  # Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
 | 
			
		||||
  # UTF16 big endian characters as \u????, and return it.
 | 
			
		||||
  def utf8_to_json(string) # :nodoc:
 | 
			
		||||
    string = string.gsub(/["\\\/\x0-\x1f]/) { |c| MAP[c] }
 | 
			
		||||
    string.gsub!(/(
 | 
			
		||||
                    (?:
 | 
			
		||||
                      [\xc2-\xdf][\x80-\xbf]    |
 | 
			
		||||
                      [\xe0-\xef][\x80-\xbf]{2} |
 | 
			
		||||
                      [\xf0-\xf4][\x80-\xbf]{3}
 | 
			
		||||
                    )+ |
 | 
			
		||||
                    [\x80-\xc1\xf5-\xff]       # invalid
 | 
			
		||||
                  )/nx) { |c|
 | 
			
		||||
      c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
 | 
			
		||||
      s = JSON::UTF8toUTF16.iconv(c).unpack('H*')[0]
 | 
			
		||||
      s.gsub!(/.{4}/n, '\\\\u\&')
 | 
			
		||||
    }
 | 
			
		||||
    string
 | 
			
		||||
  rescue Iconv::Failure => e
 | 
			
		||||
    raise GeneratorError, "Caught #{e.class}: #{e}"
 | 
			
		||||
  end
 | 
			
		||||
  module_function :utf8_to_json
 | 
			
		||||
 | 
			
		||||
  module Pure
 | 
			
		||||
    module Generator
 | 
			
		||||
      # This class is used to create State instances, that are use to hold data
 | 
			
		||||
      # while generating a JSON text from a a Ruby data structure.
 | 
			
		||||
      class State
 | 
			
		||||
        # Creates a State object from _opts_, which ought to be Hash to create
 | 
			
		||||
        # a new State instance configured by _opts_, something else to create
 | 
			
		||||
        # an unconfigured instance. If _opts_ is a State object, it is just
 | 
			
		||||
        # returned.
 | 
			
		||||
        def self.from_state(opts)
 | 
			
		||||
          case opts
 | 
			
		||||
          when self
 | 
			
		||||
            opts
 | 
			
		||||
          when Hash
 | 
			
		||||
            new(opts)
 | 
			
		||||
          else
 | 
			
		||||
            new
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Instantiates a new State object, configured by _opts_.
 | 
			
		||||
        #
 | 
			
		||||
        # _opts_ can have the following keys:
 | 
			
		||||
        #
 | 
			
		||||
        # * *indent*: a string used to indent levels (default: ''),
 | 
			
		||||
        # * *space*: a string that is put after, a : or , delimiter (default: ''),
 | 
			
		||||
        # * *space_before*: a string that is put before a : pair delimiter (default: ''),
 | 
			
		||||
        # * *object_nl*: a string that is put at the end of a JSON object (default: ''), 
 | 
			
		||||
        # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
 | 
			
		||||
        # * *check_circular*: true if checking for circular data structures
 | 
			
		||||
        #   should be done (the default), false otherwise.
 | 
			
		||||
        # * *check_circular*: true if checking for circular data structures
 | 
			
		||||
        #   should be done, false (the default) otherwise.
 | 
			
		||||
        # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
 | 
			
		||||
        #   generated, otherwise an exception is thrown, if these values are
 | 
			
		||||
        #   encountered. This options defaults to false.
 | 
			
		||||
        def initialize(opts = {})
 | 
			
		||||
          @seen = {}
 | 
			
		||||
          @indent         = ''
 | 
			
		||||
          @space          = ''
 | 
			
		||||
          @space_before   = ''
 | 
			
		||||
          @object_nl      = ''
 | 
			
		||||
          @array_nl       = ''
 | 
			
		||||
          @check_circular = true
 | 
			
		||||
          @allow_nan      = false
 | 
			
		||||
          configure opts
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # This string is used to indent levels in the JSON text.
 | 
			
		||||
        attr_accessor :indent
 | 
			
		||||
 | 
			
		||||
        # This string is used to insert a space between the tokens in a JSON
 | 
			
		||||
        # string.
 | 
			
		||||
        attr_accessor :space
 | 
			
		||||
 | 
			
		||||
        # This string is used to insert a space before the ':' in JSON objects.
 | 
			
		||||
        attr_accessor :space_before
 | 
			
		||||
 | 
			
		||||
        # This string is put at the end of a line that holds a JSON object (or
 | 
			
		||||
        # Hash).
 | 
			
		||||
        attr_accessor :object_nl
 | 
			
		||||
 | 
			
		||||
        # This string is put at the end of a line that holds a JSON array.
 | 
			
		||||
        attr_accessor :array_nl
 | 
			
		||||
 | 
			
		||||
        # This integer returns the maximum level of data structure nesting in
 | 
			
		||||
        # the generated JSON, max_nesting = 0 if no maximum is checked.
 | 
			
		||||
        attr_accessor :max_nesting
 | 
			
		||||
 | 
			
		||||
        def check_max_nesting(depth) # :nodoc:
 | 
			
		||||
          return if @max_nesting.zero?
 | 
			
		||||
          current_nesting = depth + 1
 | 
			
		||||
          current_nesting > @max_nesting and
 | 
			
		||||
            raise NestingError, "nesting of #{current_nesting} is too deep"
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Returns true, if circular data structures should be checked,
 | 
			
		||||
        # otherwise returns false.
 | 
			
		||||
        def check_circular?
 | 
			
		||||
          @check_circular
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Returns true if NaN, Infinity, and -Infinity should be considered as
 | 
			
		||||
        # valid JSON and output.
 | 
			
		||||
        def allow_nan?
 | 
			
		||||
          @allow_nan
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Returns _true_, if _object_ was already seen during this generating
 | 
			
		||||
        # run. 
 | 
			
		||||
        def seen?(object)
 | 
			
		||||
          @seen.key?(object.__id__)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Remember _object_, to find out if it was already encountered (if a
 | 
			
		||||
        # cyclic data structure is if a cyclic data structure is rendered). 
 | 
			
		||||
        def remember(object)
 | 
			
		||||
          @seen[object.__id__] = true
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Forget _object_ for this generating run.
 | 
			
		||||
        def forget(object)
 | 
			
		||||
          @seen.delete object.__id__
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Configure this State instance with the Hash _opts_, and return
 | 
			
		||||
        # itself.
 | 
			
		||||
        def configure(opts)
 | 
			
		||||
          @indent         = opts[:indent] if opts.key?(:indent)
 | 
			
		||||
          @space          = opts[:space] if opts.key?(:space)
 | 
			
		||||
          @space_before   = opts[:space_before] if opts.key?(:space_before)
 | 
			
		||||
          @object_nl      = opts[:object_nl] if opts.key?(:object_nl)
 | 
			
		||||
          @array_nl       = opts[:array_nl] if opts.key?(:array_nl)
 | 
			
		||||
          @check_circular = !!opts[:check_circular] if opts.key?(:check_circular)
 | 
			
		||||
          @allow_nan      = !!opts[:allow_nan] if opts.key?(:allow_nan)
 | 
			
		||||
          if !opts.key?(:max_nesting) # defaults to 19
 | 
			
		||||
            @max_nesting = 19
 | 
			
		||||
          elsif opts[:max_nesting]
 | 
			
		||||
            @max_nesting = opts[:max_nesting]
 | 
			
		||||
          else
 | 
			
		||||
            @max_nesting = 0
 | 
			
		||||
          end
 | 
			
		||||
          self
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # Returns the configuration instance variables as a hash, that can be
 | 
			
		||||
        # passed to the configure method.
 | 
			
		||||
        def to_h
 | 
			
		||||
          result = {}
 | 
			
		||||
          for iv in %w[indent space space_before object_nl array_nl check_circular allow_nan max_nesting]
 | 
			
		||||
            result[iv.intern] = instance_variable_get("@#{iv}")
 | 
			
		||||
          end
 | 
			
		||||
          result
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      module GeneratorMethods
 | 
			
		||||
        module Object
 | 
			
		||||
          # Converts this object to a string (calling #to_s), converts
 | 
			
		||||
          # it to a JSON string, and returns the result. This is a fallback, if no
 | 
			
		||||
          # special method #to_json was defined for some object.
 | 
			
		||||
          def to_json(*) to_s.to_json end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        module Hash
 | 
			
		||||
          # Returns a JSON string containing a JSON object, that is unparsed from
 | 
			
		||||
          # this Hash instance.
 | 
			
		||||
          # _state_ is a JSON::State object, that can also be used to configure the
 | 
			
		||||
          # produced JSON string output further.
 | 
			
		||||
          # _depth_ is used to find out nesting depth, to indent accordingly.
 | 
			
		||||
          def to_json(state = nil, depth = 0, *)
 | 
			
		||||
            if state
 | 
			
		||||
              state = JSON.state.from_state(state)
 | 
			
		||||
              state.check_max_nesting(depth)
 | 
			
		||||
              json_check_circular(state) { json_transform(state, depth) }
 | 
			
		||||
            else
 | 
			
		||||
              json_transform(state, depth)
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          private
 | 
			
		||||
 | 
			
		||||
          def json_check_circular(state)
 | 
			
		||||
            if state and state.check_circular?
 | 
			
		||||
              state.seen?(self) and raise JSON::CircularDatastructure,
 | 
			
		||||
                  "circular data structures not supported!"
 | 
			
		||||
              state.remember self
 | 
			
		||||
            end
 | 
			
		||||
            yield
 | 
			
		||||
          ensure
 | 
			
		||||
            state and state.forget self
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def json_shift(state, depth)
 | 
			
		||||
            state and not state.object_nl.empty? or return ''
 | 
			
		||||
            state.indent * depth
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def json_transform(state, depth)
 | 
			
		||||
            delim = ','
 | 
			
		||||
            delim << state.object_nl if state
 | 
			
		||||
            result = '{'
 | 
			
		||||
            result << state.object_nl if state
 | 
			
		||||
            result << map { |key,value|
 | 
			
		||||
              s = json_shift(state, depth + 1)
 | 
			
		||||
              s << key.to_s.to_json(state, depth + 1)
 | 
			
		||||
              s << state.space_before if state
 | 
			
		||||
              s << ':'
 | 
			
		||||
              s << state.space if state
 | 
			
		||||
              s << value.to_json(state, depth + 1)
 | 
			
		||||
            }.join(delim)
 | 
			
		||||
            result << state.object_nl if state
 | 
			
		||||
            result << json_shift(state, depth)
 | 
			
		||||
            result << '}'
 | 
			
		||||
            result
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        module Array
 | 
			
		||||
          # Returns a JSON string containing a JSON array, that is unparsed from
 | 
			
		||||
          # this Array instance.
 | 
			
		||||
          # _state_ is a JSON::State object, that can also be used to configure the
 | 
			
		||||
          # produced JSON string output further.
 | 
			
		||||
          # _depth_ is used to find out nesting depth, to indent accordingly.
 | 
			
		||||
          def to_json(state = nil, depth = 0, *)
 | 
			
		||||
            if state
 | 
			
		||||
              state = JSON.state.from_state(state)
 | 
			
		||||
              state.check_max_nesting(depth)
 | 
			
		||||
              json_check_circular(state) { json_transform(state, depth) }
 | 
			
		||||
            else
 | 
			
		||||
              json_transform(state, depth)
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          private
 | 
			
		||||
 | 
			
		||||
          def json_check_circular(state)
 | 
			
		||||
            if state and state.check_circular?
 | 
			
		||||
              state.seen?(self) and raise JSON::CircularDatastructure,
 | 
			
		||||
                "circular data structures not supported!"
 | 
			
		||||
              state.remember self
 | 
			
		||||
            end
 | 
			
		||||
            yield
 | 
			
		||||
          ensure
 | 
			
		||||
            state and state.forget self
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def json_shift(state, depth)
 | 
			
		||||
            state and not state.array_nl.empty? or return ''
 | 
			
		||||
            state.indent * depth
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          def json_transform(state, depth)
 | 
			
		||||
            delim = ','
 | 
			
		||||
            delim << state.array_nl if state
 | 
			
		||||
            result = '['
 | 
			
		||||
            result << state.array_nl if state
 | 
			
		||||
            result << map { |value|
 | 
			
		||||
              json_shift(state, depth + 1) << value.to_json(state, depth + 1)
 | 
			
		||||
            }.join(delim)
 | 
			
		||||
            result << state.array_nl if state
 | 
			
		||||
            result << json_shift(state, depth) 
 | 
			
		||||
            result << ']'
 | 
			
		||||
            result
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        module Integer
 | 
			
		||||
          # Returns a JSON string representation for this Integer number.
 | 
			
		||||
          def to_json(*) to_s end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        module Float
 | 
			
		||||
          # Returns a JSON string representation for this Float number.
 | 
			
		||||
          def to_json(state = nil, *)
 | 
			
		||||
            case
 | 
			
		||||
            when infinite?
 | 
			
		||||
              if !state || state.allow_nan?
 | 
			
		||||
                to_s
 | 
			
		||||
              else
 | 
			
		||||
                raise GeneratorError, "#{self} not allowed in JSON"
 | 
			
		||||
              end
 | 
			
		||||
            when nan?
 | 
			
		||||
              if !state || state.allow_nan?
 | 
			
		||||
                to_s
 | 
			
		||||
              else
 | 
			
		||||
                raise GeneratorError, "#{self} not allowed in JSON"
 | 
			
		||||
              end
 | 
			
		||||
            else
 | 
			
		||||
              to_s
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        module String
 | 
			
		||||
          # This string should be encoded with UTF-8 A call to this method
 | 
			
		||||
          # returns a JSON string encoded with UTF16 big endian characters as
 | 
			
		||||
          # \u????.
 | 
			
		||||
          def to_json(*)
 | 
			
		||||
            '"' << JSON.utf8_to_json(self) << '"'
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          # Module that holds the extinding methods if, the String module is
 | 
			
		||||
          # included.
 | 
			
		||||
          module Extend
 | 
			
		||||
            # Raw Strings are JSON Objects (the raw bytes are stored in an array for the
 | 
			
		||||
            # key "raw"). The Ruby String can be created by this module method.
 | 
			
		||||
            def json_create(o)
 | 
			
		||||
              o['raw'].pack('C*')
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          # Extends _modul_ with the String::Extend module.
 | 
			
		||||
          def self.included(modul)
 | 
			
		||||
            modul.extend Extend
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          # This method creates a raw object hash, that can be nested into
 | 
			
		||||
          # other data structures and will be unparsed as a raw string. This
 | 
			
		||||
          # method should be used, if you want to convert raw strings to JSON
 | 
			
		||||
          # instead of UTF-8 strings, e. g. binary data.
 | 
			
		||||
          def to_json_raw_object
 | 
			
		||||
            {
 | 
			
		||||
              JSON.create_id  => self.class.name,
 | 
			
		||||
              'raw'           => self.unpack('C*'),
 | 
			
		||||
            }
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          # This method creates a JSON text from the result of
 | 
			
		||||
          # a call to to_json_raw_object of this String.
 | 
			
		||||
          def to_json_raw(*args)
 | 
			
		||||
            to_json_raw_object.to_json(*args)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        module TrueClass
 | 
			
		||||
          # Returns a JSON string for true: 'true'.
 | 
			
		||||
          def to_json(*) 'true' end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        module FalseClass
 | 
			
		||||
          # Returns a JSON string for false: 'false'.
 | 
			
		||||
          def to_json(*) 'false' end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        module NilClass
 | 
			
		||||
          # Returns a JSON string for nil: 'null'.
 | 
			
		||||
          def to_json(*) 'null' end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										259
									
								
								ext/json/lib/json/pure/parser.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								ext/json/lib/json/pure/parser.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,259 @@
 | 
			
		|||
require 'strscan'
 | 
			
		||||
 | 
			
		||||
module JSON
 | 
			
		||||
  module Pure
 | 
			
		||||
    # This class implements the JSON parser that is used to parse a JSON string
 | 
			
		||||
    # into a Ruby data structure.
 | 
			
		||||
    class Parser < StringScanner
 | 
			
		||||
      STRING                = /" ((?:[^\x0-\x1f"\\] |
 | 
			
		||||
                                  \\["\\\/bfnrt] |
 | 
			
		||||
                                  \\u[0-9a-fA-F]{4} |
 | 
			
		||||
                                  \\[\x20-\xff])*)
 | 
			
		||||
                              "/nx
 | 
			
		||||
      INTEGER               = /(-?0|-?[1-9]\d*)/
 | 
			
		||||
      FLOAT                 = /(-?
 | 
			
		||||
                                (?:0|[1-9]\d*)
 | 
			
		||||
                                (?:
 | 
			
		||||
                                  \.\d+(?i:e[+-]?\d+) |
 | 
			
		||||
                                  \.\d+ |
 | 
			
		||||
                                  (?i:e[+-]?\d+)
 | 
			
		||||
                                )
 | 
			
		||||
                                )/x
 | 
			
		||||
      NAN                   = /NaN/
 | 
			
		||||
      INFINITY              = /Infinity/
 | 
			
		||||
      MINUS_INFINITY        = /-Infinity/
 | 
			
		||||
      OBJECT_OPEN           = /\{/
 | 
			
		||||
      OBJECT_CLOSE          = /\}/
 | 
			
		||||
      ARRAY_OPEN            = /\[/
 | 
			
		||||
      ARRAY_CLOSE           = /\]/
 | 
			
		||||
      PAIR_DELIMITER        = /:/
 | 
			
		||||
      COLLECTION_DELIMITER  = /,/
 | 
			
		||||
      TRUE                  = /true/
 | 
			
		||||
      FALSE                 = /false/
 | 
			
		||||
      NULL                  = /null/
 | 
			
		||||
      IGNORE                = %r(
 | 
			
		||||
        (?:
 | 
			
		||||
         //[^\n\r]*[\n\r]| # line comments
 | 
			
		||||
         /\*               # c-style comments
 | 
			
		||||
         (?:
 | 
			
		||||
          [^*/]|        # normal chars
 | 
			
		||||
          /[^*]|        # slashes that do not start a nested comment
 | 
			
		||||
          \*[^/]|       # asterisks that do not end this comment
 | 
			
		||||
          /(?=\*/)      # single slash before this comment's end 
 | 
			
		||||
         )*
 | 
			
		||||
           \*/               # the End of this comment
 | 
			
		||||
           |[ \t\r\n]+       # whitespaces: space, horicontal tab, lf, cr
 | 
			
		||||
        )+
 | 
			
		||||
      )mx
 | 
			
		||||
 | 
			
		||||
      UNPARSED = Object.new
 | 
			
		||||
 | 
			
		||||
      # Creates a new JSON::Pure::Parser instance for the string _source_.
 | 
			
		||||
      #
 | 
			
		||||
      # It will be configured by the _opts_ hash. _opts_ can have the following
 | 
			
		||||
      # keys:
 | 
			
		||||
      # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
 | 
			
		||||
      #   structures. Disable depth checking with :max_nesting => false|nil|0,
 | 
			
		||||
      #   it defaults to 19.
 | 
			
		||||
      # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
 | 
			
		||||
      #   defiance of RFC 4627 to be parsed by the Parser. This option defaults
 | 
			
		||||
      #   to false.
 | 
			
		||||
      # * *create_additions*: If set to false, the Parser doesn't create
 | 
			
		||||
      #   additions even if a matchin class and create_id was found. This option
 | 
			
		||||
      #   defaults to true.
 | 
			
		||||
      def initialize(source, opts = {})
 | 
			
		||||
        super
 | 
			
		||||
        if !opts.key?(:max_nesting) # defaults to 19
 | 
			
		||||
          @max_nesting = 19
 | 
			
		||||
        elsif opts[:max_nesting]
 | 
			
		||||
          @max_nesting = opts[:max_nesting]
 | 
			
		||||
        else
 | 
			
		||||
          @max_nesting = 0
 | 
			
		||||
        end
 | 
			
		||||
        @allow_nan = !!opts[:allow_nan]
 | 
			
		||||
        ca = true
 | 
			
		||||
        ca = opts[:create_additions] if opts.key?(:create_additions)
 | 
			
		||||
        @create_id = ca ? JSON.create_id : nil
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      alias source string
 | 
			
		||||
 | 
			
		||||
      # Parses the current JSON string _source_ and returns the complete data
 | 
			
		||||
      # structure as a result.
 | 
			
		||||
      def parse
 | 
			
		||||
        reset
 | 
			
		||||
        obj = nil
 | 
			
		||||
        until eos?
 | 
			
		||||
          case
 | 
			
		||||
          when scan(OBJECT_OPEN)
 | 
			
		||||
            obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
 | 
			
		||||
            @current_nesting = 1
 | 
			
		||||
            obj = parse_object
 | 
			
		||||
          when scan(ARRAY_OPEN)
 | 
			
		||||
            obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
 | 
			
		||||
            @current_nesting = 1
 | 
			
		||||
            obj = parse_array
 | 
			
		||||
          when skip(IGNORE)
 | 
			
		||||
            ;
 | 
			
		||||
          else
 | 
			
		||||
            raise ParserError, "source '#{peek(20)}' not in JSON!"
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
        obj or raise ParserError, "source did not contain any JSON!"
 | 
			
		||||
        obj
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      private
 | 
			
		||||
 | 
			
		||||
      # Unescape characters in strings.
 | 
			
		||||
      UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
 | 
			
		||||
      UNESCAPE_MAP.update({
 | 
			
		||||
        ?"  => '"',
 | 
			
		||||
        ?\\ => '\\',
 | 
			
		||||
        ?/  => '/',
 | 
			
		||||
        ?b  => "\b",
 | 
			
		||||
        ?f  => "\f",
 | 
			
		||||
        ?n  => "\n",
 | 
			
		||||
        ?r  => "\r",
 | 
			
		||||
        ?t  => "\t",
 | 
			
		||||
        ?u  => nil, 
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      def parse_string
 | 
			
		||||
        if scan(STRING)
 | 
			
		||||
          return '' if self[1].empty?
 | 
			
		||||
          self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do |c|
 | 
			
		||||
            if u = UNESCAPE_MAP[c[1]]
 | 
			
		||||
              u
 | 
			
		||||
            else # \uXXXX
 | 
			
		||||
              bytes = ''
 | 
			
		||||
              i = 0
 | 
			
		||||
              while c[6 * i] == ?\\ && c[6 * i + 1] == ?u 
 | 
			
		||||
                bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
 | 
			
		||||
                i += 1
 | 
			
		||||
              end
 | 
			
		||||
              JSON::UTF16toUTF8.iconv(bytes)
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        else
 | 
			
		||||
          UNPARSED
 | 
			
		||||
        end
 | 
			
		||||
      rescue Iconv::Failure => e
 | 
			
		||||
        raise GeneratorError, "Caught #{e.class}: #{e}"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def parse_value
 | 
			
		||||
        case
 | 
			
		||||
        when scan(FLOAT)
 | 
			
		||||
          Float(self[1])
 | 
			
		||||
        when scan(INTEGER)
 | 
			
		||||
          Integer(self[1])
 | 
			
		||||
        when scan(TRUE)
 | 
			
		||||
          true
 | 
			
		||||
        when scan(FALSE)
 | 
			
		||||
          false
 | 
			
		||||
        when scan(NULL)
 | 
			
		||||
          nil
 | 
			
		||||
        when (string = parse_string) != UNPARSED
 | 
			
		||||
          string
 | 
			
		||||
        when scan(ARRAY_OPEN)
 | 
			
		||||
          @current_nesting += 1
 | 
			
		||||
          ary = parse_array
 | 
			
		||||
          @current_nesting -= 1
 | 
			
		||||
          ary
 | 
			
		||||
        when scan(OBJECT_OPEN)
 | 
			
		||||
          @current_nesting += 1
 | 
			
		||||
          obj = parse_object
 | 
			
		||||
          @current_nesting -= 1
 | 
			
		||||
          obj
 | 
			
		||||
        when @allow_nan && scan(NAN)
 | 
			
		||||
          NaN
 | 
			
		||||
        when @allow_nan && scan(INFINITY)
 | 
			
		||||
          Infinity
 | 
			
		||||
        when @allow_nan && scan(MINUS_INFINITY)
 | 
			
		||||
          MinusInfinity
 | 
			
		||||
        else
 | 
			
		||||
          UNPARSED
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def parse_array
 | 
			
		||||
        raise NestingError, "nesting of #@current_nesting is to deep" if
 | 
			
		||||
          @max_nesting.nonzero? && @current_nesting > @max_nesting
 | 
			
		||||
        result = []
 | 
			
		||||
        delim = false
 | 
			
		||||
        until eos?
 | 
			
		||||
          case
 | 
			
		||||
          when (value = parse_value) != UNPARSED
 | 
			
		||||
            delim = false
 | 
			
		||||
            result << value
 | 
			
		||||
            skip(IGNORE)
 | 
			
		||||
            if scan(COLLECTION_DELIMITER)
 | 
			
		||||
              delim = true
 | 
			
		||||
            elsif match?(ARRAY_CLOSE)
 | 
			
		||||
              ;
 | 
			
		||||
            else
 | 
			
		||||
              raise ParserError, "expected ',' or ']' in array at '#{peek(20)}'!"
 | 
			
		||||
            end
 | 
			
		||||
          when scan(ARRAY_CLOSE)
 | 
			
		||||
            if delim
 | 
			
		||||
              raise ParserError, "expected next element in array at '#{peek(20)}'!"
 | 
			
		||||
            end
 | 
			
		||||
            break
 | 
			
		||||
          when skip(IGNORE)
 | 
			
		||||
            ;
 | 
			
		||||
          else
 | 
			
		||||
            raise ParserError, "unexpected token in array at '#{peek(20)}'!"
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
        result
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def parse_object
 | 
			
		||||
        raise NestingError, "nesting of #@current_nesting is to deep" if
 | 
			
		||||
          @max_nesting.nonzero? && @current_nesting > @max_nesting
 | 
			
		||||
        result = {}
 | 
			
		||||
        delim = false
 | 
			
		||||
        until eos?
 | 
			
		||||
          case
 | 
			
		||||
          when (string = parse_string) != UNPARSED
 | 
			
		||||
            skip(IGNORE)
 | 
			
		||||
            unless scan(PAIR_DELIMITER)
 | 
			
		||||
              raise ParserError, "expected ':' in object at '#{peek(20)}'!"
 | 
			
		||||
            end
 | 
			
		||||
            skip(IGNORE)
 | 
			
		||||
            unless (value = parse_value).equal? UNPARSED
 | 
			
		||||
              result[string] = value
 | 
			
		||||
              delim = false
 | 
			
		||||
              skip(IGNORE)
 | 
			
		||||
              if scan(COLLECTION_DELIMITER)
 | 
			
		||||
                delim = true
 | 
			
		||||
              elsif match?(OBJECT_CLOSE)
 | 
			
		||||
                ;
 | 
			
		||||
              else
 | 
			
		||||
                raise ParserError, "expected ',' or '}' in object at '#{peek(20)}'!"
 | 
			
		||||
              end
 | 
			
		||||
            else
 | 
			
		||||
              raise ParserError, "expected value in object at '#{peek(20)}'!"
 | 
			
		||||
            end
 | 
			
		||||
          when scan(OBJECT_CLOSE)
 | 
			
		||||
            if delim
 | 
			
		||||
              raise ParserError, "expected next name, value pair in object at '#{peek(20)}'!"
 | 
			
		||||
            end
 | 
			
		||||
            if @create_id and klassname = result[@create_id]
 | 
			
		||||
              klass = JSON.deep_const_get klassname
 | 
			
		||||
              break unless klass and klass.json_creatable?
 | 
			
		||||
              result = klass.json_create(result)
 | 
			
		||||
            end
 | 
			
		||||
            break
 | 
			
		||||
          when skip(IGNORE)
 | 
			
		||||
            ;
 | 
			
		||||
          else
 | 
			
		||||
            raise ParserError, "unexpected token in object at '#{peek(20)}'!"
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
        result
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										9
									
								
								ext/json/lib/json/version.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								ext/json/lib/json/version.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
module JSON
 | 
			
		||||
  # JSON version
 | 
			
		||||
  VERSION         = '1.1.2'
 | 
			
		||||
  VERSION_ARRAY   = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
 | 
			
		||||
  VERSION_MAJOR   = VERSION_ARRAY[0] # :nodoc:
 | 
			
		||||
  VERSION_MINOR   = VERSION_ARRAY[1] # :nodoc:
 | 
			
		||||
  VERSION_BUILD   = VERSION_ARRAY[2] # :nodoc:
 | 
			
		||||
  VARIANT_BINARY  = false
 | 
			
		||||
end
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue