diff options
author | Jari Vetoniemi <jari.vetoniemi@indooratlas.com> | 2020-03-16 18:49:26 +0900 |
---|---|---|
committer | Jari Vetoniemi <jari.vetoniemi@indooratlas.com> | 2020-03-30 00:39:06 +0900 |
commit | fcbf63e62c627deae76c1b8cb8c0876c536ed811 (patch) | |
tree | 64cb17de3f41a2b6fef2368028fbd00349946994 /jni/ruby/ext/json/lib |
Fresh start
Diffstat (limited to 'jni/ruby/ext/json/lib')
-rw-r--r-- | jni/ruby/ext/json/lib/json.rb | 62 | ||||
-rw-r--r-- | jni/ruby/ext/json/lib/json/add/bigdecimal.rb | 28 | ||||
-rw-r--r-- | jni/ruby/ext/json/lib/json/add/complex.rb | 22 | ||||
-rw-r--r-- | jni/ruby/ext/json/lib/json/add/core.rb | 11 | ||||
-rw-r--r-- | jni/ruby/ext/json/lib/json/add/date.rb | 34 | ||||
-rw-r--r-- | jni/ruby/ext/json/lib/json/add/date_time.rb | 50 | ||||
-rw-r--r-- | jni/ruby/ext/json/lib/json/add/exception.rb | 31 | ||||
-rw-r--r-- | jni/ruby/ext/json/lib/json/add/ostruct.rb | 31 | ||||
-rw-r--r-- | jni/ruby/ext/json/lib/json/add/range.rb | 29 | ||||
-rw-r--r-- | jni/ruby/ext/json/lib/json/add/rational.rb | 22 | ||||
-rw-r--r-- | jni/ruby/ext/json/lib/json/add/regexp.rb | 30 | ||||
-rw-r--r-- | jni/ruby/ext/json/lib/json/add/struct.rb | 30 | ||||
-rw-r--r-- | jni/ruby/ext/json/lib/json/add/symbol.rb | 25 | ||||
-rw-r--r-- | jni/ruby/ext/json/lib/json/add/time.rb | 38 | ||||
-rw-r--r-- | jni/ruby/ext/json/lib/json/common.rb | 484 | ||||
-rw-r--r-- | jni/ruby/ext/json/lib/json/ext.rb | 21 | ||||
-rw-r--r-- | jni/ruby/ext/json/lib/json/generic_object.rb | 70 | ||||
-rw-r--r-- | jni/ruby/ext/json/lib/json/version.rb | 8 |
18 files changed, 1026 insertions, 0 deletions
diff --git a/jni/ruby/ext/json/lib/json.rb b/jni/ruby/ext/json/lib/json.rb new file mode 100644 index 0000000..24aa385 --- /dev/null +++ b/jni/ruby/ext/json/lib/json.rb @@ -0,0 +1,62 @@ +require 'json/common' + +## +# = JavaScript Object Notation (JSON) +# +# JSON is a lightweight data-interchange format. It is easy for us +# humans to read and write. Plus, equally simple for machines to generate or parse. +# JSON is completely language agnostic, making it the ideal interchange format. +# +# Built on two universally available structures: +# 1. A collection of name/value pairs. Often referred to as an _object_, hash table, record, struct, keyed list, or associative array. +# 2. An ordered list of values. More commonly called an _array_, vector, sequence or list. +# +# To read more about JSON visit: http://json.org +# +# == Parsing JSON +# +# To parse a JSON string received by another application or generated within +# your existing application: +# +# require 'json' +# +# my_hash = JSON.parse('{"hello": "goodbye"}') +# puts my_hash["hello"] => "goodbye" +# +# Notice the extra quotes <tt>''</tt> around the hash notation. Ruby expects +# the argument to be a string and can't convert objects like a hash or array. +# +# Ruby converts your string into a hash +# +# == Generating JSON +# +# Creating a JSON string for communication or serialization is +# just as simple. +# +# require 'json' +# +# my_hash = {:hello => "goodbye"} +# puts JSON.generate(my_hash) => "{\"hello\":\"goodbye\"}" +# +# Or an alternative way: +# +# require 'json' +# puts {:hello => "goodbye"}.to_json => "{\"hello\":\"goodbye\"}" +# +# <tt>JSON.generate</tt> only allows objects or arrays to be converted +# to JSON syntax. <tt>to_json</tt>, however, accepts many Ruby classes +# even though it acts only as a method for serialization: +# +# require 'json' +# +# 1.to_json => "1" +# +module JSON + require 'json/version' + + begin + require 'json/ext' + rescue LoadError + require 'json/pure' + end +end diff --git a/jni/ruby/ext/json/lib/json/add/bigdecimal.rb b/jni/ruby/ext/json/lib/json/add/bigdecimal.rb new file mode 100644 index 0000000..0ef69f1 --- /dev/null +++ b/jni/ruby/ext/json/lib/json/add/bigdecimal.rb @@ -0,0 +1,28 @@ +unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED + require 'json' +end +defined?(::BigDecimal) or require 'bigdecimal' + +class BigDecimal + # Import a JSON Marshalled object. + # + # method used for JSON marshalling support. + def self.json_create(object) + BigDecimal._load object['b'] + end + + # Marshal the object to JSON. + # + # method used for JSON marshalling support. + def as_json(*) + { + JSON.create_id => self.class.name, + 'b' => _dump, + } + end + + # return the JSON value + def to_json(*) + as_json.to_json + end +end diff --git a/jni/ruby/ext/json/lib/json/add/complex.rb b/jni/ruby/ext/json/lib/json/add/complex.rb new file mode 100644 index 0000000..d7ebebf --- /dev/null +++ b/jni/ruby/ext/json/lib/json/add/complex.rb @@ -0,0 +1,22 @@ +unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED + require 'json' +end +defined?(::Complex) or require 'complex' + +class Complex + def self.json_create(object) + Complex(object['r'], object['i']) + end + + def as_json(*) + { + JSON.create_id => self.class.name, + 'r' => real, + 'i' => imag, + } + end + + def to_json(*) + as_json.to_json + end +end diff --git a/jni/ruby/ext/json/lib/json/add/core.rb b/jni/ruby/ext/json/lib/json/add/core.rb new file mode 100644 index 0000000..77d9dc0 --- /dev/null +++ b/jni/ruby/ext/json/lib/json/add/core.rb @@ -0,0 +1,11 @@ +# This file requires the implementations of ruby core's custom objects for +# serialisation/deserialisation. + +require 'json/add/date' +require 'json/add/date_time' +require 'json/add/exception' +require 'json/add/range' +require 'json/add/regexp' +require 'json/add/struct' +require 'json/add/symbol' +require 'json/add/time' diff --git a/jni/ruby/ext/json/lib/json/add/date.rb b/jni/ruby/ext/json/lib/json/add/date.rb new file mode 100644 index 0000000..4288237 --- /dev/null +++ b/jni/ruby/ext/json/lib/json/add/date.rb @@ -0,0 +1,34 @@ +unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED + require 'json' +end +require 'date' + +# Date serialization/deserialization +class Date + + # Deserializes JSON string by converting Julian year <tt>y</tt>, month + # <tt>m</tt>, day <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> to Date. + def self.json_create(object) + civil(*object.values_at('y', 'm', 'd', 'sg')) + end + + alias start sg unless method_defined?(:start) + + # Returns a hash, that will be turned into a JSON object and represent this + # object. + def as_json(*) + { + JSON.create_id => self.class.name, + 'y' => year, + 'm' => month, + 'd' => day, + 'sg' => start, + } + end + + # Stores class name (Date) with Julian year <tt>y</tt>, month <tt>m</tt>, day + # <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string + def to_json(*args) + as_json.to_json(*args) + end +end diff --git a/jni/ruby/ext/json/lib/json/add/date_time.rb b/jni/ruby/ext/json/lib/json/add/date_time.rb new file mode 100644 index 0000000..5ea42ea --- /dev/null +++ b/jni/ruby/ext/json/lib/json/add/date_time.rb @@ -0,0 +1,50 @@ +unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED + require 'json' +end +require 'date' + +# DateTime serialization/deserialization +class DateTime + + # Deserializes JSON string by converting year <tt>y</tt>, month <tt>m</tt>, + # day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>, + # offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> to DateTime. + def self.json_create(object) + args = object.values_at('y', 'm', 'd', 'H', 'M', 'S') + of_a, of_b = object['of'].split('/') + if of_b and of_b != '0' + args << Rational(of_a.to_i, of_b.to_i) + else + args << of_a + end + args << object['sg'] + civil(*args) + end + + alias start sg unless method_defined?(:start) + + # Returns a hash, that will be turned into a JSON object and represent this + # object. + def as_json(*) + { + JSON.create_id => self.class.name, + 'y' => year, + 'm' => month, + 'd' => day, + 'H' => hour, + 'M' => min, + 'S' => sec, + 'of' => offset.to_s, + 'sg' => start, + } + end + + # Stores class name (DateTime) with Julian year <tt>y</tt>, month <tt>m</tt>, + # day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>, + # offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string + def to_json(*args) + as_json.to_json(*args) + end +end + + diff --git a/jni/ruby/ext/json/lib/json/add/exception.rb b/jni/ruby/ext/json/lib/json/add/exception.rb new file mode 100644 index 0000000..e6ad257 --- /dev/null +++ b/jni/ruby/ext/json/lib/json/add/exception.rb @@ -0,0 +1,31 @@ +unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED + require 'json' +end + +# Exception serialization/deserialization +class Exception + + # Deserializes JSON string by constructing new Exception object with message + # <tt>m</tt> and backtrace <tt>b</tt> serialized with <tt>to_json</tt> + def self.json_create(object) + result = new(object['m']) + result.set_backtrace object['b'] + result + end + + # Returns a hash, that will be turned into a JSON object and represent this + # object. + def as_json(*) + { + JSON.create_id => self.class.name, + 'm' => message, + 'b' => backtrace, + } + end + + # Stores class name (Exception) with message <tt>m</tt> and backtrace array + # <tt>b</tt> as JSON string + def to_json(*args) + as_json.to_json(*args) + end +end diff --git a/jni/ruby/ext/json/lib/json/add/ostruct.rb b/jni/ruby/ext/json/lib/json/add/ostruct.rb new file mode 100644 index 0000000..da81e10 --- /dev/null +++ b/jni/ruby/ext/json/lib/json/add/ostruct.rb @@ -0,0 +1,31 @@ +unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED + require 'json' +end +require 'ostruct' + +# OpenStruct serialization/deserialization +class OpenStruct + + # Deserializes JSON string by constructing new Struct object with values + # <tt>v</tt> serialized by <tt>to_json</tt>. + def self.json_create(object) + new(object['t'] || object[:t]) + end + + # Returns a hash, that will be turned into a JSON object and represent this + # object. + def as_json(*) + klass = self.class.name + klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!" + { + JSON.create_id => klass, + 't' => table, + } + end + + # Stores class name (OpenStruct) with this struct's values <tt>v</tt> as a + # JSON string. + def to_json(*args) + as_json.to_json(*args) + end +end diff --git a/jni/ruby/ext/json/lib/json/add/range.rb b/jni/ruby/ext/json/lib/json/add/range.rb new file mode 100644 index 0000000..e61e553 --- /dev/null +++ b/jni/ruby/ext/json/lib/json/add/range.rb @@ -0,0 +1,29 @@ +unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED + require 'json' +end + +# Range serialization/deserialization +class Range + + # Deserializes JSON string by constructing new Range object with arguments + # <tt>a</tt> serialized by <tt>to_json</tt>. + def self.json_create(object) + new(*object['a']) + end + + # Returns a hash, that will be turned into a JSON object and represent this + # object. + def as_json(*) + { + JSON.create_id => self.class.name, + 'a' => [ first, last, exclude_end? ] + } + end + + # Stores class name (Range) with JSON array of arguments <tt>a</tt> which + # include <tt>first</tt> (integer), <tt>last</tt> (integer), and + # <tt>exclude_end?</tt> (boolean) as JSON string. + def to_json(*args) + as_json.to_json(*args) + end +end diff --git a/jni/ruby/ext/json/lib/json/add/rational.rb b/jni/ruby/ext/json/lib/json/add/rational.rb new file mode 100644 index 0000000..867cd92 --- /dev/null +++ b/jni/ruby/ext/json/lib/json/add/rational.rb @@ -0,0 +1,22 @@ +unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED + require 'json' +end +defined?(::Rational) or require 'rational' + +class Rational + def self.json_create(object) + Rational(object['n'], object['d']) + end + + def as_json(*) + { + JSON.create_id => self.class.name, + 'n' => numerator, + 'd' => denominator, + } + end + + def to_json(*) + as_json.to_json + end +end diff --git a/jni/ruby/ext/json/lib/json/add/regexp.rb b/jni/ruby/ext/json/lib/json/add/regexp.rb new file mode 100644 index 0000000..2fcbb6f --- /dev/null +++ b/jni/ruby/ext/json/lib/json/add/regexp.rb @@ -0,0 +1,30 @@ +unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED + require 'json' +end + +# Regexp serialization/deserialization +class Regexp + + # Deserializes JSON string by constructing new Regexp object with source + # <tt>s</tt> (Regexp or String) and options <tt>o</tt> serialized by + # <tt>to_json</tt> + def self.json_create(object) + new(object['s'], object['o']) + end + + # Returns a hash, that will be turned into a JSON object and represent this + # object. + def as_json(*) + { + JSON.create_id => self.class.name, + 'o' => options, + 's' => source, + } + end + + # Stores class name (Regexp) with options <tt>o</tt> and source <tt>s</tt> + # (Regexp or String) as JSON string + def to_json(*) + as_json.to_json + end +end diff --git a/jni/ruby/ext/json/lib/json/add/struct.rb b/jni/ruby/ext/json/lib/json/add/struct.rb new file mode 100644 index 0000000..6847cde --- /dev/null +++ b/jni/ruby/ext/json/lib/json/add/struct.rb @@ -0,0 +1,30 @@ +unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED + require 'json' +end + +# Struct serialization/deserialization +class Struct + + # Deserializes JSON string by constructing new Struct object with values + # <tt>v</tt> serialized by <tt>to_json</tt>. + def self.json_create(object) + new(*object['v']) + end + + # Returns a hash, that will be turned into a JSON object and represent this + # object. + def as_json(*) + klass = self.class.name + klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!" + { + JSON.create_id => klass, + 'v' => values, + } + end + + # Stores class name (Struct) with Struct values <tt>v</tt> as a JSON string. + # Only named structs are supported. + def to_json(*args) + as_json.to_json(*args) + end +end diff --git a/jni/ruby/ext/json/lib/json/add/symbol.rb b/jni/ruby/ext/json/lib/json/add/symbol.rb new file mode 100644 index 0000000..03dc9a5 --- /dev/null +++ b/jni/ruby/ext/json/lib/json/add/symbol.rb @@ -0,0 +1,25 @@ +unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED + require 'json' +end + +# Symbol serialization/deserialization +class Symbol + # Returns a hash, that will be turned into a JSON object and represent this + # object. + def as_json(*) + { + JSON.create_id => self.class.name, + 's' => to_s, + } + end + + # Stores class name (Symbol) with String representation of Symbol as a JSON string. + def to_json(*a) + as_json.to_json(*a) + end + + # Deserializes JSON string by converting the <tt>string</tt> value stored in the object to a Symbol + def self.json_create(o) + o['s'].to_sym + end +end diff --git a/jni/ruby/ext/json/lib/json/add/time.rb b/jni/ruby/ext/json/lib/json/add/time.rb new file mode 100644 index 0000000..338209d --- /dev/null +++ b/jni/ruby/ext/json/lib/json/add/time.rb @@ -0,0 +1,38 @@ +unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED + require 'json' +end + +# Time serialization/deserialization +class Time + + # Deserializes JSON string by converting time since epoch to Time + def self.json_create(object) + if usec = object.delete('u') # used to be tv_usec -> tv_nsec + object['n'] = usec * 1000 + end + if instance_methods.include?(:tv_nsec) + at(object['s'], Rational(object['n'], 1000)) + else + at(object['s'], object['n'] / 1000) + end + end + + # Returns a hash, that will be turned into a JSON object and represent this + # object. + def as_json(*) + nanoseconds = [ tv_usec * 1000 ] + respond_to?(:tv_nsec) and nanoseconds << tv_nsec + nanoseconds = nanoseconds.max + { + JSON.create_id => self.class.name, + 's' => tv_sec, + 'n' => nanoseconds, + } + end + + # Stores class name (Time) with number of seconds since epoch and number of + # microseconds for Time as JSON string + def to_json(*args) + as_json.to_json(*args) + end +end diff --git a/jni/ruby/ext/json/lib/json/common.rb b/jni/ruby/ext/json/lib/json/common.rb new file mode 100644 index 0000000..8fbaa2b --- /dev/null +++ b/jni/ruby/ext/json/lib/json/common.rb @@ -0,0 +1,484 @@ +require 'json/version' +require 'json/generic_object' + +module JSON + class << self + # If _object_ is string-like, parse the string and return the parsed result + # as a Ruby data structure. Otherwise generate a JSON text from the Ruby + # data structure object and return it. + # + # The _opts_ argument is passed through to generate/parse respectively. See + # generate and parse for their documentation. + def [](object, opts = {}) + if object.respond_to? :to_str + JSON.parse(object.to_str, opts) + else + JSON.generate(object, opts) + end + end + + # Returns the JSON parser class that is used by JSON. This is either + # JSON::Ext::Parser or JSON::Pure::Parser. + attr_reader :parser + + # Set the JSON parser class _parser_ to be used by JSON. + def parser=(parser) # :nodoc: + @parser = parser + remove_const :Parser if JSON.const_defined_in?(self, :Parser) + const_set :Parser, parser + end + + # Return the constant located at _path_. The format of _path_ has to be + # either ::A::B::C or A::B::C. In any case, A has to be located at the top + # level (absolute namespace path?). If there doesn't exist a constant at + # the given path, an ArgumentError is raised. + def deep_const_get(path) # :nodoc: + path.to_s.split(/::/).inject(Object) do |p, c| + case + when c.empty? then p + when JSON.const_defined_in?(p, c) then p.const_get(c) + else + begin + p.const_missing(c) + rescue NameError => e + raise ArgumentError, "can't get const #{path}: #{e}" + end + end + end + end + + # Set the module _generator_ to be used by JSON. + def generator=(generator) # :nodoc: + old, $VERBOSE = $VERBOSE, nil + @generator = generator + generator_methods = generator::GeneratorMethods + for const in generator_methods.constants + klass = deep_const_get(const) + modul = generator_methods.const_get(const) + klass.class_eval do + instance_methods(false).each do |m| + m.to_s == 'to_json' and remove_method m + end + include modul + end + end + self.state = generator::State + const_set :State, self.state + const_set :SAFE_STATE_PROTOTYPE, State.new + const_set :FAST_STATE_PROTOTYPE, State.new( + :indent => '', + :space => '', + :object_nl => "", + :array_nl => "", + :max_nesting => false + ) + const_set :PRETTY_STATE_PROTOTYPE, State.new( + :indent => ' ', + :space => ' ', + :object_nl => "\n", + :array_nl => "\n" + ) + ensure + $VERBOSE = old + end + + # Returns the JSON generator module that is used by JSON. This is + # either JSON::Ext::Generator or JSON::Pure::Generator. + attr_reader :generator + + # Returns the JSON generator state class that is used by JSON. This is + # either JSON::Ext::Generator::State or JSON::Pure::Generator::State. + attr_accessor :state + + # This is create identifier, which is used to decide if the _json_create_ + # hook of a class should be called. It defaults to 'json_class'. + attr_accessor :create_id + end + self.create_id = 'json_class' + + NaN = 0.0/0 + + Infinity = 1.0/0 + + MinusInfinity = -Infinity + + # The base exception for JSON errors. + class JSONError < StandardError + def self.wrap(exception) + obj = new("Wrapped(#{exception.class}): #{exception.message.inspect}") + obj.set_backtrace exception.backtrace + obj + end + end + + # This exception is raised if a parser error occurs. + class ParserError < JSONError; end + + # This exception is raised if the nesting of parsed data structures is too + # deep. + class NestingError < ParserError; end + + # :stopdoc: + class CircularDatastructure < NestingError; end + # :startdoc: + + # This exception is raised if a generator or unparser error occurs. + class GeneratorError < JSONError; end + # For backwards compatibility + UnparserError = GeneratorError + + # This exception is raised if the required unicode support is missing on the + # system. Usually this means that the iconv library is not installed. + class MissingUnicodeSupport < JSONError; end + + module_function + + # Parse the JSON document _source_ into a Ruby data structure and return it. + # + # _opts_ can have the following + # keys: + # * *max_nesting*: The maximum depth of nesting allowed in the parsed data + # structures. Disable depth checking with :max_nesting => false. It defaults + # to 100. + # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in + # defiance of RFC 4627 to be parsed by the Parser. This option defaults + # to false. + # * *symbolize_names*: If set to true, returns symbols for the names + # (keys) in a JSON object. Otherwise strings are returned. Strings are + # the default. + # * *create_additions*: If set to false, the Parser doesn't create + # additions even if a matching class and create_id was found. This option + # defaults to true. + # * *object_class*: Defaults to Hash + # * *array_class*: Defaults to Array + def parse(source, opts = {}) + Parser.new(source, opts).parse + end + + # Parse the JSON document _source_ into a Ruby data structure and return it. + # The bang version of the parse method defaults to the more dangerous values + # for the _opts_ hash, so be sure only to parse trusted _source_ documents. + # + # _opts_ can have the following keys: + # * *max_nesting*: The maximum depth of nesting allowed in the parsed data + # structures. Enable depth checking with :max_nesting => anInteger. The parse! + # methods defaults to not doing max depth checking: This can be dangerous + # if someone wants to fill up your stack. + # * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in + # defiance of RFC 4627 to be parsed by the Parser. This option defaults + # to true. + # * *create_additions*: If set to false, the Parser doesn't create + # additions even if a matching class and create_id was found. This option + # defaults to true. + def parse!(source, opts = {}) + opts = { + :max_nesting => false, + :allow_nan => true + }.update(opts) + Parser.new(source, opts).parse + end + + # Generate a JSON document from the Ruby data structure _obj_ and return + # it. _state_ is * a JSON::State object, + # * or a Hash like object (responding to to_hash), + # * an object convertible into a hash by a to_h method, + # that is used as or to configure a State object. + # + # It defaults to a state object, that creates the shortest possible JSON text + # in one line, checks for circular data structures and doesn't allow NaN, + # Infinity, and -Infinity. + # + # A _state_ hash can have the following keys: + # * *indent*: a string used to indent levels (default: ''), + # * *space*: a string that is put after, a : or , delimiter (default: ''), + # * *space_before*: a string that is put before a : pair delimiter (default: ''), + # * *object_nl*: a string that is put at the end of a JSON object (default: ''), + # * *array_nl*: a string that is put at the end of a JSON array (default: ''), + # * *allow_nan*: true if NaN, Infinity, and -Infinity should be + # generated, otherwise an exception is thrown if these values are + # encountered. This options defaults to false. + # * *max_nesting*: The maximum depth of nesting allowed in the data + # structures from which JSON is to be generated. Disable depth checking + # with :max_nesting => false, it defaults to 100. + # + # See also the fast_generate for the fastest creation method with the least + # amount of sanity checks, and the pretty_generate method for some + # defaults for pretty output. + def generate(obj, opts = nil) + if State === opts + state, opts = opts, nil + else + state = SAFE_STATE_PROTOTYPE.dup + end + if opts + if opts.respond_to? :to_hash + opts = opts.to_hash + elsif opts.respond_to? :to_h + opts = opts.to_h + else + raise TypeError, "can't convert #{opts.class} into Hash" + end + state = state.configure(opts) + end + state.generate(obj) + end + + # :stopdoc: + # I want to deprecate these later, so I'll first be silent about them, and + # later delete them. + alias unparse generate + module_function :unparse + # :startdoc: + + # Generate a JSON document from the Ruby data structure _obj_ and return it. + # This method disables the checks for circles in Ruby objects. + # + # *WARNING*: Be careful not to pass any Ruby data structures with circles as + # _obj_ argument because this will cause JSON to go into an infinite loop. + def fast_generate(obj, opts = nil) + if State === opts + state, opts = opts, nil + else + state = FAST_STATE_PROTOTYPE.dup + end + if opts + if opts.respond_to? :to_hash + opts = opts.to_hash + elsif opts.respond_to? :to_h + opts = opts.to_h + else + raise TypeError, "can't convert #{opts.class} into Hash" + end + state.configure(opts) + end + state.generate(obj) + end + + # :stopdoc: + # I want to deprecate these later, so I'll first be silent about them, and later delete them. + alias fast_unparse fast_generate + module_function :fast_unparse + # :startdoc: + + # Generate a JSON document from the Ruby data structure _obj_ and return it. + # The returned document is a prettier form of the document returned by + # #unparse. + # + # The _opts_ argument can be used to configure the generator. See the + # generate method for a more detailed explanation. + def pretty_generate(obj, opts = nil) + if State === opts + state, opts = opts, nil + else + state = PRETTY_STATE_PROTOTYPE.dup + end + if opts + if opts.respond_to? :to_hash + opts = opts.to_hash + elsif opts.respond_to? :to_h + opts = opts.to_h + else + raise TypeError, "can't convert #{opts.class} into Hash" + end + state.configure(opts) + end + state.generate(obj) + end + + # :stopdoc: + # I want to deprecate these later, so I'll first be silent about them, and later delete them. + alias pretty_unparse pretty_generate + module_function :pretty_unparse + # :startdoc: + + class << self + # The global default options for the JSON.load method: + # :max_nesting: false + # :allow_nan: true + # :quirks_mode: true + attr_accessor :load_default_options + end + self.load_default_options = { + :max_nesting => false, + :allow_nan => true, + :quirks_mode => true, + :create_additions => true, + } + + # Load a ruby data structure from a JSON _source_ and return it. A source can + # either be a string-like object, an IO-like object, or an object responding + # to the read method. If _proc_ was given, it will be called with any nested + # Ruby object as an argument recursively in depth first order. To modify the + # default options pass in the optional _options_ argument as well. + # + # BEWARE: This method is meant to serialise data from trusted user input, + # like from your own database server or clients under your control, it could + # be dangerous to allow untrusted users to pass JSON sources into it. The + # default options for the parser can be changed via the load_default_options + # method. + # + # This method is part of the implementation of the load/dump interface of + # Marshal and YAML. + def load(source, proc = nil, options = {}) + opts = load_default_options.merge options + if source.respond_to? :to_str + source = source.to_str + elsif source.respond_to? :to_io + source = source.to_io.read + elsif source.respond_to?(:read) + source = source.read + end + if opts[:quirks_mode] && (source.nil? || source.empty?) + source = 'null' + end + result = parse(source, opts) + recurse_proc(result, &proc) if proc + result + end + + # Recursively calls passed _Proc_ if the parsed data structure is an _Array_ or _Hash_ + def recurse_proc(result, &proc) + case result + when Array + result.each { |x| recurse_proc x, &proc } + proc.call result + when Hash + result.each { |x, y| recurse_proc x, &proc; recurse_proc y, &proc } + proc.call result + else + proc.call result + end + end + + alias restore load + module_function :restore + + class << self + # The global default options for the JSON.dump method: + # :max_nesting: false + # :allow_nan: true + # :quirks_mode: true + attr_accessor :dump_default_options + end + self.dump_default_options = { + :max_nesting => false, + :allow_nan => true, + :quirks_mode => true, + } + + # Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns + # the result. + # + # If anIO (an IO-like object or an object that responds to the write method) + # was given, the resulting JSON is written to it. + # + # If the number of nested arrays or objects exceeds _limit_, an ArgumentError + # exception is raised. This argument is similar (but not exactly the + # same!) to the _limit_ argument in Marshal.dump. + # + # The default options for the generator can be changed via the + # dump_default_options method. + # + # This method is part of the implementation of the load/dump interface of + # Marshal and YAML. + def dump(obj, anIO = nil, limit = nil) + if anIO and limit.nil? + anIO = anIO.to_io if anIO.respond_to?(:to_io) + unless anIO.respond_to?(:write) + limit = anIO + anIO = nil + end + end + opts = JSON.dump_default_options + limit and opts.update(:max_nesting => limit) + result = generate(obj, opts) + if anIO + anIO.write result + anIO + else + result + end + rescue JSON::NestingError + raise ArgumentError, "exceed depth limit" + end + + # Swap consecutive bytes of _string_ in place. + def self.swap!(string) # :nodoc: + 0.upto(string.size / 2) do |i| + break unless string[2 * i + 1] + string[2 * i], string[2 * i + 1] = string[2 * i + 1], string[2 * i] + end + string + end + + # Shortuct for iconv. + if ::String.method_defined?(:encode) + # Encodes string using Ruby's _String.encode_ + def self.iconv(to, from, string) + string.encode(to, from) + end + else + require 'iconv' + # Encodes string using _iconv_ library + def self.iconv(to, from, string) + Iconv.conv(to, from, string) + end + end + + if ::Object.method(:const_defined?).arity == 1 + def self.const_defined_in?(modul, constant) + modul.const_defined?(constant) + end + else + def self.const_defined_in?(modul, constant) + modul.const_defined?(constant, false) + end + end +end + +module ::Kernel + private + + # Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in + # one line. + def j(*objs) + objs.each do |obj| + puts JSON::generate(obj, :allow_nan => true, :max_nesting => false) + end + nil + end + + # Outputs _objs_ to STDOUT as JSON strings in a pretty format, with + # indentation and over many lines. + def jj(*objs) + objs.each do |obj| + puts JSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false) + end + nil + end + + # If _object_ is string-like, parse the string and return the parsed result as + # a Ruby data structure. Otherwise, generate a JSON text from the Ruby data + # structure object and return it. + # + # The _opts_ argument is passed through to generate/parse respectively. See + # generate and parse for their documentation. + def JSON(object, *args) + if object.respond_to? :to_str + JSON.parse(object.to_str, args.first) + else + JSON.generate(object, args.first) + end + end +end + +# Extends any Class to include _json_creatable?_ method. +class ::Class + # Returns true if this class can be used to create an instance + # from a serialised JSON string. The class has to implement a class + # method _json_create_ that expects a hash as first parameter. The hash + # should include the required data. + def json_creatable? + respond_to?(:json_create) + end +end diff --git a/jni/ruby/ext/json/lib/json/ext.rb b/jni/ruby/ext/json/lib/json/ext.rb new file mode 100644 index 0000000..c5f8131 --- /dev/null +++ b/jni/ruby/ext/json/lib/json/ext.rb @@ -0,0 +1,21 @@ +if ENV['SIMPLECOV_COVERAGE'].to_i == 1 + require 'simplecov' + SimpleCov.start do + add_filter "/tests/" + end +end +require 'json/common' + +module JSON + # This module holds all the modules/classes that implement JSON's + # functionality as C extensions. + module Ext + require 'json/ext/parser' + require 'json/ext/generator' + $DEBUG and warn "Using Ext extension for JSON." + JSON.parser = Parser + JSON.generator = Generator + end + + JSON_LOADED = true unless defined?(::JSON::JSON_LOADED) +end diff --git a/jni/ruby/ext/json/lib/json/generic_object.rb b/jni/ruby/ext/json/lib/json/generic_object.rb new file mode 100644 index 0000000..8b8fd53 --- /dev/null +++ b/jni/ruby/ext/json/lib/json/generic_object.rb @@ -0,0 +1,70 @@ +require 'ostruct' + +module JSON + class GenericObject < OpenStruct + class << self + alias [] new + + def json_creatable? + @json_creatable + end + + attr_writer :json_creatable + + def json_create(data) + data = data.dup + data.delete JSON.create_id + self[data] + end + + def from_hash(object) + case + when object.respond_to?(:to_hash) + result = new + object.to_hash.each do |key, value| + result[key] = from_hash(value) + end + result + when object.respond_to?(:to_ary) + object.to_ary.map { |a| from_hash(a) } + else + object + end + end + + def load(source, proc = nil, opts = {}) + result = ::JSON.load(source, proc, opts.merge(:object_class => self)) + result.nil? ? new : result + end + + def dump(obj, *args) + ::JSON.dump(obj, *args) + end + end + self.json_creatable = false + + def to_hash + table + end + + def [](name) + table[name.to_sym] + end + + def []=(name, value) + __send__ "#{name}=", value + end + + def |(other) + self.class[other.to_hash.merge(to_hash)] + end + + def as_json(*) + { JSON.create_id => self.class.name }.merge to_hash + end + + def to_json(*a) + as_json.to_json(*a) + end + end +end diff --git a/jni/ruby/ext/json/lib/json/version.rb b/jni/ruby/ext/json/lib/json/version.rb new file mode 100644 index 0000000..47cdcd6 --- /dev/null +++ b/jni/ruby/ext/json/lib/json/version.rb @@ -0,0 +1,8 @@ +module JSON + # JSON version + VERSION = '1.8.1' + VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc: + VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc: + VERSION_MINOR = VERSION_ARRAY[1] # :nodoc: + VERSION_BUILD = VERSION_ARRAY[2] # :nodoc: +end |