json 1.1.5-x86-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of json might be problematic. Click here for more details.
- data/CHANGES +106 -0
- data/GPL +340 -0
- data/README +78 -0
- data/RUBY +58 -0
- data/Rakefile +268 -0
- data/TODO +1 -0
- data/VERSION +1 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkComparison.log +52 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty-autocorrelation.dat +900 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty.dat +901 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt.log +261 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure.log +262 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails.log +82 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkComparison.log +34 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser-autocorrelation.dat +900 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser.dat +901 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt.log +81 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure.log +82 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails.log +82 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser-autocorrelation.dat +1000 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser.dat +1001 -0
- data/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML.log +82 -0
- data/benchmarks/generator_benchmark.rb +165 -0
- data/benchmarks/parser_benchmark.rb +197 -0
- data/bin/edit_json.rb +9 -0
- data/bin/prettify_json.rb +75 -0
- data/data/example.json +1 -0
- data/data/index.html +38 -0
- data/data/prototype.js +4184 -0
- data/doc-templates/main.txt +283 -0
- data/ext/json/ext/generator/extconf.rb +11 -0
- data/ext/json/ext/generator/generator.c +919 -0
- data/ext/json/ext/generator/unicode.c +182 -0
- data/ext/json/ext/generator/unicode.h +53 -0
- data/ext/json/ext/parser/extconf.rb +11 -0
- data/ext/json/ext/parser/parser.c +1829 -0
- data/ext/json/ext/parser/parser.rl +686 -0
- data/ext/json/ext/parser/unicode.c +154 -0
- data/ext/json/ext/parser/unicode.h +58 -0
- data/install.rb +26 -0
- data/lib/json.rb +10 -0
- data/lib/json/Array.xpm +21 -0
- data/lib/json/FalseClass.xpm +21 -0
- data/lib/json/Hash.xpm +21 -0
- data/lib/json/Key.xpm +73 -0
- data/lib/json/NilClass.xpm +21 -0
- data/lib/json/Numeric.xpm +28 -0
- data/lib/json/String.xpm +96 -0
- data/lib/json/TrueClass.xpm +21 -0
- data/lib/json/add/core.rb +135 -0
- data/lib/json/add/rails.rb +58 -0
- data/lib/json/common.rb +354 -0
- data/lib/json/editor.rb +1371 -0
- data/lib/json/ext.rb +15 -0
- data/lib/json/ext/generator.so +0 -0
- data/lib/json/ext/parser.so +0 -0
- data/lib/json/json.xpm +1499 -0
- data/lib/json/pure.rb +77 -0
- data/lib/json/pure/generator.rb +430 -0
- data/lib/json/pure/parser.rb +267 -0
- data/lib/json/version.rb +8 -0
- data/tests/fixtures/fail1.json +1 -0
- data/tests/fixtures/fail10.json +1 -0
- data/tests/fixtures/fail11.json +1 -0
- data/tests/fixtures/fail12.json +1 -0
- data/tests/fixtures/fail13.json +1 -0
- data/tests/fixtures/fail14.json +1 -0
- data/tests/fixtures/fail18.json +1 -0
- data/tests/fixtures/fail19.json +1 -0
- data/tests/fixtures/fail2.json +1 -0
- data/tests/fixtures/fail20.json +1 -0
- data/tests/fixtures/fail21.json +1 -0
- data/tests/fixtures/fail22.json +1 -0
- data/tests/fixtures/fail23.json +1 -0
- data/tests/fixtures/fail24.json +1 -0
- data/tests/fixtures/fail25.json +1 -0
- data/tests/fixtures/fail27.json +2 -0
- data/tests/fixtures/fail28.json +2 -0
- data/tests/fixtures/fail3.json +1 -0
- data/tests/fixtures/fail4.json +1 -0
- data/tests/fixtures/fail5.json +1 -0
- data/tests/fixtures/fail6.json +1 -0
- data/tests/fixtures/fail7.json +1 -0
- data/tests/fixtures/fail8.json +1 -0
- data/tests/fixtures/fail9.json +1 -0
- data/tests/fixtures/pass1.json +56 -0
- data/tests/fixtures/pass15.json +1 -0
- data/tests/fixtures/pass16.json +1 -0
- data/tests/fixtures/pass17.json +1 -0
- data/tests/fixtures/pass2.json +1 -0
- data/tests/fixtures/pass26.json +1 -0
- data/tests/fixtures/pass3.json +6 -0
- data/tests/test_json.rb +312 -0
- data/tests/test_json_addition.rb +164 -0
- data/tests/test_json_fixtures.rb +34 -0
- data/tests/test_json_generate.rb +106 -0
- data/tests/test_json_rails.rb +146 -0
- data/tests/test_json_unicode.rb +62 -0
- data/tools/fuzz.rb +139 -0
- data/tools/server.rb +61 -0
- metadata +200 -0
| @@ -0,0 +1,267 @@ | |
| 1 | 
            +
            require 'strscan'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module JSON
         | 
| 4 | 
            +
              module Pure
         | 
| 5 | 
            +
                # This class implements the JSON parser that is used to parse a JSON string
         | 
| 6 | 
            +
                # into a Ruby data structure.
         | 
| 7 | 
            +
                class Parser < StringScanner
         | 
| 8 | 
            +
                  STRING                = /" ((?:[^\x0-\x1f"\\] |
         | 
| 9 | 
            +
                                              \\["\\\/bfnrt] |
         | 
| 10 | 
            +
                                              \\u[0-9a-fA-F]{4} |
         | 
| 11 | 
            +
                                              \\[\x20-\xff])*)
         | 
| 12 | 
            +
                                          "/nx
         | 
| 13 | 
            +
                  INTEGER               = /(-?0|-?[1-9]\d*)/
         | 
| 14 | 
            +
                  FLOAT                 = /(-?
         | 
| 15 | 
            +
                                            (?:0|[1-9]\d*)
         | 
| 16 | 
            +
                                            (?:
         | 
| 17 | 
            +
                                              \.\d+(?i:e[+-]?\d+) |
         | 
| 18 | 
            +
                                              \.\d+ |
         | 
| 19 | 
            +
                                              (?i:e[+-]?\d+)
         | 
| 20 | 
            +
                                            )
         | 
| 21 | 
            +
                                            )/x
         | 
| 22 | 
            +
                  NAN                   = /NaN/
         | 
| 23 | 
            +
                  INFINITY              = /Infinity/
         | 
| 24 | 
            +
                  MINUS_INFINITY        = /-Infinity/
         | 
| 25 | 
            +
                  OBJECT_OPEN           = /\{/
         | 
| 26 | 
            +
                  OBJECT_CLOSE          = /\}/
         | 
| 27 | 
            +
                  ARRAY_OPEN            = /\[/
         | 
| 28 | 
            +
                  ARRAY_CLOSE           = /\]/
         | 
| 29 | 
            +
                  PAIR_DELIMITER        = /:/
         | 
| 30 | 
            +
                  COLLECTION_DELIMITER  = /,/
         | 
| 31 | 
            +
                  TRUE                  = /true/
         | 
| 32 | 
            +
                  FALSE                 = /false/
         | 
| 33 | 
            +
                  NULL                  = /null/
         | 
| 34 | 
            +
                  IGNORE                = %r(
         | 
| 35 | 
            +
                    (?:
         | 
| 36 | 
            +
                     //[^\n\r]*[\n\r]| # line comments
         | 
| 37 | 
            +
                     /\*               # c-style comments
         | 
| 38 | 
            +
                     (?:
         | 
| 39 | 
            +
                      [^*/]|        # normal chars
         | 
| 40 | 
            +
                      /[^*]|        # slashes that do not start a nested comment
         | 
| 41 | 
            +
                      \*[^/]|       # asterisks that do not end this comment
         | 
| 42 | 
            +
                      /(?=\*/)      # single slash before this comment's end 
         | 
| 43 | 
            +
                     )*
         | 
| 44 | 
            +
                       \*/               # the End of this comment
         | 
| 45 | 
            +
                       |[ \t\r\n]+       # whitespaces: space, horicontal tab, lf, cr
         | 
| 46 | 
            +
                    )+
         | 
| 47 | 
            +
                  )mx
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  UNPARSED = Object.new
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  # Creates a new JSON::Pure::Parser instance for the string _source_.
         | 
| 52 | 
            +
                  #
         | 
| 53 | 
            +
                  # It will be configured by the _opts_ hash. _opts_ can have the following
         | 
| 54 | 
            +
                  # keys:
         | 
| 55 | 
            +
                  # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
         | 
| 56 | 
            +
                  #   structures. Disable depth checking with :max_nesting => false|nil|0,
         | 
| 57 | 
            +
                  #   it defaults to 19.
         | 
| 58 | 
            +
                  # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
         | 
| 59 | 
            +
                  #   defiance of RFC 4627 to be parsed by the Parser. This option defaults
         | 
| 60 | 
            +
                  #   to false.
         | 
| 61 | 
            +
                  # * *create_additions*: If set to false, the Parser doesn't create
         | 
| 62 | 
            +
                  #   additions even if a matchin class and create_id was found. This option
         | 
| 63 | 
            +
                  #   defaults to true.
         | 
| 64 | 
            +
                  # * *object_class*: Defaults to Hash
         | 
| 65 | 
            +
                  # * *array_class*: Defaults to Array
         | 
| 66 | 
            +
                  def initialize(source, opts = {})
         | 
| 67 | 
            +
                    super
         | 
| 68 | 
            +
                    if !opts.key?(:max_nesting) # defaults to 19
         | 
| 69 | 
            +
                      @max_nesting = 19
         | 
| 70 | 
            +
                    elsif opts[:max_nesting]
         | 
| 71 | 
            +
                      @max_nesting = opts[:max_nesting]
         | 
| 72 | 
            +
                    else
         | 
| 73 | 
            +
                      @max_nesting = 0
         | 
| 74 | 
            +
                    end
         | 
| 75 | 
            +
                    @allow_nan = !!opts[:allow_nan]
         | 
| 76 | 
            +
                    ca = true
         | 
| 77 | 
            +
                    ca = opts[:create_additions] if opts.key?(:create_additions)
         | 
| 78 | 
            +
                    @create_id = ca ? JSON.create_id : nil
         | 
| 79 | 
            +
                    @object_class = opts[:object_class] || Hash
         | 
| 80 | 
            +
                    @array_class = opts[:array_class] || Array
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                  alias source string
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  # Parses the current JSON string _source_ and returns the complete data
         | 
| 86 | 
            +
                  # structure as a result.
         | 
| 87 | 
            +
                  def parse
         | 
| 88 | 
            +
                    reset
         | 
| 89 | 
            +
                    obj = nil
         | 
| 90 | 
            +
                    until eos?
         | 
| 91 | 
            +
                      case
         | 
| 92 | 
            +
                      when scan(OBJECT_OPEN)
         | 
| 93 | 
            +
                        obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
         | 
| 94 | 
            +
                        @current_nesting = 1
         | 
| 95 | 
            +
                        obj = parse_object
         | 
| 96 | 
            +
                      when scan(ARRAY_OPEN)
         | 
| 97 | 
            +
                        obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
         | 
| 98 | 
            +
                        @current_nesting = 1
         | 
| 99 | 
            +
                        obj = parse_array
         | 
| 100 | 
            +
                      when skip(IGNORE)
         | 
| 101 | 
            +
                        ;
         | 
| 102 | 
            +
                      else
         | 
| 103 | 
            +
                        raise ParserError, "source '#{peek(20)}' not in JSON!"
         | 
| 104 | 
            +
                      end
         | 
| 105 | 
            +
                    end
         | 
| 106 | 
            +
                    obj or raise ParserError, "source did not contain any JSON!"
         | 
| 107 | 
            +
                    obj
         | 
| 108 | 
            +
                  end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                  private
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                  # Unescape characters in strings.
         | 
| 113 | 
            +
                  UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
         | 
| 114 | 
            +
                  UNESCAPE_MAP.update({
         | 
| 115 | 
            +
                    ?"  => '"',
         | 
| 116 | 
            +
                    ?\\ => '\\',
         | 
| 117 | 
            +
                    ?/  => '/',
         | 
| 118 | 
            +
                    ?b  => "\b",
         | 
| 119 | 
            +
                    ?f  => "\f",
         | 
| 120 | 
            +
                    ?n  => "\n",
         | 
| 121 | 
            +
                    ?r  => "\r",
         | 
| 122 | 
            +
                    ?t  => "\t",
         | 
| 123 | 
            +
                    ?u  => nil, 
         | 
| 124 | 
            +
                  })
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                  def parse_string
         | 
| 127 | 
            +
                    if scan(STRING)
         | 
| 128 | 
            +
                      return '' if self[1].empty?
         | 
| 129 | 
            +
                      string = self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do |c|
         | 
| 130 | 
            +
                        if u = UNESCAPE_MAP[$&[1]]
         | 
| 131 | 
            +
                          u
         | 
| 132 | 
            +
                        else # \uXXXX
         | 
| 133 | 
            +
                          bytes = ''
         | 
| 134 | 
            +
                          i = 0
         | 
| 135 | 
            +
                          while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
         | 
| 136 | 
            +
                            bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
         | 
| 137 | 
            +
                            i += 1
         | 
| 138 | 
            +
                          end
         | 
| 139 | 
            +
                          JSON::UTF16toUTF8.iconv(bytes)
         | 
| 140 | 
            +
                        end
         | 
| 141 | 
            +
                      end
         | 
| 142 | 
            +
                      if string.respond_to?(:force_encoding)
         | 
| 143 | 
            +
                        string.force_encoding(Encoding::UTF_8)
         | 
| 144 | 
            +
                      end
         | 
| 145 | 
            +
                      string
         | 
| 146 | 
            +
                    else
         | 
| 147 | 
            +
                      UNPARSED
         | 
| 148 | 
            +
                    end
         | 
| 149 | 
            +
                  rescue Iconv::Failure => e
         | 
| 150 | 
            +
                    raise GeneratorError, "Caught #{e.class}: #{e}"
         | 
| 151 | 
            +
                  end
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                  def parse_value
         | 
| 154 | 
            +
                    case
         | 
| 155 | 
            +
                    when scan(FLOAT)
         | 
| 156 | 
            +
                      Float(self[1])
         | 
| 157 | 
            +
                    when scan(INTEGER)
         | 
| 158 | 
            +
                      Integer(self[1])
         | 
| 159 | 
            +
                    when scan(TRUE)
         | 
| 160 | 
            +
                      true
         | 
| 161 | 
            +
                    when scan(FALSE)
         | 
| 162 | 
            +
                      false
         | 
| 163 | 
            +
                    when scan(NULL)
         | 
| 164 | 
            +
                      nil
         | 
| 165 | 
            +
                    when (string = parse_string) != UNPARSED
         | 
| 166 | 
            +
                      string
         | 
| 167 | 
            +
                    when scan(ARRAY_OPEN)
         | 
| 168 | 
            +
                      @current_nesting += 1
         | 
| 169 | 
            +
                      ary = parse_array
         | 
| 170 | 
            +
                      @current_nesting -= 1
         | 
| 171 | 
            +
                      ary
         | 
| 172 | 
            +
                    when scan(OBJECT_OPEN)
         | 
| 173 | 
            +
                      @current_nesting += 1
         | 
| 174 | 
            +
                      obj = parse_object
         | 
| 175 | 
            +
                      @current_nesting -= 1
         | 
| 176 | 
            +
                      obj
         | 
| 177 | 
            +
                    when @allow_nan && scan(NAN)
         | 
| 178 | 
            +
                      NaN
         | 
| 179 | 
            +
                    when @allow_nan && scan(INFINITY)
         | 
| 180 | 
            +
                      Infinity
         | 
| 181 | 
            +
                    when @allow_nan && scan(MINUS_INFINITY)
         | 
| 182 | 
            +
                      MinusInfinity
         | 
| 183 | 
            +
                    else
         | 
| 184 | 
            +
                      UNPARSED
         | 
| 185 | 
            +
                    end
         | 
| 186 | 
            +
                  end
         | 
| 187 | 
            +
             | 
| 188 | 
            +
                  def parse_array
         | 
| 189 | 
            +
                    raise NestingError, "nesting of #@current_nesting is to deep" if
         | 
| 190 | 
            +
                      @max_nesting.nonzero? && @current_nesting > @max_nesting
         | 
| 191 | 
            +
                    result = @array_class.new
         | 
| 192 | 
            +
                    delim = false
         | 
| 193 | 
            +
                    until eos?
         | 
| 194 | 
            +
                      case
         | 
| 195 | 
            +
                      when (value = parse_value) != UNPARSED
         | 
| 196 | 
            +
                        delim = false
         | 
| 197 | 
            +
                        result << value
         | 
| 198 | 
            +
                        skip(IGNORE)
         | 
| 199 | 
            +
                        if scan(COLLECTION_DELIMITER)
         | 
| 200 | 
            +
                          delim = true
         | 
| 201 | 
            +
                        elsif match?(ARRAY_CLOSE)
         | 
| 202 | 
            +
                          ;
         | 
| 203 | 
            +
                        else
         | 
| 204 | 
            +
                          raise ParserError, "expected ',' or ']' in array at '#{peek(20)}'!"
         | 
| 205 | 
            +
                        end
         | 
| 206 | 
            +
                      when scan(ARRAY_CLOSE)
         | 
| 207 | 
            +
                        if delim
         | 
| 208 | 
            +
                          raise ParserError, "expected next element in array at '#{peek(20)}'!"
         | 
| 209 | 
            +
                        end
         | 
| 210 | 
            +
                        break
         | 
| 211 | 
            +
                      when skip(IGNORE)
         | 
| 212 | 
            +
                        ;
         | 
| 213 | 
            +
                      else
         | 
| 214 | 
            +
                        raise ParserError, "unexpected token in array at '#{peek(20)}'!"
         | 
| 215 | 
            +
                      end
         | 
| 216 | 
            +
                    end
         | 
| 217 | 
            +
                    result
         | 
| 218 | 
            +
                  end
         | 
| 219 | 
            +
             | 
| 220 | 
            +
                  def parse_object
         | 
| 221 | 
            +
                    raise NestingError, "nesting of #@current_nesting is to deep" if
         | 
| 222 | 
            +
                      @max_nesting.nonzero? && @current_nesting > @max_nesting
         | 
| 223 | 
            +
                    result = @object_class.new
         | 
| 224 | 
            +
                    delim = false
         | 
| 225 | 
            +
                    until eos?
         | 
| 226 | 
            +
                      case
         | 
| 227 | 
            +
                      when (string = parse_string) != UNPARSED
         | 
| 228 | 
            +
                        skip(IGNORE)
         | 
| 229 | 
            +
                        unless scan(PAIR_DELIMITER)
         | 
| 230 | 
            +
                          raise ParserError, "expected ':' in object at '#{peek(20)}'!"
         | 
| 231 | 
            +
                        end
         | 
| 232 | 
            +
                        skip(IGNORE)
         | 
| 233 | 
            +
                        unless (value = parse_value).equal? UNPARSED
         | 
| 234 | 
            +
                          result[string] = value
         | 
| 235 | 
            +
                          delim = false
         | 
| 236 | 
            +
                          skip(IGNORE)
         | 
| 237 | 
            +
                          if scan(COLLECTION_DELIMITER)
         | 
| 238 | 
            +
                            delim = true
         | 
| 239 | 
            +
                          elsif match?(OBJECT_CLOSE)
         | 
| 240 | 
            +
                            ;
         | 
| 241 | 
            +
                          else
         | 
| 242 | 
            +
                            raise ParserError, "expected ',' or '}' in object at '#{peek(20)}'!"
         | 
| 243 | 
            +
                          end
         | 
| 244 | 
            +
                        else
         | 
| 245 | 
            +
                          raise ParserError, "expected value in object at '#{peek(20)}'!"
         | 
| 246 | 
            +
                        end
         | 
| 247 | 
            +
                      when scan(OBJECT_CLOSE)
         | 
| 248 | 
            +
                        if delim
         | 
| 249 | 
            +
                          raise ParserError, "expected next name, value pair in object at '#{peek(20)}'!"
         | 
| 250 | 
            +
                        end
         | 
| 251 | 
            +
                        if @create_id and klassname = result[@create_id]
         | 
| 252 | 
            +
                          klass = JSON.deep_const_get klassname
         | 
| 253 | 
            +
                          break unless klass and klass.json_creatable?
         | 
| 254 | 
            +
                          result = klass.json_create(result)
         | 
| 255 | 
            +
                        end
         | 
| 256 | 
            +
                        break
         | 
| 257 | 
            +
                      when skip(IGNORE)
         | 
| 258 | 
            +
                        ;
         | 
| 259 | 
            +
                      else
         | 
| 260 | 
            +
                        raise ParserError, "unexpected token in object at '#{peek(20)}'!"
         | 
| 261 | 
            +
                      end
         | 
| 262 | 
            +
                    end
         | 
| 263 | 
            +
                    result
         | 
| 264 | 
            +
                  end
         | 
| 265 | 
            +
                end
         | 
| 266 | 
            +
              end
         | 
| 267 | 
            +
            end
         | 
    
        data/lib/json/version.rb
    ADDED
    
    
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            "A JSON payload should be an object or array, not a string."
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            {"Extra value after close": true} "misplaced quoted value"
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            {"Illegal expression": 1 + 2}
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            {"Illegal invocation": alert()}
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            {"Numbers cannot have leading zeroes": 013}
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            {"Numbers cannot be hex": 0x14}
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            [[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            {"Missing colon" null}
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            ["Unclosed array"
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            {"Double colon":: null}
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            {"Comma instead of colon", null}
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            ["Colon instead of comma": false]
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            ["Bad value", truth]
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            ['single quote']
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            ["tab	character	in	string	"]
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            {unquoted_key: "keys must be quoted"}
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            ["extra comma",]
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            ["double extra comma",,]
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            [   , "<-- missing value"]
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            ["Comma after the close"],
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            ["Extra close"]]
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            {"Extra comma": true,}
         | 
| @@ -0,0 +1,56 @@ | |
| 1 | 
            +
            [
         | 
| 2 | 
            +
                "JSON Test Pattern pass1",
         | 
| 3 | 
            +
                {"object with 1 member":["array with 1 element"]},
         | 
| 4 | 
            +
                {},
         | 
| 5 | 
            +
                [],
         | 
| 6 | 
            +
                -42,
         | 
| 7 | 
            +
                true,
         | 
| 8 | 
            +
                false,
         | 
| 9 | 
            +
                null,
         | 
| 10 | 
            +
                {
         | 
| 11 | 
            +
                    "integer": 1234567890,
         | 
| 12 | 
            +
                    "real": -9876.543210,
         | 
| 13 | 
            +
                    "e": 0.123456789e-12,
         | 
| 14 | 
            +
                    "E": 1.234567890E+34,
         | 
| 15 | 
            +
                    "":  23456789012E666,
         | 
| 16 | 
            +
                    "zero": 0,
         | 
| 17 | 
            +
                    "one": 1,
         | 
| 18 | 
            +
                    "space": " ",
         | 
| 19 | 
            +
                    "quote": "\"",
         | 
| 20 | 
            +
                    "backslash": "\\",
         | 
| 21 | 
            +
                    "controls": "\b\f\n\r\t",
         | 
| 22 | 
            +
                    "slash": "/ & \/",
         | 
| 23 | 
            +
                    "alpha": "abcdefghijklmnopqrstuvwyz",
         | 
| 24 | 
            +
                    "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
         | 
| 25 | 
            +
                    "digit": "0123456789",
         | 
| 26 | 
            +
                    "special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
         | 
| 27 | 
            +
                    "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
         | 
| 28 | 
            +
                    "true": true,
         | 
| 29 | 
            +
                    "false": false,
         | 
| 30 | 
            +
                    "null": null,
         | 
| 31 | 
            +
                    "array":[  ],
         | 
| 32 | 
            +
                    "object":{  },
         | 
| 33 | 
            +
                    "address": "50 St. James Street",
         | 
| 34 | 
            +
                    "url": "http://www.JSON.org/",
         | 
| 35 | 
            +
                    "comment": "// /* <!-- --",
         | 
| 36 | 
            +
                    "# -- --> */": " ",
         | 
| 37 | 
            +
                    " s p a c e d " :[1,2 , 3
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            ,
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            4 , 5        ,          6           ,7        ],
         | 
| 42 | 
            +
                    "compact": [1,2,3,4,5,6,7],
         | 
| 43 | 
            +
                    "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
         | 
| 44 | 
            +
                    "quotes": "" \u0022 %22 0x22 034 "",
         | 
| 45 | 
            +
                    "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
         | 
| 46 | 
            +
            : "A key can be any string"
         | 
| 47 | 
            +
                },
         | 
| 48 | 
            +
                0.5 ,98.6
         | 
| 49 | 
            +
            ,
         | 
| 50 | 
            +
            99.44
         | 
| 51 | 
            +
            ,
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            1066
         | 
| 54 | 
            +
             | 
| 55 | 
            +
             | 
| 56 | 
            +
            ,"rosebud"]
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            ["Illegal backslash escape: \x15"]
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            ["Illegal backslash escape: \'"]
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            ["Illegal backslash escape: \017"]
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            [[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            ["tab\   character\   in\  string\  "]
         | 
    
        data/tests/test_json.rb
    ADDED
    
    | @@ -0,0 +1,312 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
            # -*- coding: utf-8 -*-
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require 'test/unit'
         | 
| 5 | 
            +
            case ENV['JSON']
         | 
| 6 | 
            +
            when 'pure' then require 'json/pure'
         | 
| 7 | 
            +
            when 'ext'  then require 'json/ext'
         | 
| 8 | 
            +
            else             require 'json'
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
            require 'stringio'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            class TC_JSON < Test::Unit::TestCase
         | 
| 13 | 
            +
              include JSON
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              def setup
         | 
| 16 | 
            +
                @ary = [1, "foo", 3.14, 4711.0, 2.718, nil, [1,-2,3], false, true].map do
         | 
| 17 | 
            +
                  |x| [x]
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
                @ary_to_parse = ["1", '"foo"', "3.14", "4711.0", "2.718", "null",
         | 
| 20 | 
            +
                  "[1,-2,3]", "false", "true"].map do
         | 
| 21 | 
            +
                  |x| "[#{x}]"
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
                @hash = {
         | 
| 24 | 
            +
                  'a' => 2,
         | 
| 25 | 
            +
                  'b' => 3.141,
         | 
| 26 | 
            +
                  'c' => 'c',
         | 
| 27 | 
            +
                  'd' => [ 1, "b", 3.14 ],
         | 
| 28 | 
            +
                  'e' => { 'foo' => 'bar' },
         | 
| 29 | 
            +
                  'g' => "\"\0\037",
         | 
| 30 | 
            +
                  'h' => 1000.0,
         | 
| 31 | 
            +
                  'i' => 0.001
         | 
| 32 | 
            +
                }
         | 
| 33 | 
            +
                @json = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},'\
         | 
| 34 | 
            +
                  '"g":"\\"\\u0000\\u001f","h":1.0E3,"i":1.0E-3}'
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              def test_construction
         | 
| 38 | 
            +
                parser = JSON::Parser.new('test')
         | 
| 39 | 
            +
                assert_equal 'test', parser.source
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              def assert_equal_float(expected, is)
         | 
| 43 | 
            +
                assert_in_delta(expected.first, is.first, 1e-2)
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              def test_parse_simple_arrays
         | 
| 47 | 
            +
                assert_equal([], parse('[]'))
         | 
| 48 | 
            +
                assert_equal([], parse('  [  ] '))
         | 
| 49 | 
            +
                assert_equal([nil], parse('[null]'))
         | 
| 50 | 
            +
                assert_equal([false], parse('[false]'))
         | 
| 51 | 
            +
                assert_equal([true], parse('[true]'))
         | 
| 52 | 
            +
                assert_equal([-23], parse('[-23]'))
         | 
| 53 | 
            +
                assert_equal([23], parse('[23]'))
         | 
| 54 | 
            +
                assert_equal([0.23], parse('[0.23]'))
         | 
| 55 | 
            +
                assert_equal([0.0], parse('[0e0]'))
         | 
| 56 | 
            +
                assert_raises(JSON::ParserError) { parse('[+23.2]') }
         | 
| 57 | 
            +
                assert_raises(JSON::ParserError) { parse('[+23]') }
         | 
| 58 | 
            +
                assert_raises(JSON::ParserError) { parse('[.23]') }
         | 
| 59 | 
            +
                assert_raises(JSON::ParserError) { parse('[023]') }
         | 
| 60 | 
            +
                assert_equal_float [3.141], parse('[3.141]')
         | 
| 61 | 
            +
                assert_equal_float [-3.141], parse('[-3.141]')
         | 
| 62 | 
            +
                assert_equal_float [3.141], parse('[3141e-3]')
         | 
| 63 | 
            +
                assert_equal_float [3.141], parse('[3141.1e-3]')
         | 
| 64 | 
            +
                assert_equal_float [3.141], parse('[3141E-3]')
         | 
| 65 | 
            +
                assert_equal_float [3.141], parse('[3141.0E-3]')
         | 
| 66 | 
            +
                assert_equal_float [-3.141], parse('[-3141.0e-3]')
         | 
| 67 | 
            +
                assert_equal_float [-3.141], parse('[-3141e-3]')
         | 
| 68 | 
            +
                assert_raises(ParserError) { parse('[NaN]') }
         | 
| 69 | 
            +
                assert parse('[NaN]', :allow_nan => true).first.nan?
         | 
| 70 | 
            +
                assert_raises(ParserError) { parse('[Infinity]') }
         | 
| 71 | 
            +
                assert_equal [1.0/0], parse('[Infinity]', :allow_nan => true)
         | 
| 72 | 
            +
                assert_raises(ParserError) { parse('[-Infinity]') }
         | 
| 73 | 
            +
                assert_equal [-1.0/0], parse('[-Infinity]', :allow_nan => true)
         | 
| 74 | 
            +
                assert_equal([""], parse('[""]'))
         | 
| 75 | 
            +
                assert_equal(["foobar"], parse('["foobar"]'))
         | 
| 76 | 
            +
                assert_equal([{}], parse('[{}]'))
         | 
| 77 | 
            +
              end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
              def test_parse_simple_objects
         | 
| 80 | 
            +
                assert_equal({}, parse('{}'))
         | 
| 81 | 
            +
                assert_equal({}, parse(' {   }   '))
         | 
| 82 | 
            +
                assert_equal({ "a" => nil }, parse('{   "a"   :  null}'))
         | 
| 83 | 
            +
                assert_equal({ "a" => nil }, parse('{"a":null}'))
         | 
| 84 | 
            +
                assert_equal({ "a" => false }, parse('{   "a"  :  false  }  '))
         | 
| 85 | 
            +
                assert_equal({ "a" => false }, parse('{"a":false}'))
         | 
| 86 | 
            +
                assert_raises(JSON::ParserError) { parse('{false}') }
         | 
| 87 | 
            +
                assert_equal({ "a" => true }, parse('{"a":true}'))
         | 
| 88 | 
            +
                assert_equal({ "a" => true }, parse('  { "a" :  true  }   '))
         | 
| 89 | 
            +
                assert_equal({ "a" => -23 }, parse('  {  "a"  :  -23  }  '))
         | 
| 90 | 
            +
                assert_equal({ "a" => -23 }, parse('  { "a" : -23 } '))
         | 
| 91 | 
            +
                assert_equal({ "a" => 23 }, parse('{"a":23  } '))
         | 
| 92 | 
            +
                assert_equal({ "a" => 23 }, parse('  { "a"  : 23  } '))
         | 
| 93 | 
            +
                assert_equal({ "a" => 0.23 }, parse(' { "a"  :  0.23 }  '))
         | 
| 94 | 
            +
                assert_equal({ "a" => 0.23 }, parse('  {  "a"  :  0.23  }  '))
         | 
| 95 | 
            +
              end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
              begin
         | 
| 98 | 
            +
                require 'permutation'
         | 
| 99 | 
            +
                def test_parse_more_complex_arrays
         | 
| 100 | 
            +
                  a = [ nil, false, true, "foßbar", [ "n€st€d", true ], { "nested" => true, "n€ßt€ð2" => {} }]
         | 
| 101 | 
            +
                  perms = Permutation.for a
         | 
| 102 | 
            +
                  perms.each do |perm|
         | 
| 103 | 
            +
                    orig_ary = perm.project
         | 
| 104 | 
            +
                    json = pretty_generate(orig_ary)
         | 
| 105 | 
            +
                    assert_equal orig_ary, parse(json)
         | 
| 106 | 
            +
                  end
         | 
| 107 | 
            +
                end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                def test_parse_complex_objects
         | 
| 110 | 
            +
                  a = [ nil, false, true, "foßbar", [ "n€st€d", true ], { "nested" => true, "n€ßt€ð2" => {} }]
         | 
| 111 | 
            +
                  perms = Permutation.for a
         | 
| 112 | 
            +
                  perms.each do |perm|
         | 
| 113 | 
            +
                    s = "a"
         | 
| 114 | 
            +
                    orig_obj = perm.project.inject({}) { |h, x| h[s.dup] = x; s = s.succ; h }
         | 
| 115 | 
            +
                    json = pretty_generate(orig_obj)
         | 
| 116 | 
            +
                    assert_equal orig_obj, parse(json)
         | 
| 117 | 
            +
                  end
         | 
| 118 | 
            +
                end
         | 
| 119 | 
            +
              rescue LoadError
         | 
| 120 | 
            +
                warn "Skipping permutation tests."
         | 
| 121 | 
            +
              end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
              def test_parse_arrays
         | 
| 124 | 
            +
                assert_equal([1,2,3], parse('[1,2,3]'))
         | 
| 125 | 
            +
                assert_equal([1.2,2,3], parse('[1.2,2,3]'))
         | 
| 126 | 
            +
                assert_equal([[],[[],[]]], parse('[[],[[],[]]]'))
         | 
| 127 | 
            +
              end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
              def test_parse_values
         | 
| 130 | 
            +
                assert_equal([""], parse('[""]'))
         | 
| 131 | 
            +
                assert_equal(["\\"], parse('["\\\\"]'))
         | 
| 132 | 
            +
                assert_equal(['"'], parse('["\""]'))
         | 
| 133 | 
            +
                assert_equal(['\\"\\'], parse('["\\\\\\"\\\\"]'))
         | 
| 134 | 
            +
                assert_equal(["\"\b\n\r\t\0\037"],
         | 
| 135 | 
            +
                  parse('["\"\b\n\r\t\u0000\u001f"]'))
         | 
| 136 | 
            +
                for i in 0 ... @ary.size
         | 
| 137 | 
            +
                  assert_equal(@ary[i], parse(@ary_to_parse[i]))
         | 
| 138 | 
            +
                end
         | 
| 139 | 
            +
              end
         | 
| 140 | 
            +
             | 
| 141 | 
            +
              def test_parse_array
         | 
| 142 | 
            +
                assert_equal([], parse('[]'))
         | 
| 143 | 
            +
                assert_equal([], parse('  [  ]  '))
         | 
| 144 | 
            +
                assert_equal([1], parse('[1]'))
         | 
| 145 | 
            +
                assert_equal([1], parse('  [ 1  ]  '))
         | 
| 146 | 
            +
                assert_equal(@ary,
         | 
| 147 | 
            +
                  parse('[[1],["foo"],[3.14],[47.11e+2],[2718.0E-3],[null],[[1,-2,3]]'\
         | 
| 148 | 
            +
                  ',[false],[true]]'))
         | 
| 149 | 
            +
                assert_equal(@ary, parse(%Q{   [   [1] , ["foo"]  ,  [3.14] \t ,  [47.11e+2] 
         | 
| 150 | 
            +
                  , [2718.0E-3 ],\r[ null] , [[1, -2, 3 ]], [false ],[ true]\n ]  }))
         | 
| 151 | 
            +
              end
         | 
| 152 | 
            +
             | 
| 153 | 
            +
              class SubArray < Array; end
         | 
| 154 | 
            +
             | 
| 155 | 
            +
              def test_parse_array_custom_class
         | 
| 156 | 
            +
                res = parse('[]', :array_class => SubArray)
         | 
| 157 | 
            +
                assert_equal([], res)
         | 
| 158 | 
            +
                assert_equal(SubArray, res.class)
         | 
| 159 | 
            +
              end
         | 
| 160 | 
            +
             | 
| 161 | 
            +
              def test_parse_object
         | 
| 162 | 
            +
                assert_equal({}, parse('{}'))
         | 
| 163 | 
            +
                assert_equal({}, parse('  {  }  '))
         | 
| 164 | 
            +
                assert_equal({'foo'=>'bar'}, parse('{"foo":"bar"}'))
         | 
| 165 | 
            +
                assert_equal({'foo'=>'bar'}, parse('    { "foo"  :   "bar"   }   '))
         | 
| 166 | 
            +
              end
         | 
| 167 | 
            +
             | 
| 168 | 
            +
              class SubHash < Hash; end
         | 
| 169 | 
            +
             | 
| 170 | 
            +
              def test_parse_object_custom_class
         | 
| 171 | 
            +
                res = parse('{}', :object_class => SubHash)
         | 
| 172 | 
            +
                assert_equal({}, res)
         | 
| 173 | 
            +
                assert_equal(SubHash, res.class)
         | 
| 174 | 
            +
              end
         | 
| 175 | 
            +
             | 
| 176 | 
            +
              def test_parser_reset
         | 
| 177 | 
            +
                parser = Parser.new(@json)
         | 
| 178 | 
            +
                assert_equal(@hash, parser.parse)
         | 
| 179 | 
            +
                assert_equal(@hash, parser.parse)
         | 
| 180 | 
            +
              end
         | 
| 181 | 
            +
             | 
| 182 | 
            +
              def test_comments
         | 
| 183 | 
            +
                json = <<EOT
         | 
| 184 | 
            +
            {
         | 
| 185 | 
            +
              "key1":"value1", // eol comment
         | 
| 186 | 
            +
              "key2":"value2"  /* multi line
         | 
| 187 | 
            +
                                *  comment */,
         | 
| 188 | 
            +
              "key3":"value3"  /* multi line
         | 
| 189 | 
            +
                                // nested eol comment
         | 
| 190 | 
            +
                                *  comment */
         | 
| 191 | 
            +
            }
         | 
| 192 | 
            +
            EOT
         | 
| 193 | 
            +
                assert_equal(
         | 
| 194 | 
            +
                  { "key1" => "value1", "key2" => "value2", "key3" => "value3" },
         | 
| 195 | 
            +
                  parse(json))
         | 
| 196 | 
            +
                json = <<EOT
         | 
| 197 | 
            +
            {
         | 
| 198 | 
            +
              "key1":"value1"  /* multi line
         | 
| 199 | 
            +
                                // nested eol comment
         | 
| 200 | 
            +
                                /* illegal nested multi line comment */
         | 
| 201 | 
            +
                                *  comment */
         | 
| 202 | 
            +
            }
         | 
| 203 | 
            +
            EOT
         | 
| 204 | 
            +
                assert_raises(ParserError) { parse(json) }
         | 
| 205 | 
            +
                json = <<EOT
         | 
| 206 | 
            +
            {
         | 
| 207 | 
            +
              "key1":"value1"  /* multi line
         | 
| 208 | 
            +
                               // nested eol comment
         | 
| 209 | 
            +
                               closed multi comment */
         | 
| 210 | 
            +
                               and again, throw an Error */
         | 
| 211 | 
            +
            }
         | 
| 212 | 
            +
            EOT
         | 
| 213 | 
            +
                assert_raises(ParserError) { parse(json) }
         | 
| 214 | 
            +
                json = <<EOT
         | 
| 215 | 
            +
            {
         | 
| 216 | 
            +
              "key1":"value1"  /*/*/
         | 
| 217 | 
            +
            }
         | 
| 218 | 
            +
            EOT
         | 
| 219 | 
            +
                assert_equal({ "key1" => "value1" }, parse(json))
         | 
| 220 | 
            +
              end
         | 
| 221 | 
            +
             | 
| 222 | 
            +
              def test_backslash
         | 
| 223 | 
            +
                data = [ '\\.(?i:gif|jpe?g|png)$' ]
         | 
| 224 | 
            +
                json = '["\\\\.(?i:gif|jpe?g|png)$"]'
         | 
| 225 | 
            +
                assert_equal json, JSON.unparse(data)
         | 
| 226 | 
            +
                assert_equal data, JSON.parse(json)
         | 
| 227 | 
            +
                #
         | 
| 228 | 
            +
                data = [ '\\"' ]
         | 
| 229 | 
            +
                json = '["\\\\\""]'
         | 
| 230 | 
            +
                assert_equal json, JSON.unparse(data)
         | 
| 231 | 
            +
                assert_equal data, JSON.parse(json)
         | 
| 232 | 
            +
                #
         | 
| 233 | 
            +
                json = '["\/"]'
         | 
| 234 | 
            +
                data = JSON.parse(json)
         | 
| 235 | 
            +
                assert_equal ['/'], data
         | 
| 236 | 
            +
                assert_equal json, JSON.unparse(data)
         | 
| 237 | 
            +
                #
         | 
| 238 | 
            +
                json = '["\""]'
         | 
| 239 | 
            +
                data = JSON.parse(json)
         | 
| 240 | 
            +
                assert_equal ['"'], data
         | 
| 241 | 
            +
                assert_equal json, JSON.unparse(data)
         | 
| 242 | 
            +
                json = '["\\\'"]'
         | 
| 243 | 
            +
                data = JSON.parse(json)
         | 
| 244 | 
            +
                assert_equal ["'"], data
         | 
| 245 | 
            +
                assert_equal '["\'"]', JSON.unparse(data)
         | 
| 246 | 
            +
              end
         | 
| 247 | 
            +
             | 
| 248 | 
            +
              def test_wrong_inputs
         | 
| 249 | 
            +
                assert_raises(ParserError) { JSON.parse('"foo"') }
         | 
| 250 | 
            +
                assert_raises(ParserError) { JSON.parse('123') }
         | 
| 251 | 
            +
                assert_raises(ParserError) { JSON.parse('[] bla') }
         | 
| 252 | 
            +
                assert_raises(ParserError) { JSON.parse('[] 1') }
         | 
| 253 | 
            +
                assert_raises(ParserError) { JSON.parse('[] []') }
         | 
| 254 | 
            +
                assert_raises(ParserError) { JSON.parse('[] {}') }
         | 
| 255 | 
            +
                assert_raises(ParserError) { JSON.parse('{} []') }
         | 
| 256 | 
            +
                assert_raises(ParserError) { JSON.parse('{} {}') }
         | 
| 257 | 
            +
                assert_raises(ParserError) { JSON.parse('[NULL]') }
         | 
| 258 | 
            +
                assert_raises(ParserError) { JSON.parse('[FALSE]') }
         | 
| 259 | 
            +
                assert_raises(ParserError) { JSON.parse('[TRUE]') }
         | 
| 260 | 
            +
                assert_raises(ParserError) { JSON.parse('[07]    ') }
         | 
| 261 | 
            +
                assert_raises(ParserError) { JSON.parse('[0a]') }
         | 
| 262 | 
            +
                assert_raises(ParserError) { JSON.parse('[1.]') }
         | 
| 263 | 
            +
                assert_raises(ParserError) { JSON.parse('     ') }
         | 
| 264 | 
            +
              end
         | 
| 265 | 
            +
             | 
| 266 | 
            +
              def test_nesting
         | 
| 267 | 
            +
                assert_raises(JSON::NestingError) { JSON.parse '[[]]', :max_nesting => 1 }
         | 
| 268 | 
            +
                assert_raises(JSON::NestingError) { JSON.parser.new('[[]]', :max_nesting => 1).parse }
         | 
| 269 | 
            +
                assert_equal [[]], JSON.parse('[[]]', :max_nesting => 2)
         | 
| 270 | 
            +
                too_deep = '[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]'
         | 
| 271 | 
            +
                too_deep_ary = eval too_deep
         | 
| 272 | 
            +
                assert_raises(JSON::NestingError) { JSON.parse too_deep }
         | 
| 273 | 
            +
                assert_raises(JSON::NestingError) { JSON.parser.new(too_deep).parse }
         | 
| 274 | 
            +
                assert_raises(JSON::NestingError) { JSON.parse too_deep, :max_nesting => 19 }
         | 
| 275 | 
            +
                ok = JSON.parse too_deep, :max_nesting => 20
         | 
| 276 | 
            +
                assert_equal too_deep_ary, ok
         | 
| 277 | 
            +
                ok = JSON.parse too_deep, :max_nesting => nil
         | 
| 278 | 
            +
                assert_equal too_deep_ary, ok
         | 
| 279 | 
            +
                ok = JSON.parse too_deep, :max_nesting => false
         | 
| 280 | 
            +
                assert_equal too_deep_ary, ok
         | 
| 281 | 
            +
                ok = JSON.parse too_deep, :max_nesting => 0
         | 
| 282 | 
            +
                assert_equal too_deep_ary, ok
         | 
| 283 | 
            +
                assert_raises(JSON::NestingError) { JSON.generate [[]], :max_nesting => 1 }
         | 
| 284 | 
            +
                assert_equal '[[]]', JSON.generate([[]], :max_nesting => 2)
         | 
| 285 | 
            +
                assert_raises(JSON::NestingError) { JSON.generate too_deep_ary }
         | 
| 286 | 
            +
                assert_raises(JSON::NestingError) { JSON.generate too_deep_ary, :max_nesting => 19 }
         | 
| 287 | 
            +
                ok = JSON.generate too_deep_ary, :max_nesting => 20
         | 
| 288 | 
            +
                assert_equal too_deep, ok
         | 
| 289 | 
            +
                ok = JSON.generate too_deep_ary, :max_nesting => nil
         | 
| 290 | 
            +
                assert_equal too_deep, ok
         | 
| 291 | 
            +
                ok = JSON.generate too_deep_ary, :max_nesting => false
         | 
| 292 | 
            +
                assert_equal too_deep, ok
         | 
| 293 | 
            +
                ok = JSON.generate too_deep_ary, :max_nesting => 0
         | 
| 294 | 
            +
                assert_equal too_deep, ok
         | 
| 295 | 
            +
              end
         | 
| 296 | 
            +
             | 
| 297 | 
            +
              def test_load_dump
         | 
| 298 | 
            +
                too_deep = '[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]'
         | 
| 299 | 
            +
                assert_equal too_deep, JSON.dump(eval(too_deep))
         | 
| 300 | 
            +
                assert_kind_of String, Marshal.dump(eval(too_deep))
         | 
| 301 | 
            +
                assert_raises(ArgumentError) { JSON.dump(eval(too_deep), 19) }
         | 
| 302 | 
            +
                assert_raises(ArgumentError) { Marshal.dump(eval(too_deep), 19) }
         | 
| 303 | 
            +
                assert_equal too_deep, JSON.dump(eval(too_deep), 20)
         | 
| 304 | 
            +
                assert_kind_of String, Marshal.dump(eval(too_deep), 20)
         | 
| 305 | 
            +
                output = StringIO.new
         | 
| 306 | 
            +
                JSON.dump(eval(too_deep), output)
         | 
| 307 | 
            +
                assert_equal too_deep, output.string
         | 
| 308 | 
            +
                output = StringIO.new
         | 
| 309 | 
            +
                JSON.dump(eval(too_deep), output, 20)
         | 
| 310 | 
            +
                assert_equal too_deep, output.string
         | 
| 311 | 
            +
              end
         | 
| 312 | 
            +
            end
         |