scout 5.1.2 → 5.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +5 -0
- data/lib/scout.rb +1 -1
- data/lib/scout/server.rb +4 -1
- data/vendor/json_pure/CHANGES +43 -0
- data/vendor/json_pure/{RUBY → COPYING} +1 -1
- data/vendor/json_pure/GPL +7 -7
- data/vendor/json_pure/README +319 -39
- data/vendor/json_pure/Rakefile +69 -47
- data/vendor/json_pure/VERSION +1 -1
- data/vendor/json_pure/benchmarks/generator2_benchmark.rb +222 -0
- data/vendor/json_pure/benchmarks/generator_benchmark.rb +64 -5
- data/vendor/json_pure/benchmarks/ohai.json +1216 -0
- data/vendor/json_pure/benchmarks/ohai.ruby +1 -0
- data/vendor/json_pure/benchmarks/parser2_benchmark.rb +251 -0
- data/vendor/json_pure/benchmarks/parser_benchmark.rb +67 -5
- data/vendor/json_pure/ext/json/ext/generator/extconf.rb +9 -4
- data/vendor/json_pure/ext/json/ext/generator/generator.c +831 -409
- data/vendor/json_pure/ext/json/ext/generator/generator.h +170 -0
- data/vendor/json_pure/ext/json/ext/parser/extconf.rb +8 -4
- data/vendor/json_pure/ext/json/ext/parser/parser.c +292 -186
- data/vendor/json_pure/ext/json/ext/parser/parser.h +71 -0
- data/vendor/json_pure/ext/json/ext/parser/parser.rl +218 -112
- data/vendor/json_pure/lib/json/add/core.rb +20 -7
- data/vendor/json_pure/lib/json/add/rails.rb +2 -2
- data/vendor/json_pure/lib/json/common.rb +85 -42
- data/vendor/json_pure/lib/json/pure.rb +3 -3
- data/vendor/json_pure/lib/json/pure/generator.rb +112 -90
- data/vendor/json_pure/lib/json/pure/parser.rb +42 -4
- data/vendor/json_pure/lib/json/version.rb +1 -1
- data/vendor/json_pure/tests/test_json.rb +46 -18
- data/vendor/json_pure/tests/test_json_addition.rb +4 -6
- data/vendor/json_pure/tests/test_json_encoding.rb +68 -0
- data/vendor/json_pure/tests/test_json_generate.rb +30 -14
- data/vendor/json_pure/tests/test_json_rails.rb +5 -7
- data/vendor/json_pure/tests/test_json_unicode.rb +20 -6
- metadata +26 -15
- data/vendor/json_pure/doc-templates/main.txt +0 -283
- data/vendor/json_pure/ext/json/ext/generator/unicode.c +0 -182
- data/vendor/json_pure/ext/json/ext/generator/unicode.h +0 -53
- data/vendor/json_pure/ext/json/ext/parser/unicode.c +0 -154
- data/vendor/json_pure/ext/json/ext/parser/unicode.h +0 -58
| @@ -7,6 +7,19 @@ unless Object.const_defined?(:JSON) and ::JSON.const_defined?(:JSON_LOADED) and | |
| 7 7 | 
             
            end
         | 
| 8 8 | 
             
            require 'date'
         | 
| 9 9 |  | 
| 10 | 
            +
            class Symbol
         | 
| 11 | 
            +
              def to_json(*a)
         | 
| 12 | 
            +
                {
         | 
| 13 | 
            +
                  JSON.create_id => self.class.name,
         | 
| 14 | 
            +
                  's' => to_s,
         | 
| 15 | 
            +
                }.to_json(*a)
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              def self.json_create(o)
         | 
| 19 | 
            +
                o['s'].to_sym
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
            end
         | 
| 22 | 
            +
             | 
| 10 23 | 
             
            class Time
         | 
| 11 24 | 
             
              def self.json_create(object)
         | 
| 12 25 | 
             
                if usec = object.delete('u') # used to be tv_usec -> tv_nsec
         | 
| @@ -21,7 +34,7 @@ class Time | |
| 21 34 |  | 
| 22 35 | 
             
              def to_json(*args)
         | 
| 23 36 | 
             
                {
         | 
| 24 | 
            -
                   | 
| 37 | 
            +
                  JSON.create_id => self.class.name,
         | 
| 25 38 | 
             
                  's' => tv_sec,
         | 
| 26 39 | 
             
                  'n' => respond_to?(:tv_nsec) ? tv_nsec : tv_usec * 1000
         | 
| 27 40 | 
             
                }.to_json(*args)
         | 
| @@ -37,7 +50,7 @@ class Date | |
| 37 50 |  | 
| 38 51 | 
             
              def to_json(*args)
         | 
| 39 52 | 
             
                {
         | 
| 40 | 
            -
                   | 
| 53 | 
            +
                  JSON.create_id => self.class.name,
         | 
| 41 54 | 
             
                  'y' => year,
         | 
| 42 55 | 
             
                  'm' => month,
         | 
| 43 56 | 
             
                  'd' => day,
         | 
| @@ -63,7 +76,7 @@ class DateTime | |
| 63 76 |  | 
| 64 77 | 
             
              def to_json(*args)
         | 
| 65 78 | 
             
                {
         | 
| 66 | 
            -
                   | 
| 79 | 
            +
                  JSON.create_id => self.class.name,
         | 
| 67 80 | 
             
                  'y' => year,
         | 
| 68 81 | 
             
                  'm' => month,
         | 
| 69 82 | 
             
                  'd' => day,
         | 
| @@ -83,7 +96,7 @@ class Range | |
| 83 96 |  | 
| 84 97 | 
             
              def to_json(*args)
         | 
| 85 98 | 
             
                {
         | 
| 86 | 
            -
                   | 
| 99 | 
            +
                  JSON.create_id   => self.class.name,
         | 
| 87 100 | 
             
                  'a'         => [ first, last, exclude_end? ]
         | 
| 88 101 | 
             
                }.to_json(*args)
         | 
| 89 102 | 
             
              end
         | 
| @@ -98,7 +111,7 @@ class Struct | |
| 98 111 | 
             
                klass = self.class.name
         | 
| 99 112 | 
             
                klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!"
         | 
| 100 113 | 
             
                {
         | 
| 101 | 
            -
                   | 
| 114 | 
            +
                  JSON.create_id => klass,
         | 
| 102 115 | 
             
                  'v'     => values,
         | 
| 103 116 | 
             
                }.to_json(*args)
         | 
| 104 117 | 
             
              end
         | 
| @@ -113,7 +126,7 @@ class Exception | |
| 113 126 |  | 
| 114 127 | 
             
              def to_json(*args)
         | 
| 115 128 | 
             
                {
         | 
| 116 | 
            -
                   | 
| 129 | 
            +
                  JSON.create_id => self.class.name,
         | 
| 117 130 | 
             
                  'm'   => message,
         | 
| 118 131 | 
             
                  'b' => backtrace,
         | 
| 119 132 | 
             
                }.to_json(*args)
         | 
| @@ -127,7 +140,7 @@ class Regexp | |
| 127 140 |  | 
| 128 141 | 
             
              def to_json(*)
         | 
| 129 142 | 
             
                {
         | 
| 130 | 
            -
                   | 
| 143 | 
            +
                  JSON.create_id => self.class.name,
         | 
| 131 144 | 
             
                  'o' => options,
         | 
| 132 145 | 
             
                  's' => source,
         | 
| 133 146 | 
             
                }.to_json
         | 
| @@ -10,7 +10,7 @@ class Object | |
| 10 10 | 
             
              def self.json_create(object)
         | 
| 11 11 | 
             
                obj = new
         | 
| 12 12 | 
             
                for key, value in object
         | 
| 13 | 
            -
                  next if key ==  | 
| 13 | 
            +
                  next if key == JSON.create_id
         | 
| 14 14 | 
             
                  instance_variable_set "@#{key}", value
         | 
| 15 15 | 
             
                end
         | 
| 16 16 | 
             
                obj
         | 
| @@ -18,7 +18,7 @@ class Object | |
| 18 18 |  | 
| 19 19 | 
             
              def to_json(*a)
         | 
| 20 20 | 
             
                result = {
         | 
| 21 | 
            -
                   | 
| 21 | 
            +
                  JSON.create_id => self.class.name
         | 
| 22 22 | 
             
                }
         | 
| 23 23 | 
             
                instance_variables.inject(result) do |r, name|
         | 
| 24 24 | 
             
                  r[name[1..-1]] = instance_variable_get name
         | 
| @@ -1,4 +1,5 @@ | |
| 1 1 | 
             
            require 'json/version'
         | 
| 2 | 
            +
            require 'iconv'
         | 
| 2 3 |  | 
| 3 4 | 
             
            module JSON
         | 
| 4 5 | 
             
              class << self
         | 
| @@ -32,12 +33,16 @@ module JSON | |
| 32 33 | 
             
                # level (absolute namespace path?). If there doesn't exist a constant at
         | 
| 33 34 | 
             
                # the given path, an ArgumentError is raised.
         | 
| 34 35 | 
             
                def deep_const_get(path) # :nodoc:
         | 
| 35 | 
            -
                  path  | 
| 36 | 
            -
                  path.split(/::/).inject(Object) do |p, c|
         | 
| 36 | 
            +
                  path.to_s.split(/::/).inject(Object) do |p, c|
         | 
| 37 37 | 
             
                    case
         | 
| 38 38 | 
             
                    when c.empty?             then p
         | 
| 39 39 | 
             
                    when p.const_defined?(c)  then p.const_get(c)
         | 
| 40 | 
            -
                    else | 
| 40 | 
            +
                    else
         | 
| 41 | 
            +
                      begin
         | 
| 42 | 
            +
                        p.const_missing(c)
         | 
| 43 | 
            +
                      rescue NameError
         | 
| 44 | 
            +
                        raise ArgumentError, "can't find const #{path}"
         | 
| 45 | 
            +
                      end
         | 
| 41 46 | 
             
                    end
         | 
| 42 47 | 
             
                  end
         | 
| 43 48 | 
             
                end
         | 
| @@ -58,6 +63,20 @@ module JSON | |
| 58 63 | 
             
                  end
         | 
| 59 64 | 
             
                  self.state = generator::State
         | 
| 60 65 | 
             
                  const_set :State, self.state
         | 
| 66 | 
            +
                  const_set :SAFE_STATE_PROTOTYPE, State.new.freeze
         | 
| 67 | 
            +
                  const_set :FAST_STATE_PROTOTYPE, State.new(
         | 
| 68 | 
            +
                    :indent         => '',
         | 
| 69 | 
            +
                    :space          => '',
         | 
| 70 | 
            +
                    :object_nl      => "",
         | 
| 71 | 
            +
                    :array_nl       => "",
         | 
| 72 | 
            +
                    :max_nesting    => false
         | 
| 73 | 
            +
                  ).freeze
         | 
| 74 | 
            +
                  const_set :PRETTY_STATE_PROTOTYPE, State.new(
         | 
| 75 | 
            +
                    :indent         => '  ',
         | 
| 76 | 
            +
                    :space          => ' ',
         | 
| 77 | 
            +
                    :object_nl      => "\n",
         | 
| 78 | 
            +
                    :array_nl       => "\n"
         | 
| 79 | 
            +
                  ).freeze
         | 
| 61 80 | 
             
                end
         | 
| 62 81 |  | 
| 63 82 | 
             
                # Returns the JSON generator modul, that is used by JSON. This might be
         | 
| @@ -74,7 +93,7 @@ module JSON | |
| 74 93 | 
             
              end
         | 
| 75 94 | 
             
              self.create_id = 'json_class'
         | 
| 76 95 |  | 
| 77 | 
            -
              NaN           =  | 
| 96 | 
            +
              NaN           = 0.0/0
         | 
| 78 97 |  | 
| 79 98 | 
             
              Infinity      = 1.0/0
         | 
| 80 99 |  | 
| @@ -90,22 +109,22 @@ module JSON | |
| 90 109 | 
             
              # deep.
         | 
| 91 110 | 
             
              class NestingError < ParserError; end
         | 
| 92 111 |  | 
| 112 | 
            +
              # :stopdoc:
         | 
| 113 | 
            +
              class CircularDatastructure < NestingError; end
         | 
| 114 | 
            +
              # :startdoc:
         | 
| 115 | 
            +
             | 
| 93 116 | 
             
              # This exception is raised, if a generator or unparser error occurs.
         | 
| 94 117 | 
             
              class GeneratorError < JSONError; end
         | 
| 95 118 | 
             
              # For backwards compatibility
         | 
| 96 119 | 
             
              UnparserError = GeneratorError
         | 
| 97 120 |  | 
| 98 | 
            -
              # If a circular data structure is encountered while unparsing
         | 
| 99 | 
            -
              # this exception is raised.
         | 
| 100 | 
            -
              class CircularDatastructure < GeneratorError; end
         | 
| 101 | 
            -
             | 
| 102 121 | 
             
              # This exception is raised, if the required unicode support is missing on the
         | 
| 103 122 | 
             
              # system. Usually this means, that the iconv library is not installed.
         | 
| 104 123 | 
             
              class MissingUnicodeSupport < JSONError; end
         | 
| 105 124 |  | 
| 106 125 | 
             
              module_function
         | 
| 107 126 |  | 
| 108 | 
            -
              # Parse the JSON  | 
| 127 | 
            +
              # Parse the JSON document _source_ into a Ruby data structure and return it.
         | 
| 109 128 | 
             
              #
         | 
| 110 129 | 
             
              # _opts_ can have the following
         | 
| 111 130 | 
             
              # keys:
         | 
| @@ -115,16 +134,21 @@ module JSON | |
| 115 134 | 
             
              # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
         | 
| 116 135 | 
             
              #   defiance of RFC 4627 to be parsed by the Parser. This option defaults
         | 
| 117 136 | 
             
              #   to false.
         | 
| 137 | 
            +
              # * *symbolize_names*: If set to true, returns symbols for the names
         | 
| 138 | 
            +
              #   (keys) in a JSON object. Otherwise strings are returned, which is also
         | 
| 139 | 
            +
              #   the default.
         | 
| 118 140 | 
             
              # * *create_additions*: If set to false, the Parser doesn't create
         | 
| 119 141 | 
             
              #   additions even if a matchin class and create_id was found. This option
         | 
| 120 142 | 
             
              #   defaults to true.
         | 
| 143 | 
            +
              # * *object_class*: Defaults to Hash
         | 
| 144 | 
            +
              # * *array_class*: Defaults to Array
         | 
| 121 145 | 
             
              def parse(source, opts = {})
         | 
| 122 | 
            -
                 | 
| 146 | 
            +
                Parser.new(source, opts).parse
         | 
| 123 147 | 
             
              end
         | 
| 124 148 |  | 
| 125 | 
            -
              # Parse the JSON  | 
| 149 | 
            +
              # Parse the JSON document _source_ into a Ruby data structure and return it.
         | 
| 126 150 | 
             
              # The bang version of the parse method, defaults to the more dangerous values
         | 
| 127 | 
            -
              # for the _opts_ hash, so be sure only to parse trusted _source_  | 
| 151 | 
            +
              # for the _opts_ hash, so be sure only to parse trusted _source_ documents.
         | 
| 128 152 | 
             
              #
         | 
| 129 153 | 
             
              # _opts_ can have the following keys:
         | 
| 130 154 | 
             
              # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
         | 
| @@ -139,15 +163,14 @@ module JSON | |
| 139 163 | 
             
              #   defaults to true.
         | 
| 140 164 | 
             
              def parse!(source, opts = {})
         | 
| 141 165 | 
             
                opts = {
         | 
| 142 | 
            -
                  :max_nesting | 
| 143 | 
            -
                  :allow_nan | 
| 166 | 
            +
                  :max_nesting  => false,
         | 
| 167 | 
            +
                  :allow_nan    => true
         | 
| 144 168 | 
             
                }.update(opts)
         | 
| 145 | 
            -
                 | 
| 169 | 
            +
                Parser.new(source, opts).parse
         | 
| 146 170 | 
             
              end
         | 
| 147 171 |  | 
| 148 | 
            -
              #  | 
| 149 | 
            -
              #  | 
| 150 | 
            -
              # * a JSON::State object,
         | 
| 172 | 
            +
              # Generate a JSON document from the Ruby data structure _obj_ and return
         | 
| 173 | 
            +
              # it. _state_ is * a JSON::State object,
         | 
| 151 174 | 
             
              # * or a Hash like object (responding to to_hash),
         | 
| 152 175 | 
             
              # * an object convertible into a hash by a to_h method,
         | 
| 153 176 | 
             
              # that is used as or to configure a State object.
         | 
| @@ -162,8 +185,6 @@ module JSON | |
| 162 185 | 
             
              # * *space_before*: a string that is put before a : pair delimiter (default: ''),
         | 
| 163 186 | 
             
              # * *object_nl*: a string that is put at the end of a JSON object (default: ''), 
         | 
| 164 187 | 
             
              # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
         | 
| 165 | 
            -
              # * *check_circular*: true if checking for circular data structures
         | 
| 166 | 
            -
              #   should be done (the default), false otherwise.
         | 
| 167 188 | 
             
              # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
         | 
| 168 189 | 
             
              #   generated, otherwise an exception is thrown, if these values are
         | 
| 169 190 | 
             
              #   encountered. This options defaults to false.
         | 
| @@ -174,13 +195,21 @@ module JSON | |
| 174 195 | 
             
              # See also the fast_generate for the fastest creation method with the least
         | 
| 175 196 | 
             
              # amount of sanity checks, and the pretty_generate method for some
         | 
| 176 197 | 
             
              # defaults for a pretty output.
         | 
| 177 | 
            -
              def generate(obj,  | 
| 178 | 
            -
                if  | 
| 179 | 
            -
                   | 
| 198 | 
            +
              def generate(obj, opts = nil)
         | 
| 199 | 
            +
                if opts
         | 
| 200 | 
            +
                  if opts.respond_to? :to_hash
         | 
| 201 | 
            +
                    opts = opts.to_hash
         | 
| 202 | 
            +
                  elsif opts.respond_to? :to_h
         | 
| 203 | 
            +
                    opts = opts.to_h
         | 
| 204 | 
            +
                  else
         | 
| 205 | 
            +
                    raise TypeError, "can't convert #{opts.class} into Hash"
         | 
| 206 | 
            +
                  end
         | 
| 207 | 
            +
                  state = SAFE_STATE_PROTOTYPE.dup
         | 
| 208 | 
            +
                  state = state.configure(opts)
         | 
| 180 209 | 
             
                else
         | 
| 181 | 
            -
                  state =  | 
| 210 | 
            +
                  state = SAFE_STATE_PROTOTYPE
         | 
| 182 211 | 
             
                end
         | 
| 183 | 
            -
                 | 
| 212 | 
            +
                state.generate(obj)
         | 
| 184 213 | 
             
              end
         | 
| 185 214 |  | 
| 186 215 | 
             
              # :stopdoc:
         | 
| @@ -190,14 +219,26 @@ module JSON | |
| 190 219 | 
             
              module_function :unparse
         | 
| 191 220 | 
             
              # :startdoc:
         | 
| 192 221 |  | 
| 193 | 
            -
              #  | 
| 194 | 
            -
              #  | 
| 195 | 
            -
              # also generates NaN, Infinity, and, -Infinity float values.
         | 
| 222 | 
            +
              # Generate a JSON document from the Ruby data structure _obj_ and return it.
         | 
| 223 | 
            +
              # This method disables the checks for circles in Ruby objects.
         | 
| 196 224 | 
             
              #
         | 
| 197 225 | 
             
              # *WARNING*: Be careful not to pass any Ruby data structures with circles as
         | 
| 198 226 | 
             
              # _obj_ argument, because this will cause JSON to go into an infinite loop.
         | 
| 199 | 
            -
              def fast_generate(obj)
         | 
| 200 | 
            -
                 | 
| 227 | 
            +
              def fast_generate(obj, opts = nil)
         | 
| 228 | 
            +
                if opts
         | 
| 229 | 
            +
                  if opts.respond_to? :to_hash
         | 
| 230 | 
            +
                    opts = opts.to_hash
         | 
| 231 | 
            +
                  elsif opts.respond_to? :to_h
         | 
| 232 | 
            +
                    opts = opts.to_h
         | 
| 233 | 
            +
                  else
         | 
| 234 | 
            +
                    raise TypeError, "can't convert #{opts.class} into Hash"
         | 
| 235 | 
            +
                  end
         | 
| 236 | 
            +
                  state = FAST_STATE_PROTOTYPE.dup
         | 
| 237 | 
            +
                  state.configure(opts)
         | 
| 238 | 
            +
                else
         | 
| 239 | 
            +
                  state = FAST_STATE_PROTOTYPE
         | 
| 240 | 
            +
                end
         | 
| 241 | 
            +
                state.generate(obj)
         | 
| 201 242 | 
             
              end
         | 
| 202 243 |  | 
| 203 244 | 
             
              # :stopdoc:
         | 
| @@ -206,19 +247,13 @@ module JSON | |
| 206 247 | 
             
              module_function :fast_unparse
         | 
| 207 248 | 
             
              # :startdoc:
         | 
| 208 249 |  | 
| 209 | 
            -
              #  | 
| 210 | 
            -
              # returned  | 
| 250 | 
            +
              # Generate a JSON document from the Ruby data structure _obj_ and return it.
         | 
| 251 | 
            +
              # The returned document is a prettier form of the document returned by
         | 
| 252 | 
            +
              # #unparse.
         | 
| 211 253 | 
             
              #
         | 
| 212 254 | 
             
              # The _opts_ argument can be used to configure the generator, see the
         | 
| 213 255 | 
             
              # generate method for a more detailed explanation.
         | 
| 214 256 | 
             
              def pretty_generate(obj, opts = nil)
         | 
| 215 | 
            -
                state = JSON.state.new(
         | 
| 216 | 
            -
                  :indent     => '  ',
         | 
| 217 | 
            -
                  :space      => ' ',
         | 
| 218 | 
            -
                  :object_nl  => "\n",
         | 
| 219 | 
            -
                  :array_nl   => "\n",
         | 
| 220 | 
            -
                  :check_circular => true
         | 
| 221 | 
            -
                )
         | 
| 222 257 | 
             
                if opts
         | 
| 223 258 | 
             
                  if opts.respond_to? :to_hash
         | 
| 224 259 | 
             
                    opts = opts.to_hash
         | 
| @@ -227,9 +262,12 @@ module JSON | |
| 227 262 | 
             
                  else
         | 
| 228 263 | 
             
                    raise TypeError, "can't convert #{opts.class} into Hash"
         | 
| 229 264 | 
             
                  end
         | 
| 265 | 
            +
                  state = PRETTY_STATE_PROTOTYPE.dup
         | 
| 230 266 | 
             
                  state.configure(opts)
         | 
| 267 | 
            +
                else
         | 
| 268 | 
            +
                  state = PRETTY_STATE_PROTOTYPE
         | 
| 231 269 | 
             
                end
         | 
| 232 | 
            -
                 | 
| 270 | 
            +
                state.generate(obj)
         | 
| 233 271 | 
             
              end
         | 
| 234 272 |  | 
| 235 273 | 
             
              # :stopdoc:
         | 
| @@ -270,8 +308,6 @@ module JSON | |
| 270 308 | 
             
                  proc.call result
         | 
| 271 309 | 
             
                end
         | 
| 272 310 | 
             
              end
         | 
| 273 | 
            -
              private :recurse_proc
         | 
| 274 | 
            -
              module_function :recurse_proc
         | 
| 275 311 |  | 
| 276 312 | 
             
              alias restore load
         | 
| 277 313 | 
             
              module_function :restore
         | 
| @@ -307,9 +343,16 @@ module JSON | |
| 307 343 | 
             
              rescue JSON::NestingError
         | 
| 308 344 | 
             
                raise ArgumentError, "exceed depth limit"
         | 
| 309 345 | 
             
              end
         | 
| 346 | 
            +
             | 
| 347 | 
            +
              # Shortuct for iconv.
         | 
| 348 | 
            +
              def self.iconv(to, from, string)
         | 
| 349 | 
            +
                Iconv.iconv(to, from, string).first
         | 
| 350 | 
            +
              end
         | 
| 310 351 | 
             
            end
         | 
| 311 352 |  | 
| 312 353 | 
             
            module ::Kernel
         | 
| 354 | 
            +
              private
         | 
| 355 | 
            +
             | 
| 313 356 | 
             
              # Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in
         | 
| 314 357 | 
             
              # one line.
         | 
| 315 358 | 
             
              def j(*objs)
         | 
| @@ -10,6 +10,9 @@ module JSON | |
| 10 10 | 
             
                # An iconv instance to convert from UTF16 Big Endian to UTF8.
         | 
| 11 11 | 
             
                UTF8toUTF16 = Iconv.new('utf-16be', 'utf-8') # :nodoc:
         | 
| 12 12 | 
             
                UTF8toUTF16.iconv('no bom')
         | 
| 13 | 
            +
              rescue LoadError
         | 
| 14 | 
            +
                raise MissingUnicodeSupport,
         | 
| 15 | 
            +
                  "iconv couldn't be loaded, which is required for UTF-8/UTF-16 conversions"
         | 
| 13 16 | 
             
              rescue Errno::EINVAL, Iconv::InvalidEncoding
         | 
| 14 17 | 
             
                # Iconv doesn't support big endian utf-16. Let's try to hack this manually
         | 
| 15 18 | 
             
                # into the converters.
         | 
| @@ -51,9 +54,6 @@ module JSON | |
| 51 54 | 
             
                ensure
         | 
| 52 55 | 
             
                  $VERBOSE = old_verbose
         | 
| 53 56 | 
             
                end
         | 
| 54 | 
            -
              rescue LoadError
         | 
| 55 | 
            -
                raise MissingUnicodeSupport,
         | 
| 56 | 
            -
                  "iconv couldn't be loaded, which is required for UTF-8/UTF-16 conversions"
         | 
| 57 57 | 
             
              end
         | 
| 58 58 |  | 
| 59 59 | 
             
              # Swap consecutive bytes of _string_ in place.
         | 
| @@ -34,17 +34,25 @@ module JSON | |
| 34 34 | 
             
                "\x1f" => '\u001f',
         | 
| 35 35 | 
             
                '"'   =>  '\"',
         | 
| 36 36 | 
             
                '\\'  =>  '\\\\',
         | 
| 37 | 
            -
                '/'   =>  '\/',
         | 
| 38 37 | 
             
              } # :nodoc:
         | 
| 39 38 |  | 
| 40 39 | 
             
              # Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
         | 
| 41 40 | 
             
              # UTF16 big endian characters as \u????, and return it.
         | 
| 42 | 
            -
              if  | 
| 41 | 
            +
              if defined?(::Encoding)
         | 
| 43 42 | 
             
                def utf8_to_json(string) # :nodoc:
         | 
| 44 43 | 
             
                  string = string.dup
         | 
| 45 44 | 
             
                  string << '' # XXX workaround: avoid buffer sharing
         | 
| 46 | 
            -
                  string.force_encoding(Encoding::ASCII_8BIT)
         | 
| 47 | 
            -
                  string.gsub!(/[" | 
| 45 | 
            +
                  string.force_encoding(::Encoding::ASCII_8BIT)
         | 
| 46 | 
            +
                  string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
         | 
| 47 | 
            +
                  string.force_encoding(::Encoding::UTF_8)
         | 
| 48 | 
            +
                  string
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                def utf8_to_json_ascii(string) # :nodoc:
         | 
| 52 | 
            +
                  string = string.dup
         | 
| 53 | 
            +
                  string << '' # XXX workaround: avoid buffer sharing
         | 
| 54 | 
            +
                  string.force_encoding(::Encoding::ASCII_8BIT)
         | 
| 55 | 
            +
                  string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
         | 
| 48 56 | 
             
                  string.gsub!(/(
         | 
| 49 57 | 
             
                                  (?:
         | 
| 50 58 | 
             
                                    [\xc2-\xdf][\x80-\xbf]    |
         | 
| @@ -57,14 +65,18 @@ module JSON | |
| 57 65 | 
             
                                  s = JSON::UTF8toUTF16.iconv(c).unpack('H*')[0]
         | 
| 58 66 | 
             
                                  s.gsub!(/.{4}/n, '\\\\u\&')
         | 
| 59 67 | 
             
                                }
         | 
| 60 | 
            -
                  string.force_encoding(Encoding::UTF_8)
         | 
| 68 | 
            +
                  string.force_encoding(::Encoding::UTF_8)
         | 
| 61 69 | 
             
                  string
         | 
| 62 70 | 
             
                rescue Iconv::Failure => e
         | 
| 63 71 | 
             
                  raise GeneratorError, "Caught #{e.class}: #{e}"
         | 
| 64 72 | 
             
                end
         | 
| 65 73 | 
             
              else
         | 
| 66 74 | 
             
                def utf8_to_json(string) # :nodoc:
         | 
| 67 | 
            -
                  string | 
| 75 | 
            +
                  string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                def utf8_to_json_ascii(string) # :nodoc:
         | 
| 79 | 
            +
                  string = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
         | 
| 68 80 | 
             
                  string.gsub!(/(
         | 
| 69 81 | 
             
                                  (?:
         | 
| 70 82 | 
             
                                    [\xc2-\xdf][\x80-\xbf]    |
         | 
| @@ -82,7 +94,7 @@ module JSON | |
| 82 94 | 
             
                  raise GeneratorError, "Caught #{e.class}: #{e}"
         | 
| 83 95 | 
             
                end
         | 
| 84 96 | 
             
              end
         | 
| 85 | 
            -
              module_function :utf8_to_json
         | 
| 97 | 
            +
              module_function :utf8_to_json, :utf8_to_json_ascii
         | 
| 86 98 |  | 
| 87 99 | 
             
              module Pure
         | 
| 88 100 | 
             
                module Generator
         | 
| @@ -100,7 +112,7 @@ module JSON | |
| 100 112 | 
             
                      when Hash
         | 
| 101 113 | 
             
                        new(opts)
         | 
| 102 114 | 
             
                      else
         | 
| 103 | 
            -
                         | 
| 115 | 
            +
                        SAFE_STATE_PROTOTYPE
         | 
| 104 116 | 
             
                      end
         | 
| 105 117 | 
             
                    end
         | 
| 106 118 |  | 
| @@ -113,22 +125,20 @@ module JSON | |
| 113 125 | 
             
                    # * *space_before*: a string that is put before a : pair delimiter (default: ''),
         | 
| 114 126 | 
             
                    # * *object_nl*: a string that is put at the end of a JSON object (default: ''), 
         | 
| 115 127 | 
             
                    # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
         | 
| 116 | 
            -
                    # * *check_circular*:  | 
| 117 | 
            -
                    # | 
| 118 | 
            -
                    #  | 
| 119 | 
            -
                    #   should be done, false (the default) otherwise.
         | 
| 128 | 
            +
                    # * *check_circular*: is deprecated now, use the :max_nesting option instead,
         | 
| 129 | 
            +
                    # * *max_nesting*: sets the maximum level of data structure nesting in
         | 
| 130 | 
            +
                    #   the generated JSON, max_nesting = 0 if no maximum should be checked.
         | 
| 120 131 | 
             
                    # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
         | 
| 121 132 | 
             
                    #   generated, otherwise an exception is thrown, if these values are
         | 
| 122 133 | 
             
                    #   encountered. This options defaults to false.
         | 
| 123 134 | 
             
                    def initialize(opts = {})
         | 
| 124 | 
            -
                      @seen = {}
         | 
| 125 135 | 
             
                      @indent         = ''
         | 
| 126 136 | 
             
                      @space          = ''
         | 
| 127 137 | 
             
                      @space_before   = ''
         | 
| 128 138 | 
             
                      @object_nl      = ''
         | 
| 129 139 | 
             
                      @array_nl       = ''
         | 
| 130 | 
            -
                      @check_circular = true
         | 
| 131 140 | 
             
                      @allow_nan      = false
         | 
| 141 | 
            +
                      @ascii_only     = false
         | 
| 132 142 | 
             
                      configure opts
         | 
| 133 143 | 
             
                    end
         | 
| 134 144 |  | 
| @@ -160,10 +170,10 @@ module JSON | |
| 160 170 | 
             
                        raise NestingError, "nesting of #{current_nesting} is too deep"
         | 
| 161 171 | 
             
                    end
         | 
| 162 172 |  | 
| 163 | 
            -
                    # Returns true, if circular data structures  | 
| 173 | 
            +
                    # Returns true, if circular data structures are checked,
         | 
| 164 174 | 
             
                    # otherwise returns false.
         | 
| 165 175 | 
             
                    def check_circular?
         | 
| 166 | 
            -
                       | 
| 176 | 
            +
                      !@max_nesting.zero?
         | 
| 167 177 | 
             
                    end
         | 
| 168 178 |  | 
| 169 179 | 
             
                    # Returns true if NaN, Infinity, and -Infinity should be considered as
         | 
| @@ -172,21 +182,8 @@ module JSON | |
| 172 182 | 
             
                      @allow_nan
         | 
| 173 183 | 
             
                    end
         | 
| 174 184 |  | 
| 175 | 
            -
                     | 
| 176 | 
            -
             | 
| 177 | 
            -
                    def seen?(object)
         | 
| 178 | 
            -
                      @seen.key?(object.__id__)
         | 
| 179 | 
            -
                    end
         | 
| 180 | 
            -
             | 
| 181 | 
            -
                    # Remember _object_, to find out if it was already encountered (if a
         | 
| 182 | 
            -
                    # cyclic data structure is if a cyclic data structure is rendered). 
         | 
| 183 | 
            -
                    def remember(object)
         | 
| 184 | 
            -
                      @seen[object.__id__] = true
         | 
| 185 | 
            -
                    end
         | 
| 186 | 
            -
             | 
| 187 | 
            -
                    # Forget _object_ for this generating run.
         | 
| 188 | 
            -
                    def forget(object)
         | 
| 189 | 
            -
                      @seen.delete object.__id__
         | 
| 185 | 
            +
                    def ascii_only?
         | 
| 186 | 
            +
                      @ascii_only
         | 
| 190 187 | 
             
                    end
         | 
| 191 188 |  | 
| 192 189 | 
             
                    # Configure this State instance with the Hash _opts_, and return
         | 
| @@ -197,8 +194,8 @@ module JSON | |
| 197 194 | 
             
                      @space_before   = opts[:space_before] if opts.key?(:space_before)
         | 
| 198 195 | 
             
                      @object_nl      = opts[:object_nl] if opts.key?(:object_nl)
         | 
| 199 196 | 
             
                      @array_nl       = opts[:array_nl] if opts.key?(:array_nl)
         | 
| 200 | 
            -
                      @check_circular = !!opts[:check_circular] if opts.key?(:check_circular)
         | 
| 201 197 | 
             
                      @allow_nan      = !!opts[:allow_nan] if opts.key?(:allow_nan)
         | 
| 198 | 
            +
                      @ascii_only     = opts[:ascii_only] if opts.key?(:ascii_only)
         | 
| 202 199 | 
             
                      if !opts.key?(:max_nesting) # defaults to 19
         | 
| 203 200 | 
             
                        @max_nesting = 19
         | 
| 204 201 | 
             
                      elsif opts[:max_nesting]
         | 
| @@ -213,11 +210,27 @@ module JSON | |
| 213 210 | 
             
                    # passed to the configure method.
         | 
| 214 211 | 
             
                    def to_h
         | 
| 215 212 | 
             
                      result = {}
         | 
| 216 | 
            -
                      for iv in %w[indent space space_before object_nl array_nl  | 
| 213 | 
            +
                      for iv in %w[indent space space_before object_nl array_nl allow_nan max_nesting]
         | 
| 217 214 | 
             
                        result[iv.intern] = instance_variable_get("@#{iv}")
         | 
| 218 215 | 
             
                      end
         | 
| 219 216 | 
             
                      result
         | 
| 220 217 | 
             
                    end
         | 
| 218 | 
            +
             | 
| 219 | 
            +
                    # Generates a valid JSON document from object +obj+ and returns the
         | 
| 220 | 
            +
                    # result. If no valid JSON document can be created this method raises a
         | 
| 221 | 
            +
                    # GeneratorError exception.
         | 
| 222 | 
            +
                    def generate(obj)
         | 
| 223 | 
            +
                      result = obj.to_json(self)
         | 
| 224 | 
            +
                      if result !~ /\A\s*(?:\[.*\]|\{.*\})\s*\Z/m
         | 
| 225 | 
            +
                        raise GeneratorError, "only generation of JSON objects or arrays allowed"
         | 
| 226 | 
            +
                      end
         | 
| 227 | 
            +
                      result
         | 
| 228 | 
            +
                    end
         | 
| 229 | 
            +
             | 
| 230 | 
            +
                    # Return the value returned by method +name+.
         | 
| 231 | 
            +
                    def [](name)
         | 
| 232 | 
            +
                      __send__ name
         | 
| 233 | 
            +
                    end
         | 
| 221 234 | 
             
                  end
         | 
| 222 235 |  | 
| 223 236 | 
             
                  module GeneratorMethods
         | 
| @@ -236,27 +249,14 @@ module JSON | |
| 236 249 | 
             
                      # _depth_ is used to find out nesting depth, to indent accordingly.
         | 
| 237 250 | 
             
                      def to_json(state = nil, depth = 0, *)
         | 
| 238 251 | 
             
                        if state
         | 
| 239 | 
            -
                          state =  | 
| 252 | 
            +
                          state = State.from_state(state)
         | 
| 240 253 | 
             
                          state.check_max_nesting(depth)
         | 
| 241 | 
            -
                          json_check_circular(state) { json_transform(state, depth) }
         | 
| 242 | 
            -
                        else
         | 
| 243 | 
            -
                          json_transform(state, depth)
         | 
| 244 254 | 
             
                        end
         | 
| 255 | 
            +
                        json_transform(state, depth)
         | 
| 245 256 | 
             
                      end
         | 
| 246 257 |  | 
| 247 258 | 
             
                      private
         | 
| 248 259 |  | 
| 249 | 
            -
                      def json_check_circular(state)
         | 
| 250 | 
            -
                        if state and state.check_circular?
         | 
| 251 | 
            -
                          state.seen?(self) and raise JSON::CircularDatastructure,
         | 
| 252 | 
            -
                              "circular data structures not supported!"
         | 
| 253 | 
            -
                          state.remember self
         | 
| 254 | 
            -
                        end
         | 
| 255 | 
            -
                        yield
         | 
| 256 | 
            -
                      ensure
         | 
| 257 | 
            -
                        state and state.forget self
         | 
| 258 | 
            -
                      end
         | 
| 259 | 
            -
             | 
| 260 260 | 
             
                      def json_shift(state, depth)
         | 
| 261 261 | 
             
                        state and not state.object_nl.empty? or return ''
         | 
| 262 262 | 
             
                        state.indent * depth
         | 
| @@ -268,16 +268,22 @@ module JSON | |
| 268 268 | 
             
                          delim << state.object_nl
         | 
| 269 269 | 
             
                          result = '{'
         | 
| 270 270 | 
             
                          result << state.object_nl
         | 
| 271 | 
            -
                           | 
| 272 | 
            -
             | 
| 273 | 
            -
             | 
| 274 | 
            -
             | 
| 275 | 
            -
                             | 
| 276 | 
            -
                             | 
| 277 | 
            -
                             | 
| 278 | 
            -
             | 
| 271 | 
            +
                          depth += 1
         | 
| 272 | 
            +
                          first = true
         | 
| 273 | 
            +
                          indent = state && !state.object_nl.empty?
         | 
| 274 | 
            +
                          each { |key,value|
         | 
| 275 | 
            +
                            result << delim unless first
         | 
| 276 | 
            +
                            result << state.indent * depth if indent
         | 
| 277 | 
            +
                            result << key.to_s.to_json(state, depth)
         | 
| 278 | 
            +
                            result << state.space_before
         | 
| 279 | 
            +
                            result << ':'
         | 
| 280 | 
            +
                            result << state.space
         | 
| 281 | 
            +
                            result << value.to_json(state, depth)
         | 
| 282 | 
            +
                            first = false
         | 
| 283 | 
            +
                          }
         | 
| 284 | 
            +
                          depth -= 1
         | 
| 279 285 | 
             
                          result << state.object_nl
         | 
| 280 | 
            -
                          result <<  | 
| 286 | 
            +
                          result << state.indent * depth if indent if indent
         | 
| 281 287 | 
             
                          result << '}'
         | 
| 282 288 | 
             
                        else
         | 
| 283 289 | 
             
                          result = '{'
         | 
| @@ -298,43 +304,32 @@ module JSON | |
| 298 304 | 
             
                      # _depth_ is used to find out nesting depth, to indent accordingly.
         | 
| 299 305 | 
             
                      def to_json(state = nil, depth = 0, *)
         | 
| 300 306 | 
             
                        if state
         | 
| 301 | 
            -
                          state =  | 
| 307 | 
            +
                          state = State.from_state(state)
         | 
| 302 308 | 
             
                          state.check_max_nesting(depth)
         | 
| 303 | 
            -
                          json_check_circular(state) { json_transform(state, depth) }
         | 
| 304 | 
            -
                        else
         | 
| 305 | 
            -
                          json_transform(state, depth)
         | 
| 306 309 | 
             
                        end
         | 
| 310 | 
            +
                        json_transform(state, depth)
         | 
| 307 311 | 
             
                      end
         | 
| 308 312 |  | 
| 309 313 | 
             
                      private
         | 
| 310 314 |  | 
| 311 | 
            -
                      def json_check_circular(state)
         | 
| 312 | 
            -
                        if state and state.check_circular?
         | 
| 313 | 
            -
                          state.seen?(self) and raise JSON::CircularDatastructure,
         | 
| 314 | 
            -
                            "circular data structures not supported!"
         | 
| 315 | 
            -
                          state.remember self
         | 
| 316 | 
            -
                        end
         | 
| 317 | 
            -
                        yield
         | 
| 318 | 
            -
                      ensure
         | 
| 319 | 
            -
                        state and state.forget self
         | 
| 320 | 
            -
                      end
         | 
| 321 | 
            -
             | 
| 322 | 
            -
                      def json_shift(state, depth)
         | 
| 323 | 
            -
                        state and not state.array_nl.empty? or return ''
         | 
| 324 | 
            -
                        state.indent * depth
         | 
| 325 | 
            -
                      end
         | 
| 326 | 
            -
             | 
| 327 315 | 
             
                      def json_transform(state, depth)
         | 
| 328 316 | 
             
                        delim = ','
         | 
| 329 317 | 
             
                        if state
         | 
| 330 318 | 
             
                          delim << state.array_nl
         | 
| 331 319 | 
             
                          result = '['
         | 
| 332 320 | 
             
                          result << state.array_nl
         | 
| 333 | 
            -
                           | 
| 334 | 
            -
             | 
| 335 | 
            -
                           | 
| 321 | 
            +
                          depth += 1
         | 
| 322 | 
            +
                          first = true
         | 
| 323 | 
            +
                          indent = state && !state.array_nl.empty?
         | 
| 324 | 
            +
                          each { |value|
         | 
| 325 | 
            +
                            result << delim unless first
         | 
| 326 | 
            +
                            result << state.indent * depth if indent
         | 
| 327 | 
            +
                            result << value.to_json(state, depth)
         | 
| 328 | 
            +
                            first = false
         | 
| 329 | 
            +
                          }
         | 
| 330 | 
            +
                          depth -= 1
         | 
| 336 331 | 
             
                          result << state.array_nl
         | 
| 337 | 
            -
                          result <<  | 
| 332 | 
            +
                          result << state.indent * depth if indent
         | 
| 338 333 | 
             
                          result << ']'
         | 
| 339 334 | 
             
                        else
         | 
| 340 335 | 
             
                          '[' << map { |value| value.to_json }.join(delim) << ']'
         | 
| @@ -352,13 +347,13 @@ module JSON | |
| 352 347 | 
             
                      def to_json(state = nil, *)
         | 
| 353 348 | 
             
                        case
         | 
| 354 349 | 
             
                        when infinite?
         | 
| 355 | 
            -
                          if  | 
| 350 | 
            +
                          if state && state.allow_nan?
         | 
| 356 351 | 
             
                            to_s
         | 
| 357 352 | 
             
                          else
         | 
| 358 353 | 
             
                            raise GeneratorError, "#{self} not allowed in JSON"
         | 
| 359 354 | 
             
                          end
         | 
| 360 355 | 
             
                        when nan?
         | 
| 361 | 
            -
                          if  | 
| 356 | 
            +
                          if state && state.allow_nan?
         | 
| 362 357 | 
             
                            to_s
         | 
| 363 358 | 
             
                          else
         | 
| 364 359 | 
             
                            raise GeneratorError, "#{self} not allowed in JSON"
         | 
| @@ -370,18 +365,45 @@ module JSON | |
| 370 365 | 
             
                    end
         | 
| 371 366 |  | 
| 372 367 | 
             
                    module String
         | 
| 373 | 
            -
                       | 
| 374 | 
            -
             | 
| 375 | 
            -
             | 
| 376 | 
            -
             | 
| 377 | 
            -
                         | 
| 368 | 
            +
                      if defined?(::Encoding)
         | 
| 369 | 
            +
                        # This string should be encoded with UTF-8 A call to this method
         | 
| 370 | 
            +
                        # returns a JSON string encoded with UTF16 big endian characters as
         | 
| 371 | 
            +
                        # \u????.
         | 
| 372 | 
            +
                        def to_json(*args)
         | 
| 373 | 
            +
                          state, = *args
         | 
| 374 | 
            +
                          state ||= State.from_state(state)
         | 
| 375 | 
            +
                          if encoding == ::Encoding::UTF_8
         | 
| 376 | 
            +
                            string = self
         | 
| 377 | 
            +
                          else
         | 
| 378 | 
            +
                            string = encode(::Encoding::UTF_8)
         | 
| 379 | 
            +
                          end
         | 
| 380 | 
            +
                          if state.ascii_only?
         | 
| 381 | 
            +
                            '"' << JSON.utf8_to_json_ascii(string) << '"'
         | 
| 382 | 
            +
                          else
         | 
| 383 | 
            +
                            '"' << JSON.utf8_to_json(string) << '"'
         | 
| 384 | 
            +
                          end
         | 
| 385 | 
            +
                        end
         | 
| 386 | 
            +
                      else
         | 
| 387 | 
            +
                        # This string should be encoded with UTF-8 A call to this method
         | 
| 388 | 
            +
                        # returns a JSON string encoded with UTF16 big endian characters as
         | 
| 389 | 
            +
                        # \u????.
         | 
| 390 | 
            +
                        def to_json(*args)
         | 
| 391 | 
            +
                          state, = *args
         | 
| 392 | 
            +
                          state ||= State.from_state(state)
         | 
| 393 | 
            +
                          if state.ascii_only?
         | 
| 394 | 
            +
                            '"' << JSON.utf8_to_json_ascii(self) << '"'
         | 
| 395 | 
            +
                          else
         | 
| 396 | 
            +
                            '"' << JSON.utf8_to_json(self) << '"'
         | 
| 397 | 
            +
                          end
         | 
| 398 | 
            +
                        end
         | 
| 378 399 | 
             
                      end
         | 
| 379 400 |  | 
| 380 401 | 
             
                      # Module that holds the extinding methods if, the String module is
         | 
| 381 402 | 
             
                      # included.
         | 
| 382 403 | 
             
                      module Extend
         | 
| 383 | 
            -
                        # Raw Strings are JSON Objects (the raw bytes are stored in an | 
| 384 | 
            -
                        # key "raw"). The Ruby String can be created by this | 
| 404 | 
            +
                        # Raw Strings are JSON Objects (the raw bytes are stored in an
         | 
| 405 | 
            +
                        # array for the key "raw"). The Ruby String can be created by this
         | 
| 406 | 
            +
                        # module method.
         | 
| 385 407 | 
             
                        def json_create(o)
         | 
| 386 408 | 
             
                          o['raw'].pack('C*')
         | 
| 387 409 | 
             
                        end
         |