RFC8259 8259
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.
- checksums.yaml +7 -0
- data/.gitignore +61 -0
- data/.rspec +4 -0
- data/.yardopts +2 -0
- data/Gemfile +58 -0
- data/LICENSE.txt +40 -0
- data/README.txt +1 -0
- data/RFC8259 +899 -0
- data/RFC8259.gemspec +89 -0
- data/Rakefile +86 -0
- data/lib/RFC8259.rb +94 -0
- data/lib/RFC8259/array.rb +136 -0
- data/lib/RFC8259/dumper.rb +255 -0
- data/lib/RFC8259/false.rb +79 -0
- data/lib/RFC8259/null.rb +79 -0
- data/lib/RFC8259/number.rb +149 -0
- data/lib/RFC8259/object.rb +137 -0
- data/lib/RFC8259/parser.ry +275 -0
- data/lib/RFC8259/string.rb +226 -0
- data/lib/RFC8259/true.rb +79 -0
- data/lib/RFC8259/value.rb +96 -0
- data/lib/RFC8259/version.rb +46 -0
- data/spec/RFC8259_spec.rb +305 -0
- data/spec/acceptance/README.txt +66 -0
- data/spec/acceptance/invalid/0001-ws/0001-verical-tab.txt +1 -0
- data/spec/acceptance/invalid/0001-ws/0002-null.txt +0 -0
- data/spec/acceptance/invalid/0001-ws/0003-space-in-number-1.txt +1 -0
- data/spec/acceptance/invalid/0001-ws/0004-space-in-number-2.txt +1 -0
- data/spec/acceptance/invalid/0001-ws/0005-space-in-number-3.txt +1 -0
- data/spec/acceptance/invalid/0001-ws/0006-space-in-number-4.txt +1 -0
- data/spec/acceptance/invalid/0001-ws/0007-space-in-number-5.txt +1 -0
- data/spec/acceptance/invalid/0001-ws/0008-space-in-number-6.txt +1 -0
- data/spec/acceptance/invalid/0001-ws/0009-space-in-literal.txt +1 -0
- data/spec/acceptance/invalid/0001-ws/0010-Unicode-LINE_SEPARATOR.txt +1 -0
- data/spec/acceptance/invalid/0002-comments/0001-C-style.txt +1 -0
- data/spec/acceptance/invalid/0002-comments/0002-C-plusplus-style.txt +2 -0
- data/spec/acceptance/invalid/0002-comments/0003-sh-style.txt +2 -0
- data/spec/acceptance/invalid/0002-comments/0004-python-docstring.txt +3 -0
- data/spec/acceptance/invalid/0002-comments/0005-SQL-style.txt +2 -0
- data/spec/acceptance/invalid/0002-comments/0006-BASIC-style.txt +2 -0
- data/spec/acceptance/invalid/0003-literals/0001-FALSE.txt +1 -0
- data/spec/acceptance/invalid/0003-literals/0002-NULL.txt +1 -0
- data/spec/acceptance/invalid/0003-literals/0003-TRUE.txt +1 -0
- data/spec/acceptance/invalid/0003-literals/0004-NUL.txt +1 -0
- data/spec/acceptance/invalid/0003-literals/0005-nil.txt +1 -0
- data/spec/acceptance/invalid/0003-literals/0006-undef.txt +1 -0
- data/spec/acceptance/invalid/0003-literals/0007-modifier.txt +1 -0
- data/spec/acceptance/invalid/0003-literals/0008-undefined.txt +1 -0
- data/spec/acceptance/invalid/0004-numbers/0001-omit-zero.txt +1 -0
- data/spec/acceptance/invalid/0004-numbers/0002-minus-dot.txt +1 -0
- data/spec/acceptance/invalid/0004-numbers/0003-missing-frac.txt +1 -0
- data/spec/acceptance/invalid/0004-numbers/0004-missing-exp.txt +1 -0
- data/spec/acceptance/invalid/0004-numbers/0005-octal.txt +1 -0
- data/spec/acceptance/invalid/0004-numbers/0006-hexadecimal.txt +1 -0
- data/spec/acceptance/invalid/0004-numbers/0007-comma.txt +1 -0
- data/spec/acceptance/invalid/0004-numbers/0008-perl-underscore.txt +1 -0
- data/spec/acceptance/invalid/0004-numbers/0009-NaN.txt +1 -0
- data/spec/acceptance/invalid/0004-numbers/0010-Inf.txt +1 -0
- data/spec/acceptance/invalid/0004-numbers/0011-Infinity.txt +1 -0
- data/spec/acceptance/invalid/0005-strings/0000-NUL.txt +0 -0
- data/spec/acceptance/invalid/0005-strings/0001-not-terminated.txt +1 -0
- data/spec/acceptance/invalid/0005-strings/0002-single-quote.txt +1 -0
- data/spec/acceptance/invalid/0005-strings/0003-back-quote.txt +1 -0
- data/spec/acceptance/invalid/0005-strings/0004-carriage-return.txt +1 -0
- data/spec/acceptance/invalid/0005-strings/0005-line-feed.txt +2 -0
- data/spec/acceptance/invalid/0005-strings/0006-unknown-escape-a.txt +1 -0
- data/spec/acceptance/invalid/0005-strings/0007-unknown-escape-perl-style.txt +1 -0
- data/spec/acceptance/invalid/0005-strings/0008-unknown-escape-C-style.txt +1 -0
- data/spec/acceptance/invalid/0005-strings/0009-unknown-escape-ruby-style.txt +1 -0
- data/spec/acceptance/invalid/0005-strings/0010-escape-too-short.txt +1 -0
- data/spec/acceptance/invalid/0005-strings/0011-C-string-concat.txt +1 -0
- data/spec/acceptance/invalid/0005-strings/0012-perl-string-concat.txt +1 -0
- data/spec/acceptance/invalid/0005-strings/0013-Java-string-concat.txt +1 -0
- data/spec/acceptance/invalid/0006-encodings/0001-CESU-8.txt +1 -0
- data/spec/acceptance/invalid/0006-encodings/0002-Windows-31J.txt +1 -0
- data/spec/acceptance/invalid/0006-encodings/0003-EBCDIC.txt +1 -0
- data/spec/acceptance/invalid/0006-encodings/0004-overlong-utf8.txt +1 -0
- data/spec/acceptance/invalid/0007-arrays/0001-lacks-open.txt +1 -0
- data/spec/acceptance/invalid/0007-arrays/0002-lacks-close.txt +1 -0
- data/spec/acceptance/invalid/0007-arrays/0003-interleaving-parens.txt +1 -0
- data/spec/acceptance/invalid/0007-arrays/0004-dangling-comma.txt +1 -0
- data/spec/acceptance/invalid/0007-arrays/0005-missing-comma.txt +1 -0
- data/spec/acceptance/invalid/0007-arrays/0006-colon-instead-of-comma.txt +1 -0
- data/spec/acceptance/invalid/0008-hashes/0001-key-missing.txt +1 -0
- data/spec/acceptance/invalid/0008-hashes/0002-value-missing.txt +1 -0
- data/spec/acceptance/invalid/0008-hashes/0003-true-key.txt +1 -0
- data/spec/acceptance/invalid/0008-hashes/0004-false-key.txt +1 -0
- data/spec/acceptance/invalid/0008-hashes/0005-null-key.txt +1 -0
- data/spec/acceptance/invalid/0008-hashes/0006-numeric-key.txt +1 -0
- data/spec/acceptance/invalid/0008-hashes/0007-array-key.txt +1 -0
- data/spec/acceptance/invalid/0008-hashes/0008-hash-key.txt +1 -0
- data/spec/acceptance/invalid/0008-hashes/0009-key-not-escaped.txt +4 -0
- data/spec/acceptance/invalid/0009-javascriptisms/0001-JSONP.txt +1 -0
- data/spec/acceptance/invalid/0009-javascriptisms/0002-new-Array.txt +3 -0
- data/spec/acceptance/invalid/0009-javascriptisms/0003-new-Date.txt +1 -0
- data/spec/acceptance/invalid/0009-javascriptisms/0004-new-Error.txt +1 -0
- data/spec/acceptance/invalid/0009-javascriptisms/0005-Math.txt +1 -0
- data/spec/acceptance/invalid/0009-javascriptisms/0006-regular-expression.txt +1 -0
- data/spec/acceptance/invalid/0009-javascriptisms/0007-function.txt +7 -0
- data/spec/acceptance/invalid/0009-javascriptisms/0008-this.txt +1 -0
- data/spec/acceptance/invalid/0009-javascriptisms/0009-plusplus.txt +3 -0
- data/spec/acceptance/invalid/0009-javascriptisms/0010-ternary-operator.txt +1 -0
- data/spec/acceptance/valid/0001-ws/0001-space.json +1 -0
- data/spec/acceptance/valid/0001-ws/0002-tab.json +1 -0
- data/spec/acceptance/valid/0001-ws/0003-lf.json +1 -0
- data/spec/acceptance/valid/0001-ws/0004-cr.json +1 -0
- data/spec/acceptance/valid/0001-ws/0005-before.json +1 -0
- data/spec/acceptance/valid/0001-ws/0006-after.json +1 -0
- data/spec/acceptance/valid/0001-ws/0007-around-comma.json +3 -0
- data/spec/acceptance/valid/0001-ws/0008-around-colon.json +3 -0
- data/spec/acceptance/valid/0002-bare-values/0001-false.json +1 -0
- data/spec/acceptance/valid/0002-bare-values/0002-null.json +1 -0
- data/spec/acceptance/valid/0002-bare-values/0003-true.json +1 -0
- data/spec/acceptance/valid/0002-bare-values/0004-number.json +1 -0
- data/spec/acceptance/valid/0002-bare-values/0005-string.json +1 -0
- data/spec/acceptance/valid/0003-literals/0001-false.json +1 -0
- data/spec/acceptance/valid/0003-literals/0002-null.json +1 -0
- data/spec/acceptance/valid/0003-literals/0003-true.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0000-zero.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0001-one.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0002-two.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0003-three.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0004-four.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0005-five.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0006-six.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0007-seven.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0008-eight.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0009-nine.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0010-ten.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0011-minus.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0012-fraction.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0013-exponent.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0014-exponent-minus.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0015-exponent-plus.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0016-complex.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0017-DBL_MAX.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0018-DBL_MIN.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0019-subnormal-number.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0020-1E400.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0021-pi.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0022-UINT32_MAX.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0023-UINT64_MAX.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0024-INT64_MIN.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0025-high-resolution-zero.json +1 -0
- data/spec/acceptance/valid/0004-numbers/0026-high-resolution-100.json +1 -0
- data/spec/acceptance/valid/0005-strings/0001-empty.json +1 -0
- data/spec/acceptance/valid/0005-strings/0002-basic-latin.json +1 -0
- data/spec/acceptance/valid/0005-strings/0003-escapes.json +1 -0
- data/spec/acceptance/valid/0005-strings/0004-raw-unicode.json +1 -0
- data/spec/acceptance/valid/0005-strings/0005-escaped-unicode.json +1 -0
- data/spec/acceptance/valid/0005-strings/0006-escaped-NUL.json +1 -0
- data/spec/acceptance/valid/0005-strings/0007-escaped-invalid-unicode-still-valid-as-json.json +1 -0
- data/spec/acceptance/valid/0005-strings/0008-ruby-json-gem-cant-handle-this.json +1 -0
- data/spec/acceptance/valid/0005-strings/0009-unescaped-invalid-javascript-still-valid-as-json.json +1 -0
- data/spec/acceptance/valid/0005-strings/0010-escaped-separated-surrogate.json +1 -0
- data/spec/acceptance/valid/0005-strings/0011-escaped-surrogate-then-normal.json +1 -0
- data/spec/acceptance/valid/0006-m17n/0001-genesis.json +6 -0
- data/spec/acceptance/valid/0006-m17n/0002-heart-sutra.json +5 -0
- data/spec/acceptance/valid/0006-m17n/0003-escaped-valid-surrogate-pair.json +1 -0
- data/spec/acceptance/valid/0006-m17n/0004-unescaped-valid-supplementary-multilingual-plane.json +1 -0
- data/spec/acceptance/valid/0007-arrays/0000-empty.json +1 -0
- data/spec/acceptance/valid/0007-arrays/0001-one-element.json +1 -0
- data/spec/acceptance/valid/0007-arrays/0002-multiple-elements.json +33 -0
- data/spec/acceptance/valid/0007-arrays/0003-various-types.json +1 -0
- data/spec/acceptance/valid/0007-arrays/0004-nested.json +17 -0
- data/spec/acceptance/valid/0008-hashes/0000-empty.json +1 -0
- data/spec/acceptance/valid/0008-hashes/0001-onekey.json +1 -0
- data/spec/acceptance/valid/0008-hashes/0002-many-keys.json +5 -0
- data/spec/acceptance/valid/0008-hashes/0003-empty-key.json +3 -0
- data/spec/acceptance/valid/0008-hashes/0004-true-value.json +3 -0
- data/spec/acceptance/valid/0008-hashes/0005-false-value.json +3 -0
- data/spec/acceptance/valid/0008-hashes/0006-null-value.json +3 -0
- data/spec/acceptance/valid/0008-hashes/0007-string-value.json +3 -0
- data/spec/acceptance/valid/0008-hashes/0008-numeric-value.json +3 -0
- data/spec/acceptance/valid/0008-hashes/0009-array-value.json +8 -0
- data/spec/acceptance/valid/0008-hashes/0010-hash-value.json +20 -0
- data/spec/acceptance/valid/0008-hashes/0011-duplicate-key.json +4 -0
- data/spec/acceptance/valid/0008-hashes/0012-duplicate-key-in-different-representations.json +4 -0
- data/spec/acceptance/valid/0009-complicated/0001-jsonschema.json +46 -0
- data/spec/acceptance/valid/0009-complicated/0002-example-in-RFC7159-section-13.json +14 -0
- data/spec/acceptance/valid/0009-complicated/0003-example-in-RFC7159-section-13.json +22 -0
- data/spec/spec_helper.rb +60 -0
- metadata +530 -0
data/RFC8259.gemspec
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
#! /your/favourite/path/to/gem
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# Copyright (c) 2014 Urabe, Shyouhei. All rights reserved.
|
5
|
+
#
|
6
|
+
# Redistribution and use in source and binary forms, with or without
|
7
|
+
# modification, are permitted provided that the following conditions are met:
|
8
|
+
#
|
9
|
+
# - Redistributions of source code must retain the above copyright
|
10
|
+
# notice, this list of conditions and the following disclaimer.
|
11
|
+
#
|
12
|
+
# - Redistributions in binary form must reproduce the above copyright
|
13
|
+
# notice, this list of conditions and the following disclaimer in
|
14
|
+
# the documentation and/or other materials provided with the
|
15
|
+
# distribution.
|
16
|
+
#
|
17
|
+
# - Neither the name of Internet Society, IETF or IETF Trust, nor the
|
18
|
+
# names of specific contributors, may be used to endorse or promote
|
19
|
+
# products derived from this software without specific prior written
|
20
|
+
# permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
|
34
|
+
# coding: utf-8
|
35
|
+
|
36
|
+
# hack avoid namespace pollution
|
37
|
+
path = File.expand_path 'lib/RFC8259/version.rb', __dir__
|
38
|
+
content = File.read path
|
39
|
+
version = Module.new.module_eval <<-'end'
|
40
|
+
RFC8259 = Module.new
|
41
|
+
eval content, binding, path
|
42
|
+
end
|
43
|
+
|
44
|
+
Gem::Specification.new do |spec|
|
45
|
+
spec.name = 'RFC8259'
|
46
|
+
spec.version = version
|
47
|
+
spec.authors = %w'Urabe, Shyouhei'
|
48
|
+
spec.email = %w'shyouhei@ruby-lang.org'
|
49
|
+
spec.summary = 'RFC8259 parser / generator'
|
50
|
+
spec.description = <<-'end'.gsub(/[\n\s]+/, ' ').strip
|
51
|
+
A JSON parser/generator that conforms (I believe) to RFC8259 "The
|
52
|
+
JavaScript Object Notation (JSON) Data Interchange Format". This gem
|
53
|
+
honors the syntax as possible. The generator guarantees that a parsed
|
54
|
+
valid properly rounds-trip to identical valid JSON representation.
|
55
|
+
end
|
56
|
+
spec.homepage = 'http://github.com/shyouhei/RFC8259'
|
57
|
+
spec.license = "Simplified BSD License" # consult LICENSE.txt
|
58
|
+
|
59
|
+
spec.files = `git ls-files -z`.split("\x0") + %w'lib/RFC8259/parser.rb'
|
60
|
+
spec.executables = %w''
|
61
|
+
spec.test_files = spec.files.grep(%r{^spec/})
|
62
|
+
spec.require_paths = %w'lib'
|
63
|
+
|
64
|
+
spec.required_ruby_version = '~> 2.0'
|
65
|
+
spec.add_development_dependency 'bundler', '~> 1.5'
|
66
|
+
spec.add_development_dependency 'rake', '~> 10.1'
|
67
|
+
spec.add_development_dependency 'rdoc', '~> 4.0'
|
68
|
+
spec.add_development_dependency 'yard', '~> 0.8'
|
69
|
+
spec.add_development_dependency 'rspec', '~> 2.14'
|
70
|
+
spec.add_development_dependency 'simplecov', '>= 0'
|
71
|
+
spec.add_development_dependency 'racc', '~> 1.4.11'
|
72
|
+
# racc runtime is inside ruby's stdlib so no runtime dependency.
|
73
|
+
|
74
|
+
# below are only for comparisons
|
75
|
+
spec.add_development_dependency 'json' # 1.8.1 tested
|
76
|
+
spec.add_development_dependency 'yajl-ruby' # 1.2.0 tested
|
77
|
+
spec.add_development_dependency 'oj' # 2.6.1 tested
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# Local Variables:
|
82
|
+
# mode: ruby
|
83
|
+
# coding: utf-8-unix
|
84
|
+
# indent-tabs-mode: t
|
85
|
+
# tab-width: 3
|
86
|
+
# ruby-indent-level: 3
|
87
|
+
# fill-column: 79
|
88
|
+
# default-justification: full
|
89
|
+
# End:
|
data/Rakefile
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
#! /your/favourite/path/to/rake
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# Copyright (c) 2014 Urabe, Shyouhei. All rights reserved.
|
5
|
+
#
|
6
|
+
# Redistribution and use in source and binary forms, with or without
|
7
|
+
# modification, are permitted provided that the following conditions are met:
|
8
|
+
#
|
9
|
+
# - Redistributions of source code must retain the above copyright
|
10
|
+
# notice, this list of conditions and the following disclaimer.
|
11
|
+
#
|
12
|
+
# - Redistributions in binary form must reproduce the above copyright
|
13
|
+
# notice, this list of conditions and the following disclaimer in
|
14
|
+
# the documentation and/or other materials provided with the
|
15
|
+
# distribution.
|
16
|
+
#
|
17
|
+
# - Neither the name of Internet Society, IETF or IETF Trust, nor the
|
18
|
+
# names of specific contributors, may be used to endorse or promote
|
19
|
+
# products derived from this software without specific prior written
|
20
|
+
# permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
|
34
|
+
require 'rubygems'
|
35
|
+
require 'bundler'
|
36
|
+
require 'rake'
|
37
|
+
begin
|
38
|
+
require "bundler/gem_tasks"
|
39
|
+
Bundler.setup(:default, :development)
|
40
|
+
rescue Bundler::BundlerError => e
|
41
|
+
$stderr.puts e.message
|
42
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
43
|
+
exit e.status_code
|
44
|
+
end
|
45
|
+
|
46
|
+
require 'rspec/core'
|
47
|
+
require 'rspec/core/rake_task'
|
48
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
49
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
50
|
+
end
|
51
|
+
|
52
|
+
require 'yard'
|
53
|
+
YARD::Rake::YardocTask.new
|
54
|
+
|
55
|
+
task yard: 'lib/RFC8259/parser.rb'
|
56
|
+
task rdoc: 'lib/RFC8259/parser.rb'
|
57
|
+
task build: 'lib/RFC8259/parser.rb'
|
58
|
+
task spec: 'lib/RFC8259/parser.rb'
|
59
|
+
file 'lib/RFC8259/parser.rb' => %w'lib/RFC8259/parser.ry' do |t|
|
60
|
+
sh "bundle exec racc --debug --output-file=#{t.name} #{t.prerequisites.first}"
|
61
|
+
end
|
62
|
+
|
63
|
+
desc "a la rails console"
|
64
|
+
task :console do
|
65
|
+
require_relative 'lib/RFC8259'
|
66
|
+
require 'json'
|
67
|
+
require 'yajl'
|
68
|
+
require 'oj'
|
69
|
+
require 'irb'
|
70
|
+
require 'irb/completion'
|
71
|
+
ARGV.clear
|
72
|
+
IRB.start
|
73
|
+
end
|
74
|
+
|
75
|
+
task default: :spec
|
76
|
+
|
77
|
+
#
|
78
|
+
# Local Variables:
|
79
|
+
# mode: ruby
|
80
|
+
# coding: utf-8-unix
|
81
|
+
# indent-tabs-mode: t
|
82
|
+
# tab-width: 3
|
83
|
+
# ruby-indent-level: 3
|
84
|
+
# fill-column: 79
|
85
|
+
# default-justification: full
|
86
|
+
# End:
|
data/lib/RFC8259.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
#! /your/favourite/path/to/ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# Copyright (c) 2014 Urabe, Shyouhei. All rights reserved.
|
5
|
+
#
|
6
|
+
# Redistribution and use in source and binary forms, with or without
|
7
|
+
# modification, are permitted provided that the following conditions are met:
|
8
|
+
#
|
9
|
+
# - Redistributions of source code must retain the above copyright
|
10
|
+
# notice, this list of conditions and the following disclaimer.
|
11
|
+
#
|
12
|
+
# - Redistributions in binary form must reproduce the above copyright
|
13
|
+
# notice, this list of conditions and the following disclaimer in
|
14
|
+
# the documentation and/or other materials provided with the
|
15
|
+
# distribution.
|
16
|
+
#
|
17
|
+
# - Neither the name of Internet Society, IETF or IETF Trust, nor the
|
18
|
+
# names of specific contributors, may be used to endorse or promote
|
19
|
+
# products derived from this software without specific prior written
|
20
|
+
# permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
|
34
|
+
# This is a RFC8259-conforming JSON parser/generator.
|
35
|
+
module RFC8259
|
36
|
+
require_relative 'RFC8259/parser'
|
37
|
+
require_relative 'RFC8259/value'
|
38
|
+
require_relative 'RFC8259/dumper'
|
39
|
+
|
40
|
+
# This is our Marshal.load -compat API
|
41
|
+
# @param [::String, IO] str The input
|
42
|
+
# @param [true, false] plain Output to be plain-old ruby object, or not.
|
43
|
+
# @return [::Object] Evaluated plain-old ruby object
|
44
|
+
# @return [RFC8259::Value] Evaluated JSON value object
|
45
|
+
# @raise [Racc::ParseError] The input is invalid
|
46
|
+
# @raise [Encoding::CompatibilityError] The input is invalid
|
47
|
+
def self.load str, plain: false
|
48
|
+
ast = RFC8259::Parser.new.parse str
|
49
|
+
obj = RFC8259::Value.from_ast ast
|
50
|
+
if plain
|
51
|
+
return obj.plain_old_ruby_object
|
52
|
+
else
|
53
|
+
return obj
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# This is our Marshal.dump -compat API
|
58
|
+
# @param [::Object] obj The input (should be JSONable)
|
59
|
+
# @param [IO] port IO port to dump obj into
|
60
|
+
# @param [Fixnum] indent indent depth
|
61
|
+
# @param [Numeric] width page width (see {::PP})
|
62
|
+
# @return [::String] Dumped valid JSON text representation
|
63
|
+
# @return [port] Indicates the output went to the port.
|
64
|
+
# @raise [TypeError] obj not JSONable
|
65
|
+
# @raise [Errno::ELOOP] Cyclic relation(s) detected
|
66
|
+
def self.dump obj, port: ''.encode(Encoding::UTF_8), indent: 4, width: Math.atanh(1)
|
67
|
+
bag = RFC8259::Dumper.new port, indent, width
|
68
|
+
bag.start_dump obj
|
69
|
+
return port
|
70
|
+
end
|
71
|
+
|
72
|
+
# (Experimental) Sometimes JSON is required somewhere inside of a
|
73
|
+
# pretty-print, and you might want to inherit the indentation(s) of
|
74
|
+
# surrounding PP structure. In order to do so here we propose a dump
|
75
|
+
# variant that takes a PP object rather than destination IO.
|
76
|
+
# @param [::Object] obj The input (should be JSONable)
|
77
|
+
# @param [PP] pp The PP.
|
78
|
+
def self.pp_object pp, obj, indent=4
|
79
|
+
bag = RFC8259::Dumper.new nil, indent, nil, pp
|
80
|
+
bag.start_dump obj
|
81
|
+
return nil
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# Local Variables:
|
87
|
+
# mode: ruby
|
88
|
+
# coding: utf-8-unix
|
89
|
+
# indent-tabs-mode: t
|
90
|
+
# tab-width: 3
|
91
|
+
# ruby-indent-level: 3
|
92
|
+
# fill-column: 79
|
93
|
+
# default-justification: full
|
94
|
+
# End:
|
@@ -0,0 +1,136 @@
|
|
1
|
+
#! /your/favourite/path/to/ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# Copyright (c) 2014 Urabe, Shyouhei. All rights reserved.
|
5
|
+
#
|
6
|
+
# Redistribution and use in source and binary forms, with or without
|
7
|
+
# modification, are permitted provided that the following conditions are met:
|
8
|
+
#
|
9
|
+
# - Redistributions of source code must retain the above copyright
|
10
|
+
# notice, this list of conditions and the following disclaimer.
|
11
|
+
#
|
12
|
+
# - Redistributions in binary form must reproduce the above copyright
|
13
|
+
# notice, this list of conditions and the following disclaimer in
|
14
|
+
# the documentation and/or other materials provided with the
|
15
|
+
# distribution.
|
16
|
+
#
|
17
|
+
# - Neither the name of Internet Society, IETF or IETF Trust, nor the
|
18
|
+
# names of specific contributors, may be used to endorse or promote
|
19
|
+
# products derived from this software without specific prior written
|
20
|
+
# permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
|
34
|
+
# The Arrays, as described in RFC8259 section 5.
|
35
|
+
class RFC8259::Array < RFC8259::Value
|
36
|
+
|
37
|
+
# Parse the AST from parser, and convert into corrsponding values.
|
38
|
+
# @param [::Array] ast the AST, generated by the parser
|
39
|
+
# @return [Array] evaluated instance
|
40
|
+
# @raise [ArgumentError] malformed input
|
41
|
+
def self.from_ast ast
|
42
|
+
type, *ary = *ast
|
43
|
+
raise ArgumentError, "not an object: #{ast.inspect}" if type != :array
|
44
|
+
ary.map! do |a|
|
45
|
+
RFC8259::Value.from_ast a
|
46
|
+
end
|
47
|
+
new ary
|
48
|
+
end
|
49
|
+
|
50
|
+
# fetch the index
|
51
|
+
# @param [Integer] idx index to obtain
|
52
|
+
# @return [Value] corresponding value
|
53
|
+
# @return [nil] not found / out of bounds
|
54
|
+
def [] idx
|
55
|
+
@array[idx]
|
56
|
+
end
|
57
|
+
|
58
|
+
# iterate over the contents
|
59
|
+
# @yield [RFC8259::Value] element
|
60
|
+
def each &b
|
61
|
+
@array.each(&b)
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [Integer] the count of elements
|
65
|
+
def size
|
66
|
+
@array.size
|
67
|
+
end
|
68
|
+
|
69
|
+
alias length size
|
70
|
+
|
71
|
+
# equality
|
72
|
+
# @param [Array] other comparison target
|
73
|
+
# @return [true] they are equal
|
74
|
+
# @return [false] otherwise.
|
75
|
+
def == other
|
76
|
+
return false unless length == other.length
|
77
|
+
@array.each_index do |i|
|
78
|
+
j = @array[i]
|
79
|
+
k = other[i]
|
80
|
+
return false unless j == k
|
81
|
+
end
|
82
|
+
return true
|
83
|
+
end
|
84
|
+
|
85
|
+
# @return [::Array] converted array
|
86
|
+
def plain_old_ruby_object
|
87
|
+
@array.map do |i|
|
88
|
+
i.plain_old_ruby_object
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
alias to_a plain_old_ruby_object
|
93
|
+
alias to_ary plain_old_ruby_object
|
94
|
+
|
95
|
+
# JSON gem compat
|
96
|
+
# @return [::String] JSONified representation
|
97
|
+
def to_json
|
98
|
+
RFC8259::Dumper.new.dump self
|
99
|
+
end
|
100
|
+
|
101
|
+
# @return [::String] the array in string
|
102
|
+
def inspect
|
103
|
+
sprintf "#<%p:%#016x %p>", self.class, self.object_id << 1, @array
|
104
|
+
end
|
105
|
+
|
106
|
+
# For pretty print
|
107
|
+
# @param [PP] pp the pp
|
108
|
+
def pretty_print pp
|
109
|
+
hdr = sprintf '#<%p:%#016x', self.class, self.object_id << 1
|
110
|
+
pp.group 1, hdr, '>' do
|
111
|
+
pp.text ' '
|
112
|
+
RFC8259::Dumper.kandr pp, 1, @array.each, '[', ']' do |i|
|
113
|
+
i.pretty_print pp
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
private_class_method:new
|
120
|
+
# @private
|
121
|
+
def initialize ary
|
122
|
+
@array = ary
|
123
|
+
@array.freeze
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
#
|
128
|
+
# Local Variables:
|
129
|
+
# mode: ruby
|
130
|
+
# coding: utf-8-unix
|
131
|
+
# indent-tabs-mode: t
|
132
|
+
# tab-width: 3
|
133
|
+
# ruby-indent-level: 3
|
134
|
+
# fill-column: 79
|
135
|
+
# default-justification: full
|
136
|
+
# End:
|
@@ -0,0 +1,255 @@
|
|
1
|
+
#! /your/favourite/path/to/ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
# Copyright (c) 2014 Urabe, Shyouhei. All rights reserved.
|
5
|
+
#
|
6
|
+
# Redistribution and use in source and binary forms, with or without
|
7
|
+
# modification, are permitted provided that the following conditions are met:
|
8
|
+
#
|
9
|
+
# - Redistributions of source code must retain the above copyright
|
10
|
+
# notice, this list of conditions and the following disclaimer.
|
11
|
+
#
|
12
|
+
# - Redistributions in binary form must reproduce the above copyright
|
13
|
+
# notice, this list of conditions and the following disclaimer in
|
14
|
+
# the documentation and/or other materials provided with the
|
15
|
+
# distribution.
|
16
|
+
#
|
17
|
+
# - Neither the name of Internet Society, IETF or IETF Trust, nor the
|
18
|
+
# names of specific contributors, may be used to endorse or promote
|
19
|
+
# products derived from this software without specific prior written
|
20
|
+
# permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
|
34
|
+
require_relative 'value'
|
35
|
+
require 'prettyprint'
|
36
|
+
|
37
|
+
# Dumps ruby object into JSON string
|
38
|
+
class RFC8259::Dumper
|
39
|
+
|
40
|
+
# much like PP#object_group, except that it indents like K&R.
|
41
|
+
def self.kandr pp, indent, enum, open, close
|
42
|
+
pp.text open
|
43
|
+
pp.group_sub do
|
44
|
+
pp.nest indent do
|
45
|
+
enum.with_index do |a, i|
|
46
|
+
if i > 0
|
47
|
+
pp.text ','
|
48
|
+
end
|
49
|
+
pp.breakable ' '
|
50
|
+
yield a
|
51
|
+
end
|
52
|
+
end
|
53
|
+
pp.breakable ' '
|
54
|
+
end
|
55
|
+
pp.text close
|
56
|
+
end
|
57
|
+
|
58
|
+
# @param [#<<] port output destination
|
59
|
+
def initialize port, indent = 4, width = 79, pp = PrettyPrint.new(port, width)
|
60
|
+
@port = port
|
61
|
+
@bag = Hash.new
|
62
|
+
@indent = indent
|
63
|
+
@pp = pp
|
64
|
+
@bag.compare_by_identity
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param [::Object] target target to dump
|
68
|
+
# @return [self] self.
|
69
|
+
def start_dump target
|
70
|
+
dump target
|
71
|
+
return self
|
72
|
+
ensure
|
73
|
+
@bag.clear
|
74
|
+
@pp.flush
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def dump obj
|
80
|
+
obj2 = try_convert obj
|
81
|
+
case obj2
|
82
|
+
when ::Array, RFC8259::Array then
|
83
|
+
kandr obj2, :each, '[', ']' do |i|
|
84
|
+
dump i
|
85
|
+
end
|
86
|
+
when ::Hash, RFC8259::Object then
|
87
|
+
kandr obj2, :each_pair, '{', '}' do |(i, j)|
|
88
|
+
case i
|
89
|
+
when ::String, RFC8259::String
|
90
|
+
dump i
|
91
|
+
else
|
92
|
+
dump i.to_str # should raise for non-string-ish
|
93
|
+
end
|
94
|
+
@pp.text ': '
|
95
|
+
dump j
|
96
|
+
end
|
97
|
+
when RFC8259::Value then
|
98
|
+
obj3 = obj2.to_json
|
99
|
+
@pp.text obj3
|
100
|
+
when ::String then
|
101
|
+
obj3 = try_escape_string obj2
|
102
|
+
@pp.text '"'
|
103
|
+
@pp.text obj3
|
104
|
+
@pp.text '"'
|
105
|
+
when ::Numeric then
|
106
|
+
obj3 = try_stringize_numeric obj2
|
107
|
+
@pp.text obj3
|
108
|
+
when ::TrueClass then
|
109
|
+
@pp.text 'true'
|
110
|
+
when ::FalseClass then
|
111
|
+
@pp.text 'false'
|
112
|
+
when ::NilClass then
|
113
|
+
@pp.text 'null'
|
114
|
+
else
|
115
|
+
begin
|
116
|
+
# Try fallback
|
117
|
+
@pp.text obj2.to_json
|
118
|
+
rescue NoMethodError
|
119
|
+
raise TypeError, "not JSONable: #{obj}"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Check repetition. JSON is a true tree -- no cyclic lists, nor even direct
|
125
|
+
# acyclic graphs are allowed. We check that here.
|
126
|
+
#
|
127
|
+
# - strings, numbers, booleans are all OK to appear multiple times.
|
128
|
+
# - empty arrays and empty hashes are special-cased OK.
|
129
|
+
# - other cases are subject to appear exactly once.
|
130
|
+
def ensure_unique obj
|
131
|
+
if @bag.include? obj and not obj.empty?
|
132
|
+
raise Errno::ELOOP, "target appears twice: #{obj.inspect}"
|
133
|
+
else
|
134
|
+
begin
|
135
|
+
@bag.store obj, obj
|
136
|
+
yield
|
137
|
+
ensure
|
138
|
+
@bag.delete obj
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# much like PP#object_group, except that it indents like K&R.
|
144
|
+
def kandr obj, method, open, close
|
145
|
+
ensure_unique obj do
|
146
|
+
enum = obj.enum_for method
|
147
|
+
RFC8259::Dumper.kandr @pp, @indent, enum, open, close do |obj|
|
148
|
+
yield obj
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def try_convert obj
|
154
|
+
case obj
|
155
|
+
when RFC8259::Value, Hash, Array, String, Integer, Float, BigDecimal, TrueClass, FalseClass, NilClass
|
156
|
+
return obj
|
157
|
+
else
|
158
|
+
begin
|
159
|
+
return obj.to_hash
|
160
|
+
rescue NoMethodError
|
161
|
+
begin
|
162
|
+
return obj.to_ary
|
163
|
+
rescue NoMethodError
|
164
|
+
begin
|
165
|
+
return obj.to_str
|
166
|
+
rescue NoMethodError
|
167
|
+
begin
|
168
|
+
return obj.to_int
|
169
|
+
rescue NoMethodError
|
170
|
+
begin
|
171
|
+
return obj.to_f
|
172
|
+
rescue NoMethodError
|
173
|
+
raise TypeError, "not JSONable: #{obj.class}"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def try_escape_string str
|
183
|
+
buf = nil
|
184
|
+
|
185
|
+
begin
|
186
|
+
# fast path
|
187
|
+
if str.valid_encoding?
|
188
|
+
str2 = str.encode Encoding::UTF_8
|
189
|
+
buf = str2.unpack('U*')
|
190
|
+
end
|
191
|
+
rescue Encoding::UndefinedConversionError
|
192
|
+
# str might be invalid, but that's OK as per RFC8259 section 8.2.
|
193
|
+
end
|
194
|
+
|
195
|
+
unless buf
|
196
|
+
case str.encoding
|
197
|
+
when Encoding::UTF_32BE then buf = str.unpack 'N*'
|
198
|
+
when Encoding::UTF_32LE then buf = str.unpack 'V*'
|
199
|
+
when Encoding::UTF_16BE then buf = str.unpack 'n*'
|
200
|
+
when Encoding::UTF_16LE then buf = str.unpack 'v*'
|
201
|
+
when Encoding::UTF_8,
|
202
|
+
Encoding::UTF8_MAC,
|
203
|
+
Encoding::US_ASCII then buf = str.unpack 'U*'
|
204
|
+
else buf = str.unpack 'C*' # fallback
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# We don't escape \/, because that seems to be de facto standard.
|
209
|
+
return buf.inject '' do |r, i|
|
210
|
+
c = nil
|
211
|
+
case i
|
212
|
+
when 0x22 then c = '\\"' # " quotation mark U+0022
|
213
|
+
when 0x5C then c = '\\\\' # \ reverse solidus U+005C
|
214
|
+
# when 0x2F then c = '\\/' # / solidus U+002F
|
215
|
+
when 0x08 then c = '\\b' # b backspace U+0008
|
216
|
+
when 0x0C then c = '\\f' # f form feed U+000C
|
217
|
+
when 0x0A then c = '\\n' # n line feed U+000A
|
218
|
+
when 0x0D then c = '\\r' # r carriage return U+000D
|
219
|
+
when 0x09 then c = '\\t' # t tab U+0009
|
220
|
+
when 0x00..0x1F, 0xD800..0xDFFF then
|
221
|
+
c = sprintf '\\u%04X', i
|
222
|
+
else
|
223
|
+
c = [i].pack 'U'
|
224
|
+
end
|
225
|
+
r << c
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def try_stringize_numeric num
|
230
|
+
case num
|
231
|
+
when Float, BigDecimal
|
232
|
+
if num.finite?
|
233
|
+
# FIXME: does this lose precision?
|
234
|
+
num.to_s
|
235
|
+
else
|
236
|
+
raise TypeError, "not JSONable: #{num.inspect}"
|
237
|
+
end
|
238
|
+
when Integer
|
239
|
+
return num.to_s
|
240
|
+
else
|
241
|
+
raise TypeError, "not JSONable: #{num.inspect}"
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
#
|
247
|
+
# Local Variables:
|
248
|
+
# mode: ruby
|
249
|
+
# coding: utf-8-unix
|
250
|
+
# indent-tabs-mode: t
|
251
|
+
# tab-width: 3
|
252
|
+
# ruby-indent-level: 3
|
253
|
+
# fill-column: 79
|
254
|
+
# default-justification: full
|
255
|
+
# End:
|