summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFlorian Frank <flori@ping.de>2011-07-27 02:46:10 +0200
committerFlorian Frank <flori@ping.de>2011-07-31 00:55:16 +0200
commit9d0b1ca629f6f5bc558a4b3f887f0f8cf154fe78 (patch)
treebdfcebfd65e40f591514515bad3106ad1dadcf92 /lib
parent9320a2a18a4d09f8e8a83129db793057968928b1 (diff)
downloadjson-9d0b1ca629f6f5bc558a4b3f887f0f8cf154fe78.tar.gz
Implement quirks_mode
This allows parsing of primitive values
Diffstat (limited to 'lib')
-rw-r--r--lib/json/pure/parser.rb142
1 files changed, 87 insertions, 55 deletions
diff --git a/lib/json/pure/parser.rb b/lib/json/pure/parser.rb
index d612018..5ef1b78 100644
--- a/lib/json/pure/parser.rb
+++ b/lib/json/pure/parser.rb
@@ -70,40 +70,8 @@ module JSON
# * *array_class*: Defaults to Array
def initialize(source, opts = {})
opts ||= {}
- if defined?(::Encoding)
- if source.encoding == ::Encoding::ASCII_8BIT
- b = source[0, 4].bytes.to_a
- source = case
- when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
- source.dup.force_encoding(::Encoding::UTF_32BE).encode!(::Encoding::UTF_8)
- when b.size >= 4 && b[0] == 0 && b[2] == 0
- source.dup.force_encoding(::Encoding::UTF_16BE).encode!(::Encoding::UTF_8)
- when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
- source.dup.force_encoding(::Encoding::UTF_32LE).encode!(::Encoding::UTF_8)
-
- when b.size >= 4 && b[1] == 0 && b[3] == 0
- source.dup.force_encoding(::Encoding::UTF_16LE).encode!(::Encoding::UTF_8)
- else
- source.dup
- end
- else
- source = source.encode(::Encoding::UTF_8)
- end
- source.force_encoding(::Encoding::ASCII_8BIT)
- else
- b = source
- source = case
- when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
- JSON.iconv('utf-8', 'utf-32be', b)
- when b.size >= 4 && b[0] == 0 && b[2] == 0
- JSON.iconv('utf-8', 'utf-16be', b)
- when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
- JSON.iconv('utf-8', 'utf-32le', b)
- when b.size >= 4 && b[1] == 0 && b[3] == 0
- JSON.iconv('utf-8', 'utf-16le', b)
- else
- b
- end
+ unless @quirks_mode = opts[:quirks_mode]
+ source = determine_encoding source
end
super source
if !opts.key?(:max_nesting) # defaults to 19
@@ -113,44 +81,108 @@ module JSON
else
@max_nesting = 0
end
- @allow_nan = !!opts[:allow_nan]
- @symbolize_names = !!opts[:symbolize_names]
- @create_additions = opts.key?(:create_additions) ? !!opts[:create_additions] : true
- @create_id = opts[:create_id] || JSON.create_id
- @object_class = opts[:object_class] || Hash
- @array_class = opts[:array_class] || Array
- @match_string = opts[:match_string]
+ @allow_nan = !!opts[:allow_nan]
+ @symbolize_names = !!opts[:symbolize_names]
+ if opts.key?(:create_additions)
+ @create_additions = !!opts[:create_additions]
+ else
+ @create_additions = true
+ end
+ @create_id = @create_additions ? JSON.create_id : nil
+ @object_class = opts[:object_class] || Hash
+ @array_class = opts[:array_class] || Array
+ @match_string = opts[:match_string]
end
alias source string
+ def quirks_mode?
+ !!@quirks_mode
+ end
+
+ def reset
+ super
+ @current_nesting = 0
+ end
+
# 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)
- ;
+ if @quirks_mode
+ while !eos? && skip(IGNORE)
+ end
+ if eos?
+ raise ParserError, "source did not contain any JSON!"
else
- raise ParserError, "source '#{peek(20)}' not in JSON!"
+ obj = parse_value
+ obj == UNPARSED and raise ParserError, "source did not contain any JSON!"
end
+ else
+ 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!"
end
- obj or raise ParserError, "source did not contain any JSON!"
obj
end
private
+ def determine_encoding(source)
+ if defined?(::Encoding)
+ if source.encoding == ::Encoding::ASCII_8BIT
+ b = source[0, 4].bytes.to_a
+ source =
+ case
+ when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
+ source.dup.force_encoding(::Encoding::UTF_32BE).encode!(::Encoding::UTF_8)
+ when b.size >= 4 && b[0] == 0 && b[2] == 0
+ source.dup.force_encoding(::Encoding::UTF_16BE).encode!(::Encoding::UTF_8)
+ when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
+ source.dup.force_encoding(::Encoding::UTF_32LE).encode!(::Encoding::UTF_8)
+ when b.size >= 4 && b[1] == 0 && b[3] == 0
+ source.dup.force_encoding(::Encoding::UTF_16LE).encode!(::Encoding::UTF_8)
+ else
+ source.dup
+ end
+ else
+ source = source.encode(::Encoding::UTF_8)
+ end
+ source.force_encoding(::Encoding::ASCII_8BIT)
+ else
+ b = source
+ source =
+ case
+ when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
+ JSON.iconv('utf-8', 'utf-32be', b)
+ when b.size >= 4 && b[0] == 0 && b[2] == 0
+ JSON.iconv('utf-8', 'utf-16be', b)
+ when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
+ JSON.iconv('utf-8', 'utf-32le', b)
+ when b.size >= 4 && b[1] == 0 && b[3] == 0
+ JSON.iconv('utf-8', 'utf-16le', b)
+ else
+ b
+ end
+ end
+ source
+ end
+
# Unescape characters in strings.
UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
UNESCAPE_MAP.update({