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,79 @@
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 false, as defined in RFC7159 section 3.
35
+ class RFC7159::False < RFC7159::Value
36
+
37
+ # Parse the AST from parser, and convert into corrsponding value.
38
+ # @param [::Array] ast the AST, generated by the parser
39
+ # @return [False] evaluated instance
40
+ # @raise [ArgumentError] malformed input
41
+ def self.from_ast ast
42
+ raise ArgumentError "garbage included: #{ast.inspect}" if ast.length > 1
43
+ raise ArgumentError "not a false: #{ast.inspect}" if ast[0] != :false
44
+ return new
45
+ end
46
+
47
+ # convert to Ruby's false
48
+ # @return [false] the ruby counter part.
49
+ def plain_old_ruby_object
50
+ return false
51
+ end
52
+
53
+ # JSON gem compat
54
+ # @return [::String] JSONified string representation
55
+ def to_json
56
+ return 'false'
57
+ end
58
+
59
+ # Equality. All false instances are equal each other, plus a FalseClass
60
+ # instance is also equal to this.
61
+ def == other
62
+ case other when FalseClass, self.class
63
+ true
64
+ else
65
+ false
66
+ end
67
+ end
68
+ end
69
+
70
+ #
71
+ # Local Variables:
72
+ # mode: ruby
73
+ # coding: utf-8-unix
74
+ # indent-tabs-mode: t
75
+ # tab-width: 3
76
+ # ruby-indent-level: 3
77
+ # fill-column: 79
78
+ # default-justification: full
79
+ # End:
@@ -0,0 +1,79 @@
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 null, as defined in RFC7159 section 3.
35
+ class RFC7159::Null < RFC7159::Value
36
+
37
+ # Parse the AST from parser, and convert into corrsponding value.
38
+ # @param [::Array] ast the AST, generated by the parser
39
+ # @return [Null] evaluated instance
40
+ # @raise [ArgumentError] malformed input
41
+ def self.from_ast ast
42
+ raise ArgumentError "garbage included: #{ast.inspect}" if ast.length > 1
43
+ raise ArgumentError "not a false: #{ast.inspect}" if ast[0] != :null
44
+ return new
45
+ end
46
+
47
+ # convert to Ruby's nil
48
+ # @return [nil] the ruby counter part.
49
+ def plain_old_ruby_object
50
+ return nil
51
+ end
52
+
53
+ # JSON gem compat
54
+ # @return [::String] JSONified string representation
55
+ def to_json
56
+ return 'null'
57
+ end
58
+
59
+ # Equality. All null instances are equal each other, plus a NilClass
60
+ # instance is also equal to this.
61
+ def == other
62
+ case other when NilClass, self.class
63
+ true
64
+ else
65
+ false
66
+ end
67
+ end
68
+ end
69
+
70
+ #
71
+ # Local Variables:
72
+ # mode: ruby
73
+ # coding: utf-8-unix
74
+ # indent-tabs-mode: t
75
+ # tab-width: 3
76
+ # ruby-indent-level: 3
77
+ # fill-column: 79
78
+ # default-justification: full
79
+ # End:
@@ -0,0 +1,149 @@
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 'bigdecimal'
35
+
36
+ # The Numbers, as described in RFC7159 section 6.
37
+ class RFC7159::Number < RFC7159::Value
38
+
39
+ # Notie about technical design: this class _could_ have been made much
40
+ # faster if we implement the whole type-conversion thing by hand. But that
41
+ # is very bug-prone. So to avoid unnecessary complexity here we took an
42
+ # approach to first let everything be BigDecimal, then convert to others
43
+ # like Float.
44
+
45
+ # Parse the AST from parser, and convert into corrsponding values.
46
+ # @param [::Array] ast the AST, generated by the parser
47
+ # @return [Number] evaluated instance
48
+ # @raise [ArgumentError] malformed input
49
+ def self.from_ast ast
50
+ type, sign, int, frac, exp = *ast
51
+ raise ArgumentError, "not an object: #{ast.inspect}" if type != :number
52
+ raise ArgumentError, "not a number: #{ast.inspect}" if int.nil?
53
+ new sign, int, frac, exp
54
+ end
55
+
56
+ # @return [Numeric] converted numeric
57
+ # @note this conversion might lose precision. Use `to_d` if you want
58
+ # something that fully represents this number.
59
+ def plain_old_ruby_object
60
+ if /\A[+-]?\d+\z/ =~ @to_s
61
+ return to_i
62
+ else
63
+ return to_f
64
+ end
65
+ end
66
+
67
+ # @return [BigDecimal] lossless conversion to numeric
68
+ def to_d
69
+ return @to_d
70
+ end
71
+
72
+ # @return [::String] the original string
73
+ def to_s
74
+ return @to_s.dup # dup just in case.
75
+ end
76
+
77
+ # JSON gem compat
78
+ # @return [::String] the original string
79
+ def to_json *;
80
+ return to_s
81
+ end
82
+
83
+ # @return [Float] conversion to float
84
+ def to_f
85
+ # This method must be ideoponent so the result is cached
86
+ unless @to_f
87
+ num = to_d.to_f
88
+ @to_f ||= num # ||= to avoid race
89
+ end
90
+ return @to_f
91
+ end
92
+
93
+ # @return [Integer] conversion to integer
94
+ def to_i
95
+ # This method must be ideoponent so the result is cached
96
+ unless @to_i
97
+ num = to_d.to_i
98
+ @to_i ||= num # ||= to avoid race
99
+ end
100
+ return @to_i
101
+ end
102
+
103
+ # @return [::String] the value in string
104
+ def inspect
105
+ sprintf "#<%p:%p>", self.class, plain_old_ruby_object
106
+ end
107
+
108
+ # For pretty print (require 'pp' beforehand)
109
+ # @param [PP] pp the pp
110
+ def pretty_print pp
111
+ pp.object_group self do
112
+ pp.text ':'
113
+ plain_old_ruby_object.pretty_print pp
114
+ end
115
+ end
116
+
117
+ # Number equality is _not_ defined in the RFC so we take liberty of defining
118
+ # that to be mathematical comparison
119
+ def == other
120
+ other == @to_d
121
+ end
122
+
123
+ private
124
+
125
+ private_class_method:new
126
+ # @private
127
+ def initialize sign, int, frac, exp
128
+ @sign = sign # nil, '-', or '+'
129
+ @int = int.join
130
+ @frac = frac && frac.join # nil, or '.dddd..'
131
+ @exp = exp && exp.join # nil, or 'e+ddd..'
132
+
133
+ # pre-cache common computations
134
+ @to_s = sprintf "%s%s%s%s", @sign, @int, @frac, @exp
135
+ @to_s.freeze # just in case
136
+ @to_d = BigDecimal.new @to_s
137
+ end
138
+ end
139
+
140
+ #
141
+ # Local Variables:
142
+ # mode: ruby
143
+ # coding: utf-8-unix
144
+ # indent-tabs-mode: t
145
+ # tab-width: 3
146
+ # ruby-indent-level: 3
147
+ # fill-column: 79
148
+ # default-justification: full
149
+ # End:
@@ -0,0 +1,140 @@
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 Objects, as described in RFC7159 section 4.
35
+ class RFC7159::Object < 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 [Object] evaluated instance
40
+ # @raise [ArgumentError] malformed input
41
+ def self.from_ast ast
42
+ type, *assoc = *ast
43
+ raise ArgumentError, "not an object: #{ast.inspect}" if type != :object
44
+ assoc.map! do |a|
45
+ a.map! do |b|
46
+ RFC7159::Value.from_ast b
47
+ end
48
+ end
49
+ new assoc
50
+ end
51
+
52
+ # fetch the key.
53
+ # @note RFC7159 allows identical key to appear multiple times in an object.
54
+ # @note This is O(1)
55
+ # @param [::String, String] key key to look at
56
+ # @return [ [Value] ] corresponding value(s)
57
+ def [] key
58
+ ret = @assoc.select do |(k, v)| k == key end
59
+ ret.map! do |(k, v)| v end
60
+ return ret
61
+ end
62
+
63
+ # iterates over the pairs.
64
+ # @yield [key, value] the pair.
65
+ def each_pair
66
+ e = Enumerator.new do |y|
67
+ @assoc.each do |a|
68
+ y << a
69
+ end
70
+ end
71
+ return block_given? ? e.each(&b) : e
72
+ end
73
+
74
+ alias each each_pair
75
+
76
+ # @raise [RuntimeError] keys conflict
77
+ # @return [::Hash] converted object
78
+ def plain_old_ruby_object
79
+ ret = Hash.new
80
+ @assoc.each do |(k, v)|
81
+ kk = k.plain_old_ruby_object
82
+ if ret.include? kk
83
+ raise RuntimeError, "key #{kk} conflict."
84
+ else
85
+ vv = v.plain_old_ruby_object
86
+ ret.store kk, vv
87
+ end
88
+ end
89
+ return ret
90
+ end
91
+
92
+ alias to_h plain_old_ruby_object
93
+ alias to_hash plain_old_ruby_object
94
+
95
+ # @return [::String] the object in string
96
+ def inspect
97
+ hdr = sprintf "#<%p:%#016x {", self.class, self.object_id << 1
98
+ map = @assoc.map do |(k, v)|
99
+ sprintf '%p: %p', k.to_s, v
100
+ end.join ', '
101
+ hdr << map << '}>'
102
+ end
103
+
104
+ # For pretty print
105
+ # @param [PP] pp the pp
106
+ def pretty_print pp
107
+ hdr = sprintf '#<%p:%#016x', self.class, self.object_id << 1
108
+ pp.group 1, hdr, '>' do
109
+ pp.breakable
110
+ pp.group 1, '{', '}' do
111
+ @assoc.each_with_index do |(k, v), i|
112
+ pp.breakable ',' if i.nonzero?
113
+ k.to_s.pretty_print pp
114
+ pp.text ': '
115
+ v.pretty_print pp
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ private
122
+ private_class_method:new
123
+ # @private
124
+ def initialize assoc
125
+ @assoc = assoc
126
+ @assoc.each {|i| i.freeze }
127
+ @assoc.freeze
128
+ end
129
+ end
130
+
131
+ #
132
+ # Local Variables:
133
+ # mode: ruby
134
+ # coding: utf-8-unix
135
+ # indent-tabs-mode: t
136
+ # tab-width: 3
137
+ # ruby-indent-level: 3
138
+ # fill-column: 79
139
+ # default-justification: full
140
+ # End: