json 1.0.0 → 2.7.2
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/CHANGES.md +503 -0
- data/LICENSE +56 -0
- data/README.md +416 -0
- data/ext/json/ext/fbuffer/fbuffer.h +187 -0
- data/ext/json/ext/generator/depend +1 -0
- data/ext/json/ext/generator/extconf.rb +2 -7
- data/ext/json/ext/generator/generator.c +1312 -338
- data/ext/json/ext/generator/generator.h +177 -0
- data/ext/json/ext/parser/depend +1 -0
- data/ext/json/ext/parser/extconf.rb +28 -5
- data/ext/json/ext/parser/parser.c +1349 -689
- data/ext/json/ext/parser/parser.h +96 -0
- data/ext/json/ext/parser/parser.rl +644 -188
- data/ext/json/extconf.rb +3 -0
- data/json.gemspec +68 -0
- data/lib/json/add/bigdecimal.rb +58 -0
- data/lib/json/add/complex.rb +51 -0
- data/lib/json/add/core.rb +12 -0
- data/lib/json/add/date.rb +54 -0
- data/lib/json/add/date_time.rb +67 -0
- data/lib/json/add/exception.rb +49 -0
- data/lib/json/add/ostruct.rb +54 -0
- data/lib/json/add/range.rb +54 -0
- data/lib/json/add/rational.rb +49 -0
- data/lib/json/add/regexp.rb +48 -0
- data/lib/json/add/set.rb +48 -0
- data/lib/json/add/struct.rb +52 -0
- data/lib/json/add/symbol.rb +48 -0
- data/lib/json/add/time.rb +59 -0
- data/lib/json/common.rb +588 -74
- data/lib/json/ext.rb +3 -1
- data/lib/json/generic_object.rb +75 -0
- data/lib/json/pure/generator.rb +311 -119
- data/lib/json/pure/parser.rb +182 -55
- data/lib/json/pure.rb +5 -65
- data/lib/json/version.rb +2 -1
- data/lib/json.rb +583 -196
- metadata +78 -137
- data/CHANGES +0 -25
- data/GPL +0 -340
- data/README +0 -77
- data/Rakefile +0 -250
- data/TODO +0 -1
- data/VERSION +0 -1
- data/benchmarks/benchmark.txt +0 -133
- data/benchmarks/benchmark_generator.rb +0 -44
- data/benchmarks/benchmark_parser.rb +0 -22
- data/benchmarks/benchmark_rails.rb +0 -26
- data/bin/edit_json.rb +0 -11
- data/data/example.json +0 -1
- data/data/index.html +0 -37
- data/data/prototype.js +0 -2515
- data/ext/json/ext/generator/Makefile +0 -149
- data/ext/json/ext/generator/unicode.c +0 -184
- data/ext/json/ext/generator/unicode.h +0 -40
- data/ext/json/ext/parser/Makefile +0 -149
- data/ext/json/ext/parser/unicode.c +0 -156
- data/ext/json/ext/parser/unicode.h +0 -44
- data/install.rb +0 -26
- data/lib/json/Array.xpm +0 -21
- data/lib/json/FalseClass.xpm +0 -21
- data/lib/json/Hash.xpm +0 -21
- data/lib/json/Key.xpm +0 -73
- data/lib/json/NilClass.xpm +0 -21
- data/lib/json/Numeric.xpm +0 -28
- data/lib/json/String.xpm +0 -96
- data/lib/json/TrueClass.xpm +0 -21
- data/lib/json/editor.rb +0 -1207
- data/lib/json/json.xpm +0 -1499
- data/tests/fixtures/fail1.json +0 -1
- data/tests/fixtures/fail10.json +0 -1
- data/tests/fixtures/fail11.json +0 -1
- data/tests/fixtures/fail12.json +0 -1
- data/tests/fixtures/fail13.json +0 -1
- data/tests/fixtures/fail14.json +0 -1
- data/tests/fixtures/fail15.json +0 -1
- data/tests/fixtures/fail16.json +0 -1
- data/tests/fixtures/fail17.json +0 -1
- data/tests/fixtures/fail19.json +0 -1
- data/tests/fixtures/fail2.json +0 -1
- data/tests/fixtures/fail20.json +0 -1
- data/tests/fixtures/fail21.json +0 -1
- data/tests/fixtures/fail22.json +0 -1
- data/tests/fixtures/fail23.json +0 -1
- data/tests/fixtures/fail24.json +0 -1
- data/tests/fixtures/fail25.json +0 -1
- data/tests/fixtures/fail26.json +0 -1
- data/tests/fixtures/fail27.json +0 -2
- data/tests/fixtures/fail28.json +0 -2
- data/tests/fixtures/fail3.json +0 -1
- data/tests/fixtures/fail4.json +0 -1
- data/tests/fixtures/fail5.json +0 -1
- data/tests/fixtures/fail6.json +0 -1
- data/tests/fixtures/fail7.json +0 -1
- data/tests/fixtures/fail8.json +0 -1
- data/tests/fixtures/fail9.json +0 -1
- data/tests/fixtures/pass1.json +0 -56
- data/tests/fixtures/pass18.json +0 -1
- data/tests/fixtures/pass2.json +0 -1
- data/tests/fixtures/pass3.json +0 -6
- data/tests/runner.rb +0 -24
- data/tests/test_json.rb +0 -235
- data/tests/test_json_addition.rb +0 -94
- data/tests/test_json_fixtures.rb +0 -30
- data/tests/test_json_generate.rb +0 -81
- data/tests/test_json_unicode.rb +0 -55
- data/tools/fuzz.rb +0 -133
- data/tools/server.rb +0 -62
data/lib/json/pure/parser.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
#frozen_string_literal: false
|
1
2
|
require 'strscan'
|
2
3
|
|
3
4
|
module JSON
|
@@ -6,9 +7,12 @@ module JSON
|
|
6
7
|
# into a Ruby data structure.
|
7
8
|
class Parser < StringScanner
|
8
9
|
STRING = /" ((?:[^\x0-\x1f"\\] |
|
10
|
+
# escaped special characters:
|
9
11
|
\\["\\\/bfnrt] |
|
10
|
-
\\u[0-9a-fA-F]{4}
|
11
|
-
|
12
|
+
\\u[0-9a-fA-F]{4} |
|
13
|
+
# match all but escaped special characters:
|
14
|
+
\\[\x20-\x21\x23-\x2e\x30-\x5b\x5d-\x61\x63-\x65\x67-\x6d\x6f-\x71\x73\x75-\xff])*)
|
15
|
+
"/nx
|
12
16
|
INTEGER = /(-?0|-?[1-9]\d*)/
|
13
17
|
FLOAT = /(-?
|
14
18
|
(?:0|[1-9]\d*)
|
@@ -18,6 +22,9 @@ module JSON
|
|
18
22
|
(?i:e[+-]?\d+)
|
19
23
|
)
|
20
24
|
)/x
|
25
|
+
NAN = /NaN/
|
26
|
+
INFINITY = /Infinity/
|
27
|
+
MINUS_INFINITY = /-Infinity/
|
21
28
|
OBJECT_OPEN = /\{/
|
22
29
|
OBJECT_CLOSE = /\}/
|
23
30
|
ARRAY_OPEN = /\[/
|
@@ -35,83 +42,184 @@ module JSON
|
|
35
42
|
[^*/]| # normal chars
|
36
43
|
/[^*]| # slashes that do not start a nested comment
|
37
44
|
\*[^/]| # asterisks that do not end this comment
|
38
|
-
/(?=\*/) # single slash before this comment's end
|
45
|
+
/(?=\*/) # single slash before this comment's end
|
39
46
|
)*
|
40
47
|
\*/ # the End of this comment
|
41
|
-
|[ \t\r\n]+ # whitespaces: space,
|
48
|
+
|[ \t\r\n]+ # whitespaces: space, horizontal tab, lf, cr
|
42
49
|
)+
|
43
50
|
)mx
|
44
51
|
|
45
|
-
UNPARSED = Object.new
|
52
|
+
UNPARSED = Object.new.freeze
|
46
53
|
|
47
54
|
# Creates a new JSON::Pure::Parser instance for the string _source_.
|
48
|
-
|
49
|
-
|
50
|
-
|
55
|
+
#
|
56
|
+
# It will be configured by the _opts_ hash. _opts_ can have the following
|
57
|
+
# keys:
|
58
|
+
# * *max_nesting*: The maximum depth of nesting allowed in the parsed data
|
59
|
+
# structures. Disable depth checking with :max_nesting => false|nil|0,
|
60
|
+
# it defaults to 100.
|
61
|
+
# * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
|
62
|
+
# defiance of RFC 7159 to be parsed by the Parser. This option defaults
|
63
|
+
# to false.
|
64
|
+
# * *freeze*: If set to true, all parsed objects will be frozen. Parsed
|
65
|
+
# string will be deduplicated if possible.
|
66
|
+
# * *symbolize_names*: If set to true, returns symbols for the names
|
67
|
+
# (keys) in a JSON object. Otherwise strings are returned, which is
|
68
|
+
# also the default. It's not possible to use this option in
|
69
|
+
# conjunction with the *create_additions* option.
|
70
|
+
# * *create_additions*: If set to true, the Parser creates
|
71
|
+
# additions when a matching class and create_id are found. This
|
72
|
+
# option defaults to false.
|
73
|
+
# * *object_class*: Defaults to Hash
|
74
|
+
# * *array_class*: Defaults to Array
|
75
|
+
# * *decimal_class*: Specifies which class to use instead of the default
|
76
|
+
# (Float) when parsing decimal numbers. This class must accept a single
|
77
|
+
# string argument in its constructor.
|
78
|
+
def initialize(source, opts = {})
|
79
|
+
opts ||= {}
|
80
|
+
source = convert_encoding source
|
81
|
+
super source
|
82
|
+
if !opts.key?(:max_nesting) # defaults to 100
|
83
|
+
@max_nesting = 100
|
84
|
+
elsif opts[:max_nesting]
|
85
|
+
@max_nesting = opts[:max_nesting]
|
86
|
+
else
|
87
|
+
@max_nesting = 0
|
88
|
+
end
|
89
|
+
@allow_nan = !!opts[:allow_nan]
|
90
|
+
@symbolize_names = !!opts[:symbolize_names]
|
91
|
+
@freeze = !!opts[:freeze]
|
92
|
+
if opts.key?(:create_additions)
|
93
|
+
@create_additions = !!opts[:create_additions]
|
94
|
+
else
|
95
|
+
@create_additions = false
|
96
|
+
end
|
97
|
+
@symbolize_names && @create_additions and raise ArgumentError,
|
98
|
+
'options :symbolize_names and :create_additions cannot be used '\
|
99
|
+
'in conjunction'
|
100
|
+
@create_id = @create_additions ? JSON.create_id : nil
|
101
|
+
@object_class = opts[:object_class] || Hash
|
102
|
+
@array_class = opts[:array_class] || Array
|
103
|
+
@decimal_class = opts[:decimal_class]
|
104
|
+
@match_string = opts[:match_string]
|
51
105
|
end
|
52
106
|
|
53
107
|
alias source string
|
54
108
|
|
55
|
-
|
56
|
-
|
109
|
+
def reset
|
110
|
+
super
|
111
|
+
@current_nesting = 0
|
112
|
+
end
|
113
|
+
|
114
|
+
# Parses the current JSON string _source_ and returns the
|
115
|
+
# complete data structure as a result.
|
57
116
|
def parse
|
58
117
|
reset
|
59
118
|
obj = nil
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
when skip(IGNORE)
|
69
|
-
;
|
70
|
-
else
|
71
|
-
raise ParserError, "source '#{peek(20)}' not in JSON!"
|
72
|
-
end
|
119
|
+
while !eos? && skip(IGNORE) do end
|
120
|
+
if eos?
|
121
|
+
raise ParserError, "source is not valid JSON!"
|
122
|
+
else
|
123
|
+
obj = parse_value
|
124
|
+
UNPARSED.equal?(obj) and raise ParserError,
|
125
|
+
"source is not valid JSON!"
|
126
|
+
obj.freeze if @freeze
|
73
127
|
end
|
74
|
-
|
128
|
+
while !eos? && skip(IGNORE) do end
|
129
|
+
eos? or raise ParserError, "source is not valid JSON!"
|
75
130
|
obj
|
76
131
|
end
|
77
132
|
|
78
133
|
private
|
79
134
|
|
135
|
+
def convert_encoding(source)
|
136
|
+
if source.respond_to?(:to_str)
|
137
|
+
source = source.to_str
|
138
|
+
else
|
139
|
+
raise TypeError,
|
140
|
+
"#{source.inspect} is not like a string"
|
141
|
+
end
|
142
|
+
if source.encoding != ::Encoding::ASCII_8BIT
|
143
|
+
source = source.encode(::Encoding::UTF_8)
|
144
|
+
source.force_encoding(::Encoding::ASCII_8BIT)
|
145
|
+
end
|
146
|
+
source
|
147
|
+
end
|
148
|
+
|
149
|
+
# Unescape characters in strings.
|
150
|
+
UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
|
151
|
+
UNESCAPE_MAP.update({
|
152
|
+
?" => '"',
|
153
|
+
?\\ => '\\',
|
154
|
+
?/ => '/',
|
155
|
+
?b => "\b",
|
156
|
+
?f => "\f",
|
157
|
+
?n => "\n",
|
158
|
+
?r => "\r",
|
159
|
+
?t => "\t",
|
160
|
+
?u => nil,
|
161
|
+
})
|
162
|
+
|
163
|
+
EMPTY_8BIT_STRING = ''
|
164
|
+
if ::String.method_defined?(:encode)
|
165
|
+
EMPTY_8BIT_STRING.force_encoding Encoding::ASCII_8BIT
|
166
|
+
end
|
167
|
+
|
168
|
+
STR_UMINUS = ''.respond_to?(:-@)
|
80
169
|
def parse_string
|
81
170
|
if scan(STRING)
|
82
171
|
return '' if self[1].empty?
|
83
|
-
self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
when '\\b' then "\b"
|
89
|
-
when '\\f' then "\f"
|
90
|
-
when '\\n' then "\n"
|
91
|
-
when '\\r' then "\r"
|
92
|
-
when '\\t' then "\t"
|
93
|
-
else
|
94
|
-
bytes = ''
|
95
|
-
c = $~[0]
|
172
|
+
string = self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do |c|
|
173
|
+
if u = UNESCAPE_MAP[$&[1]]
|
174
|
+
u
|
175
|
+
else # \uXXXX
|
176
|
+
bytes = EMPTY_8BIT_STRING.dup
|
96
177
|
i = 0
|
97
|
-
while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
|
178
|
+
while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
|
98
179
|
bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
|
99
180
|
i += 1
|
100
181
|
end
|
101
|
-
JSON
|
182
|
+
JSON.iconv('utf-8', 'utf-16be', bytes).force_encoding(::Encoding::ASCII_8BIT)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
if string.respond_to?(:force_encoding)
|
186
|
+
string.force_encoding(::Encoding::UTF_8)
|
187
|
+
end
|
188
|
+
|
189
|
+
if @freeze
|
190
|
+
if STR_UMINUS
|
191
|
+
string = -string
|
192
|
+
else
|
193
|
+
string.freeze
|
102
194
|
end
|
103
195
|
end
|
196
|
+
|
197
|
+
if @create_additions and @match_string
|
198
|
+
for (regexp, klass) in @match_string
|
199
|
+
klass.json_creatable? or next
|
200
|
+
string =~ regexp and return klass.json_create(string)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
string
|
104
204
|
else
|
105
205
|
UNPARSED
|
106
206
|
end
|
107
|
-
rescue
|
108
|
-
raise
|
207
|
+
rescue => e
|
208
|
+
raise ParserError, "Caught #{e.class} at '#{peek(20)}': #{e}"
|
109
209
|
end
|
110
210
|
|
111
211
|
def parse_value
|
112
212
|
case
|
113
213
|
when scan(FLOAT)
|
114
|
-
|
214
|
+
if @decimal_class then
|
215
|
+
if @decimal_class == BigDecimal then
|
216
|
+
BigDecimal(self[1])
|
217
|
+
else
|
218
|
+
@decimal_class.new(self[1]) || Float(self[1])
|
219
|
+
end
|
220
|
+
else
|
221
|
+
Float(self[1])
|
222
|
+
end
|
115
223
|
when scan(INTEGER)
|
116
224
|
Integer(self[1])
|
117
225
|
when scan(TRUE)
|
@@ -120,23 +228,39 @@ module JSON
|
|
120
228
|
false
|
121
229
|
when scan(NULL)
|
122
230
|
nil
|
123
|
-
when (string = parse_string)
|
231
|
+
when !UNPARSED.equal?(string = parse_string)
|
124
232
|
string
|
125
233
|
when scan(ARRAY_OPEN)
|
126
|
-
|
234
|
+
@current_nesting += 1
|
235
|
+
ary = parse_array
|
236
|
+
@current_nesting -= 1
|
237
|
+
ary
|
127
238
|
when scan(OBJECT_OPEN)
|
128
|
-
|
239
|
+
@current_nesting += 1
|
240
|
+
obj = parse_object
|
241
|
+
@current_nesting -= 1
|
242
|
+
obj
|
243
|
+
when @allow_nan && scan(NAN)
|
244
|
+
NaN
|
245
|
+
when @allow_nan && scan(INFINITY)
|
246
|
+
Infinity
|
247
|
+
when @allow_nan && scan(MINUS_INFINITY)
|
248
|
+
MinusInfinity
|
129
249
|
else
|
130
250
|
UNPARSED
|
131
251
|
end
|
132
252
|
end
|
133
253
|
|
134
254
|
def parse_array
|
135
|
-
|
255
|
+
raise NestingError, "nesting of #@current_nesting is too deep" if
|
256
|
+
@max_nesting.nonzero? && @current_nesting > @max_nesting
|
257
|
+
result = @array_class.new
|
136
258
|
delim = false
|
137
|
-
|
259
|
+
loop do
|
138
260
|
case
|
139
|
-
when
|
261
|
+
when eos?
|
262
|
+
raise ParserError, "unexpected end of string while parsing array"
|
263
|
+
when !UNPARSED.equal?(value = parse_value)
|
140
264
|
delim = false
|
141
265
|
result << value
|
142
266
|
skip(IGNORE)
|
@@ -162,18 +286,22 @@ module JSON
|
|
162
286
|
end
|
163
287
|
|
164
288
|
def parse_object
|
165
|
-
|
289
|
+
raise NestingError, "nesting of #@current_nesting is too deep" if
|
290
|
+
@max_nesting.nonzero? && @current_nesting > @max_nesting
|
291
|
+
result = @object_class.new
|
166
292
|
delim = false
|
167
|
-
|
293
|
+
loop do
|
168
294
|
case
|
169
|
-
when
|
295
|
+
when eos?
|
296
|
+
raise ParserError, "unexpected end of string while parsing object"
|
297
|
+
when !UNPARSED.equal?(string = parse_string)
|
170
298
|
skip(IGNORE)
|
171
299
|
unless scan(PAIR_DELIMITER)
|
172
300
|
raise ParserError, "expected ':' in object at '#{peek(20)}'!"
|
173
301
|
end
|
174
302
|
skip(IGNORE)
|
175
|
-
unless (value = parse_value)
|
176
|
-
result[string] = value
|
303
|
+
unless UNPARSED.equal?(value = parse_value)
|
304
|
+
result[@symbolize_names ? string.to_sym : string] = value
|
177
305
|
delim = false
|
178
306
|
skip(IGNORE)
|
179
307
|
if scan(COLLECTION_DELIMITER)
|
@@ -190,11 +318,10 @@ module JSON
|
|
190
318
|
if delim
|
191
319
|
raise ParserError, "expected next name, value pair in object at '#{peek(20)}'!"
|
192
320
|
end
|
193
|
-
if klassname = result[@create_id]
|
321
|
+
if @create_additions and klassname = result[@create_id]
|
194
322
|
klass = JSON.deep_const_get klassname
|
195
323
|
break unless klass and klass.json_creatable?
|
196
324
|
result = klass.json_create(result)
|
197
|
-
result
|
198
325
|
end
|
199
326
|
break
|
200
327
|
when skip(IGNORE)
|
data/lib/json/pure.rb
CHANGED
@@ -1,75 +1,15 @@
|
|
1
1
|
require 'json/common'
|
2
|
-
require 'json/pure/parser'
|
3
|
-
require 'json/pure/generator'
|
4
2
|
|
5
3
|
module JSON
|
6
|
-
begin
|
7
|
-
require 'iconv'
|
8
|
-
# An iconv instance to convert from UTF8 to UTF16 Big Endian.
|
9
|
-
UTF16toUTF8 = Iconv.new('utf-8', 'utf-16be') # :nodoc:
|
10
|
-
# An iconv instance to convert from UTF16 Big Endian to UTF8.
|
11
|
-
UTF8toUTF16 = Iconv.new('utf-16be', 'utf-8') # :nodoc:
|
12
|
-
UTF8toUTF16.iconv('no bom')
|
13
|
-
rescue Errno::EINVAL, Iconv::InvalidEncoding
|
14
|
-
# Iconv doesn't support big endian utf-16. Let's try to hack this manually
|
15
|
-
# into the converters.
|
16
|
-
begin
|
17
|
-
old_verbose, $VERBSOSE = $VERBOSE, nil
|
18
|
-
# An iconv instance to convert from UTF8 to UTF16 Big Endian.
|
19
|
-
UTF16toUTF8 = Iconv.new('utf-8', 'utf-16') # :nodoc:
|
20
|
-
# An iconv instance to convert from UTF16 Big Endian to UTF8.
|
21
|
-
UTF8toUTF16 = Iconv.new('utf-16', 'utf-8') # :nodoc:
|
22
|
-
UTF8toUTF16.iconv('no bom')
|
23
|
-
if UTF8toUTF16.iconv("\xe2\x82\xac") == "\xac\x20"
|
24
|
-
swapper = Class.new do
|
25
|
-
def initialize(iconv) # :nodoc:
|
26
|
-
@iconv = iconv
|
27
|
-
end
|
28
|
-
|
29
|
-
def iconv(string) # :nodoc:
|
30
|
-
result = @iconv.iconv(string)
|
31
|
-
JSON.swap!(result)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
UTF8toUTF16 = swapper.new(UTF8toUTF16) # :nodoc:
|
35
|
-
end
|
36
|
-
if UTF16toUTF8.iconv("\xac\x20") == "\xe2\x82\xac"
|
37
|
-
swapper = Class.new do
|
38
|
-
def initialize(iconv) # :nodoc:
|
39
|
-
@iconv = iconv
|
40
|
-
end
|
41
|
-
|
42
|
-
def iconv(string) # :nodoc:
|
43
|
-
string = JSON.swap!(string.dup)
|
44
|
-
@iconv.iconv(string)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
UTF16toUTF8 = swapper.new(UTF16toUTF8) # :nodoc:
|
48
|
-
end
|
49
|
-
rescue Errno::EINVAL, Iconv::InvalidEncoding
|
50
|
-
raise MissingUnicodeSupport, "iconv doesn't seem to support UTF-8/UTF-16 conversions"
|
51
|
-
ensure
|
52
|
-
$VERBOSE = old_verbose
|
53
|
-
end
|
54
|
-
rescue LoadError
|
55
|
-
raise MissingUnicodeSupport,
|
56
|
-
"iconv couldn't be loaded, which is required for UTF-8/UTF-16 conversions"
|
57
|
-
end
|
58
|
-
|
59
|
-
# Swap consecutive bytes of _string_ in place.
|
60
|
-
def self.swap!(string) # :nodoc:
|
61
|
-
0.upto(string.size / 2) do |i|
|
62
|
-
break unless string[2 * i + 1]
|
63
|
-
string[2 * i], string[2 * i + 1] = string[2 * i + 1], string[2 * i]
|
64
|
-
end
|
65
|
-
string
|
66
|
-
end
|
67
|
-
|
68
4
|
# This module holds all the modules/classes that implement JSON's
|
69
5
|
# functionality in pure ruby.
|
70
6
|
module Pure
|
71
|
-
|
7
|
+
require 'json/pure/parser'
|
8
|
+
require 'json/pure/generator'
|
9
|
+
$DEBUG and warn "Using Pure library for JSON."
|
72
10
|
JSON.parser = Parser
|
73
11
|
JSON.generator = Generator
|
74
12
|
end
|
13
|
+
|
14
|
+
JSON_LOADED = true unless defined?(::JSON::JSON_LOADED)
|
75
15
|
end
|
data/lib/json/version.rb
CHANGED