RFC7159 7159

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.
Files changed (177) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +61 -0
  3. data/.rspec +4 -0
  4. data/.yardopts +2 -0
  5. data/Gemfile +46 -0
  6. data/LICENSE.txt +40 -0
  7. data/README.txt +899 -0
  8. data/RFC7159 +899 -0
  9. data/RFC7159.gemspec +85 -0
  10. data/Rakefile +82 -0
  11. data/lib/RFC7159.rb +80 -0
  12. data/lib/RFC7159/array.rb +134 -0
  13. data/lib/RFC7159/dumper.rb +231 -0
  14. data/lib/RFC7159/false.rb +79 -0
  15. data/lib/RFC7159/null.rb +79 -0
  16. data/lib/RFC7159/number.rb +149 -0
  17. data/lib/RFC7159/object.rb +140 -0
  18. data/lib/RFC7159/parser.ry +267 -0
  19. data/lib/RFC7159/string.rb +221 -0
  20. data/lib/RFC7159/true.rb +79 -0
  21. data/lib/RFC7159/value.rb +96 -0
  22. data/lib/RFC7159/version.rb +48 -0
  23. data/spec/RFC7159_spec.rb +275 -0
  24. data/spec/acceptance/README.txt +66 -0
  25. data/spec/acceptance/invalid/0001-ws/0001-verical-tab.txt +1 -0
  26. data/spec/acceptance/invalid/0001-ws/0002-null.txt +0 -0
  27. data/spec/acceptance/invalid/0001-ws/0003-space-in-number-1.txt +1 -0
  28. data/spec/acceptance/invalid/0001-ws/0004-space-in-number-2.txt +1 -0
  29. data/spec/acceptance/invalid/0001-ws/0005-space-in-number-3.txt +1 -0
  30. data/spec/acceptance/invalid/0001-ws/0006-space-in-number-4.txt +1 -0
  31. data/spec/acceptance/invalid/0001-ws/0007-space-in-number-5.txt +1 -0
  32. data/spec/acceptance/invalid/0001-ws/0008-space-in-number-6.txt +1 -0
  33. data/spec/acceptance/invalid/0001-ws/0009-space-in-literal.txt +1 -0
  34. data/spec/acceptance/invalid/0001-ws/0010-Unicode-LINE_SEPARATOR.txt +1 -0
  35. data/spec/acceptance/invalid/0002-comments/0001-C-style.txt +1 -0
  36. data/spec/acceptance/invalid/0002-comments/0002-C-plusplus-style.txt +2 -0
  37. data/spec/acceptance/invalid/0002-comments/0003-sh-style.txt +2 -0
  38. data/spec/acceptance/invalid/0002-comments/0004-python-docstring.txt +3 -0
  39. data/spec/acceptance/invalid/0002-comments/0005-SQL-style.txt +2 -0
  40. data/spec/acceptance/invalid/0002-comments/0006-BASIC-style.txt +2 -0
  41. data/spec/acceptance/invalid/0003-literals/0001-FALSE.txt +1 -0
  42. data/spec/acceptance/invalid/0003-literals/0002-NULL.txt +1 -0
  43. data/spec/acceptance/invalid/0003-literals/0003-TRUE.txt +1 -0
  44. data/spec/acceptance/invalid/0003-literals/0004-NUL.txt +1 -0
  45. data/spec/acceptance/invalid/0003-literals/0005-nil.txt +1 -0
  46. data/spec/acceptance/invalid/0003-literals/0006-undef.txt +1 -0
  47. data/spec/acceptance/invalid/0003-literals/0007-modifier.txt +1 -0
  48. data/spec/acceptance/invalid/0003-literals/0008-undefined.txt +1 -0
  49. data/spec/acceptance/invalid/0004-numbers/0001-omit-zero.txt +1 -0
  50. data/spec/acceptance/invalid/0004-numbers/0002-minus-dot.txt +1 -0
  51. data/spec/acceptance/invalid/0004-numbers/0003-missing-frac.txt +1 -0
  52. data/spec/acceptance/invalid/0004-numbers/0004-missing-exp.txt +1 -0
  53. data/spec/acceptance/invalid/0004-numbers/0005-octal.txt +1 -0
  54. data/spec/acceptance/invalid/0004-numbers/0006-hexadecimal.txt +1 -0
  55. data/spec/acceptance/invalid/0004-numbers/0007-comma.txt +1 -0
  56. data/spec/acceptance/invalid/0004-numbers/0008-perl-underscore.txt +1 -0
  57. data/spec/acceptance/invalid/0004-numbers/0009-NaN.txt +1 -0
  58. data/spec/acceptance/invalid/0004-numbers/0010-Inf.txt +1 -0
  59. data/spec/acceptance/invalid/0004-numbers/0011-Infinity.txt +1 -0
  60. data/spec/acceptance/invalid/0005-strings/0000-NUL.txt +0 -0
  61. data/spec/acceptance/invalid/0005-strings/0001-not-terminated.txt +1 -0
  62. data/spec/acceptance/invalid/0005-strings/0002-single-quote.txt +1 -0
  63. data/spec/acceptance/invalid/0005-strings/0003-back-quote.txt +1 -0
  64. data/spec/acceptance/invalid/0005-strings/0004-carriage-return.txt +1 -0
  65. data/spec/acceptance/invalid/0005-strings/0005-line-feed.txt +2 -0
  66. data/spec/acceptance/invalid/0005-strings/0006-unknown-escape-a.txt +1 -0
  67. data/spec/acceptance/invalid/0005-strings/0007-unknown-escape-perl-style.txt +1 -0
  68. data/spec/acceptance/invalid/0005-strings/0008-unknown-escape-C-style.txt +1 -0
  69. data/spec/acceptance/invalid/0005-strings/0009-unknown-escape-ruby-style.txt +1 -0
  70. data/spec/acceptance/invalid/0005-strings/0010-escape-too-short.txt +1 -0
  71. data/spec/acceptance/invalid/0005-strings/0011-C-string-concat.txt +1 -0
  72. data/spec/acceptance/invalid/0005-strings/0012-perl-string-concat.txt +1 -0
  73. data/spec/acceptance/invalid/0005-strings/0013-Java-string-concat.txt +1 -0
  74. data/spec/acceptance/invalid/0006-encodings/0001-CESU-8.txt +1 -0
  75. data/spec/acceptance/invalid/0006-encodings/0002-Windows-31J.txt +1 -0
  76. data/spec/acceptance/invalid/0006-encodings/0003-EBCDIC.txt +1 -0
  77. data/spec/acceptance/invalid/0006-encodings/0004-overlong-utf8.txt +1 -0
  78. data/spec/acceptance/invalid/0007-arrays/0001-lacks-open.txt +1 -0
  79. data/spec/acceptance/invalid/0007-arrays/0002-lacks-close.txt +1 -0
  80. data/spec/acceptance/invalid/0007-arrays/0003-interleaving-parens.txt +1 -0
  81. data/spec/acceptance/invalid/0007-arrays/0004-dangling-comma.txt +1 -0
  82. data/spec/acceptance/invalid/0007-arrays/0005-missing-comma.txt +1 -0
  83. data/spec/acceptance/invalid/0007-arrays/0006-colon-instead-of-comma.txt +1 -0
  84. data/spec/acceptance/invalid/0008-hashes/0001-key-missing.txt +1 -0
  85. data/spec/acceptance/invalid/0008-hashes/0002-value-missing.txt +1 -0
  86. data/spec/acceptance/invalid/0008-hashes/0003-true-key.txt +1 -0
  87. data/spec/acceptance/invalid/0008-hashes/0004-false-key.txt +1 -0
  88. data/spec/acceptance/invalid/0008-hashes/0005-null-key.txt +1 -0
  89. data/spec/acceptance/invalid/0008-hashes/0006-numeric-key.txt +1 -0
  90. data/spec/acceptance/invalid/0008-hashes/0007-array-key.txt +1 -0
  91. data/spec/acceptance/invalid/0008-hashes/0008-hash-key.txt +1 -0
  92. data/spec/acceptance/invalid/0008-hashes/0009-key-not-escaped.txt +4 -0
  93. data/spec/acceptance/invalid/0009-javascriptisms/0001-JSONP.txt +1 -0
  94. data/spec/acceptance/invalid/0009-javascriptisms/0002-new-Array.txt +3 -0
  95. data/spec/acceptance/invalid/0009-javascriptisms/0003-new-Date.txt +1 -0
  96. data/spec/acceptance/invalid/0009-javascriptisms/0004-new-Error.txt +1 -0
  97. data/spec/acceptance/invalid/0009-javascriptisms/0005-Math.txt +1 -0
  98. data/spec/acceptance/invalid/0009-javascriptisms/0006-regular-expression.txt +1 -0
  99. data/spec/acceptance/invalid/0009-javascriptisms/0007-function.txt +7 -0
  100. data/spec/acceptance/invalid/0009-javascriptisms/0008-this.txt +1 -0
  101. data/spec/acceptance/invalid/0009-javascriptisms/0009-plusplus.txt +3 -0
  102. data/spec/acceptance/invalid/0009-javascriptisms/0010-ternary-operator.txt +1 -0
  103. data/spec/acceptance/valid/0001-ws/0001-space.json +1 -0
  104. data/spec/acceptance/valid/0001-ws/0002-tab.json +1 -0
  105. data/spec/acceptance/valid/0001-ws/0003-lf.json +1 -0
  106. data/spec/acceptance/valid/0001-ws/0004-cr.json +1 -0
  107. data/spec/acceptance/valid/0001-ws/0005-before.json +1 -0
  108. data/spec/acceptance/valid/0001-ws/0006-after.json +1 -0
  109. data/spec/acceptance/valid/0001-ws/0007-around-comma.json +3 -0
  110. data/spec/acceptance/valid/0001-ws/0008-around-colon.json +3 -0
  111. data/spec/acceptance/valid/0002-bare-values/0001-false.json +1 -0
  112. data/spec/acceptance/valid/0002-bare-values/0002-null.json +1 -0
  113. data/spec/acceptance/valid/0002-bare-values/0003-true.json +1 -0
  114. data/spec/acceptance/valid/0002-bare-values/0004-number.json +1 -0
  115. data/spec/acceptance/valid/0002-bare-values/0005-string.json +1 -0
  116. data/spec/acceptance/valid/0003-literals/0001-false.json +1 -0
  117. data/spec/acceptance/valid/0003-literals/0002-null.json +1 -0
  118. data/spec/acceptance/valid/0003-literals/0003-true.json +1 -0
  119. data/spec/acceptance/valid/0004-numbers/0000-zero.json +1 -0
  120. data/spec/acceptance/valid/0004-numbers/0001-one.json +1 -0
  121. data/spec/acceptance/valid/0004-numbers/0002-two.json +1 -0
  122. data/spec/acceptance/valid/0004-numbers/0003-three.json +1 -0
  123. data/spec/acceptance/valid/0004-numbers/0004-four.json +1 -0
  124. data/spec/acceptance/valid/0004-numbers/0005-five.json +1 -0
  125. data/spec/acceptance/valid/0004-numbers/0006-six.json +1 -0
  126. data/spec/acceptance/valid/0004-numbers/0007-seven.json +1 -0
  127. data/spec/acceptance/valid/0004-numbers/0008-eight.json +1 -0
  128. data/spec/acceptance/valid/0004-numbers/0009-nine.json +1 -0
  129. data/spec/acceptance/valid/0004-numbers/0010-ten.json +1 -0
  130. data/spec/acceptance/valid/0004-numbers/0011-minus.json +1 -0
  131. data/spec/acceptance/valid/0004-numbers/0012-fraction.json +1 -0
  132. data/spec/acceptance/valid/0004-numbers/0013-exponent.json +1 -0
  133. data/spec/acceptance/valid/0004-numbers/0014-exponent-minus.json +1 -0
  134. data/spec/acceptance/valid/0004-numbers/0015-exponent-plus.json +1 -0
  135. data/spec/acceptance/valid/0004-numbers/0016-complex.json +1 -0
  136. data/spec/acceptance/valid/0004-numbers/0017-DBL_MAX.json +1 -0
  137. data/spec/acceptance/valid/0004-numbers/0018-DBL_MIN.json +1 -0
  138. data/spec/acceptance/valid/0004-numbers/0019-subnormal-number.json +1 -0
  139. data/spec/acceptance/valid/0004-numbers/0020-1E400.json +1 -0
  140. data/spec/acceptance/valid/0004-numbers/0021-pi.json +1 -0
  141. data/spec/acceptance/valid/0004-numbers/0022-UINT32_MAX.json +1 -0
  142. data/spec/acceptance/valid/0004-numbers/0023-UINT64_MAX.json +1 -0
  143. data/spec/acceptance/valid/0004-numbers/0024-INT64_MIN.json +1 -0
  144. data/spec/acceptance/valid/0004-numbers/0025-high-resolution-zero.json +1 -0
  145. data/spec/acceptance/valid/0005-strings/0001-empty.json +1 -0
  146. data/spec/acceptance/valid/0005-strings/0002-basic-latin.json +1 -0
  147. data/spec/acceptance/valid/0005-strings/0003-escapes.json +1 -0
  148. data/spec/acceptance/valid/0005-strings/0004-raw-unicode.json +1 -0
  149. data/spec/acceptance/valid/0005-strings/0005-escaped-unicode.json +1 -0
  150. data/spec/acceptance/valid/0005-strings/0006-escaped-NUL.json +1 -0
  151. data/spec/acceptance/valid/0005-strings/0007-escaped-invalid-unicode-still-valid-as-json.json +1 -0
  152. data/spec/acceptance/valid/0005-strings/0008-ruby-json-gem-cant-handle-this.json +1 -0
  153. data/spec/acceptance/valid/0005-strings/0009-unescaped-invalid-javascript-still-valid-as-json.json +1 -0
  154. data/spec/acceptance/valid/0006-m17n/0001-genesis.json +6 -0
  155. data/spec/acceptance/valid/0006-m17n/0002-heart-sutra.json +5 -0
  156. data/spec/acceptance/valid/0006-m17n/0003-escaped-valid-surrogate-pair.json +1 -0
  157. data/spec/acceptance/valid/0006-m17n/0004-unescaped-valid-supplementary-multilingual-plane.json +1 -0
  158. data/spec/acceptance/valid/0007-arrays/0000-empty.json +1 -0
  159. data/spec/acceptance/valid/0007-arrays/0001-one-element.json +1 -0
  160. data/spec/acceptance/valid/0007-arrays/0002-multiple-elements.json +33 -0
  161. data/spec/acceptance/valid/0007-arrays/0003-various-types.json +1 -0
  162. data/spec/acceptance/valid/0007-arrays/0004-nested.json +17 -0
  163. data/spec/acceptance/valid/0008-hashes/0000-empty.json +1 -0
  164. data/spec/acceptance/valid/0008-hashes/0001-onekey.json +1 -0
  165. data/spec/acceptance/valid/0008-hashes/0002-many-keys.json +5 -0
  166. data/spec/acceptance/valid/0008-hashes/0003-empty-key.json +3 -0
  167. data/spec/acceptance/valid/0008-hashes/0004-true-value.json +3 -0
  168. data/spec/acceptance/valid/0008-hashes/0005-false-value.json +3 -0
  169. data/spec/acceptance/valid/0008-hashes/0006-null-value.json +3 -0
  170. data/spec/acceptance/valid/0008-hashes/0007-string-value.json +3 -0
  171. data/spec/acceptance/valid/0008-hashes/0008-numeric-value.json +3 -0
  172. data/spec/acceptance/valid/0008-hashes/0009-array-value.json +8 -0
  173. data/spec/acceptance/valid/0008-hashes/0010-hash-value.json +20 -0
  174. data/spec/acceptance/valid/0008-hashes/0011-duplicate-key-in-different-representations.json +4 -0
  175. data/spec/acceptance/valid/0008-hashes/0011-duplicate-key.json +4 -0
  176. data/spec/spec_helper.rb +54 -0
  177. metadata +520 -0
@@ -0,0 +1,85 @@
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
+ require_relative 'lib/RFC7159/version'
37
+
38
+ Gem::Specification.new do |spec|
39
+ spec.name = 'RFC7159'
40
+ spec.version = RFC7159::VERSION
41
+ spec.authors = %w'Urabe, Shyouhei'
42
+ spec.email = %w'shyouhei@ruby-lang.org'
43
+ spec.summary = 'RFC7159 parser / generator'
44
+ spec.description = <<-'end'.gsub /\n\s*/, ''
45
+ A JSON parser/generator that conforms (I believe) to RFC7159 "The
46
+ JavaScript Object Notation (JSON) Data Interchange Format". That RFC is
47
+ very different to its predecessor RFC4627, when it comes to parsing.
48
+ This gem honors the updated syntax as possible. The generator guarantees
49
+ that a parsed valid properly rounds-trip to identical valid JSON
50
+ representation.
51
+ end
52
+ spec.homepage = 'http://github.com/shyouhei/RFC7159'
53
+ spec.license = "Simplified BSD License" # consult LICENSE.txt
54
+
55
+ spec.files = `git ls-files -z`.split("\x0") + %w'lib/RFC7159/parser.rb'
56
+ spec.executables = %w''
57
+ spec.test_files = spec.files.grep(%r{^spec/})
58
+ spec.require_paths = %w'lib'
59
+
60
+ spec.required_ruby_version = '~> 2.1' # String#scrub used
61
+ spec.add_development_dependency 'bundler', '~> 1.5'
62
+ spec.add_development_dependency 'rake', '~> 10.1'
63
+ spec.add_development_dependency 'rdoc', '~> 4.0'
64
+ spec.add_development_dependency 'yard', '~> 0.8'
65
+ spec.add_development_dependency 'rspec', '~> 2.14'
66
+ spec.add_development_dependency 'simplecov', '>= 0'
67
+ spec.add_development_dependency 'racc', '~> 1.4.11'
68
+ # racc runtime is inside ruby's stdlib so no runtime dependency.
69
+
70
+ # below are only for comparisons
71
+ spec.add_development_dependency 'json' # 1.8.1 tested
72
+ spec.add_development_dependency 'yajl-ruby' # 1.2.0 tested
73
+ spec.add_development_dependency 'oj' # 2.6.1 tested
74
+ end
75
+
76
+ #
77
+ # Local Variables:
78
+ # mode: ruby
79
+ # coding: utf-8-unix
80
+ # indent-tabs-mode: t
81
+ # tab-width: 3
82
+ # ruby-indent-level: 3
83
+ # fill-column: 79
84
+ # default-justification: full
85
+ # End:
@@ -0,0 +1,82 @@
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
+ require "bundler/gem_tasks"
38
+ begin
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/RFC7159/parser.rb'
56
+ task rdoc: 'lib/RFC7159/parser.rb'
57
+ task build: 'lib/RFC7159/parser.rb'
58
+ file 'lib/RFC7159/parser.rb' => %w'lib/RFC7159/parser.ry' do |t|
59
+ sh "bundle exec racc --debug --output-file=#{t.name} #{t.prerequisites.first}"
60
+ end
61
+
62
+ desc "a la rails console"
63
+ task :console do
64
+ require_relative 'lib/RFC7159'
65
+ require 'irb'
66
+ require 'irb/completion'
67
+ ARGV.clear
68
+ IRB.start
69
+ end
70
+
71
+ task default: :spec
72
+
73
+ #
74
+ # Local Variables:
75
+ # mode: ruby
76
+ # coding: utf-8-unix
77
+ # indent-tabs-mode: t
78
+ # tab-width: 3
79
+ # ruby-indent-level: 3
80
+ # fill-column: 79
81
+ # default-justification: full
82
+ # End:
@@ -0,0 +1,80 @@
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 'RFC7159/parser'
35
+ require_relative 'RFC7159/value'
36
+ require_relative 'RFC7159/dumper'
37
+
38
+ # This is a RFC7159-conforming JSON parser/generator.
39
+ module RFC7159
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 [RFC7159::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 = RFC7159::Parser.new.parse str
49
+ obj = RFC7159::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
+ # @return [::String] Dumped valid JSON text representation
61
+ # @return [port] Indicates the output went to the port.
62
+ # @raise [TypeEeepe] obj not JSONable
63
+ # @raise [Errno::ELOOP] Cyclic relation(s) detected
64
+ def self.dump obj, port: ''.encode(Encoding::UTF_8)
65
+ bag = RFC7159::Dumper.new port
66
+ bag.start_dump obj
67
+ return port
68
+ end
69
+ end
70
+
71
+ #
72
+ # Local Variables:
73
+ # mode: ruby
74
+ # coding: utf-8-unix
75
+ # indent-tabs-mode: t
76
+ # tab-width: 3
77
+ # ruby-indent-level: 3
78
+ # fill-column: 79
79
+ # default-justification: full
80
+ # End:
@@ -0,0 +1,134 @@
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 RFC7159 section 5.
35
+ class RFC7159::Array < RFC7159::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
+ RFC7159::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 [RFC7159::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
+ RFC7159::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.breakable
112
+ @array.pretty_print pp
113
+ end
114
+ end
115
+
116
+ private
117
+ private_class_method:new
118
+ # @private
119
+ def initialize ary
120
+ @array = ary
121
+ @array.freeze
122
+ end
123
+ end
124
+
125
+ #
126
+ # Local Variables:
127
+ # mode: ruby
128
+ # coding: utf-8-unix
129
+ # indent-tabs-mode: t
130
+ # tab-width: 3
131
+ # ruby-indent-level: 3
132
+ # fill-column: 79
133
+ # default-justification: full
134
+ # End:
@@ -0,0 +1,231 @@
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 RFC7159::Dumper
39
+
40
+ # @param [#<<] port output destination
41
+ def initialize port
42
+ @port = port
43
+ @bag = Hash.new
44
+ @pp = PrettyPrint.new @port
45
+ @bag.compare_by_identity
46
+ end
47
+
48
+ # @param [::Object] target target to dump
49
+ # @return [self] self.
50
+ def start_dump target
51
+ dump target
52
+ return self
53
+ ensure
54
+ @bag.clear
55
+ @pp.flush
56
+ end
57
+
58
+ private
59
+
60
+ def dump obj
61
+ obj2 = try_convert obj
62
+ case obj2
63
+ when ::Array, RFC7159::Array then
64
+ ensure_unique obj2
65
+ @pp.group 1, '[', ']' do
66
+ obj2.each.with_index do |i, j|
67
+ @pp.text ',' if j > 0
68
+ @pp.breakable ''
69
+ dump i
70
+ end
71
+ end
72
+ when ::Hash, RFC7159::Object then
73
+ ensure_unique obj2
74
+ @pp.group 1, '{', '}' do
75
+ obj2.each_pair.with_index do |(i, j), k|
76
+ @pp.text ',' if k > 0
77
+ @pp.breakable ''
78
+ case i
79
+ when ::String, RFC7159::String
80
+ dump i
81
+ else
82
+ dump i.to_str # should raise for non-string-ish
83
+ end
84
+ @pp.text ':'
85
+ dump j
86
+ end
87
+ end
88
+ when RFC7159::Value then
89
+ obj3 = obj2.to_json
90
+ @pp.text obj3
91
+ when ::String then
92
+ obj3 = try_escape_string obj2
93
+ @pp.text '"'
94
+ @pp.text obj3
95
+ @pp.text '"'
96
+ when ::Numeric then
97
+ obj3 = try_stringize_numeric obj2
98
+ @pp.text obj3
99
+ when ::TrueClass then
100
+ @pp.text 'true'
101
+ when ::FalseClass then
102
+ @pp.text 'false'
103
+ when ::NilClass then
104
+ @pp.text 'null'
105
+ else
106
+ begin
107
+ # Try fallback
108
+ @pp.text obj2.to_json
109
+ rescue NoMethodError
110
+ raise TypeError, "not JSONable: #{obj}"
111
+ end
112
+ end
113
+ end
114
+
115
+ # Check repetition. JSON is a true tree -- no cyclic lists, nor even direct
116
+ # acyclic graphs are allowed. We check that here.
117
+ #
118
+ # - strings, numbers, booleans are all OK to appear multiple times.
119
+ # - empty arrays and empty hashes are special-cased OK.
120
+ # - other cases are subject to appear exactly once.
121
+ def ensure_unique obj
122
+ if @bag.include? obj and not obj2.empty?
123
+ raise Errno::ELOOP, "target appears twice: #{target.inspect}"
124
+ else
125
+ @bag.store obj, obj
126
+ end
127
+ end
128
+
129
+ def try_convert obj
130
+ case obj
131
+ when RFC7159::Value, Hash, Array, String, Integer, Float, BigDecimal, TrueClass, FalseClass, NilClass
132
+ return obj
133
+ else
134
+ begin
135
+ return obj.to_hash
136
+ rescue NoMethodError
137
+ begin
138
+ return obj.to_ary
139
+ rescue NoMethodError
140
+ begin
141
+ return obj.to_str
142
+ rescue NoMethodError
143
+ begin
144
+ return obj.to_int
145
+ rescue NoMethodError
146
+ begin
147
+ return obj.to_f
148
+ rescue NoMethodError
149
+ raise TypeError, "not JSONable: #{obj.class}"
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ def try_escape_string str
159
+ buf = nil
160
+
161
+ begin
162
+ # fast path
163
+ if str.valid_encoding?
164
+ str2 = str.encode Encoding::UTF_8
165
+ buf = str.unpack('U*')
166
+ end
167
+ rescue Encoding::UndefinedConversionError
168
+ # str might be invalid, but that's OK as per RFC7159 section 8.2.
169
+ end
170
+
171
+ unless buf
172
+ case str.encoding
173
+ when Encoding::UTF_32BE then buf = str.unpack 'N*'
174
+ when Encoding::UTF_32LE then buf = str.unpack 'V*'
175
+ when Encoding::UTF_16BE then buf = str.unpack 'n*'
176
+ when Encoding::UTF_16LE then buf = str.unpack 'v*'
177
+ when Encoding::UTF_8,
178
+ Encoding::UTF8_MAC,
179
+ Encoding::US_ASCII then buf = str.unpack 'U*'
180
+ else buf = str.unpack 'C*' # fallback
181
+ end
182
+ end
183
+
184
+ # We don't escape \/, because that seems to be de facto standard.
185
+ return buf.inject '' do |r, i|
186
+ c = nil
187
+ case i
188
+ when 0x22 then c = '\\"' # " quotation mark U+0022
189
+ when 0x5C then c = '\\\\' # \ reverse solidus U+005C
190
+ # when 0x2F then c = '\\/' # / solidus U+002F
191
+ when 0x08 then c = '\\b' # b backspace U+0008
192
+ when 0x0C then c = '\\f' # f form feed U+000C
193
+ when 0x0A then c = '\\n' # n line feed U+000A
194
+ when 0x0D then c = '\\r' # r carriage return U+000D
195
+ when 0x09 then c = '\\t' # t tab U+0009
196
+ when 0x00..0x1F, 0xD800..0xDFFF then
197
+ c = sprintf '\\u%04X', i
198
+ else
199
+ c = [i].pack 'U'
200
+ end
201
+ r << c
202
+ end
203
+ end
204
+
205
+ def try_stringize_numeric num
206
+ case num
207
+ when Float, BigDecimal
208
+ if num.finite?
209
+ # FIXME: does this lose precision?
210
+ num.to_s
211
+ else
212
+ raise TypeError, "not JSONable: #{num.inspect}"
213
+ end
214
+ when Integer
215
+ return num.to_s
216
+ else
217
+ raise TypeError, "not JSONable: #{num.inspect}"
218
+ end
219
+ end
220
+ end
221
+
222
+ #
223
+ # Local Variables:
224
+ # mode: ruby
225
+ # coding: utf-8-unix
226
+ # indent-tabs-mode: t
227
+ # tab-width: 3
228
+ # ruby-indent-level: 3
229
+ # fill-column: 79
230
+ # default-justification: full
231
+ # End: