21
21
# THE SOFTWARE.
22
22
23
23
# See https://github.com/kr/okjson for updates.
24
- # Imported from the above repo @ d4e8643ad92e14b37d11326855499c7e4108ed17
25
- # Namespace modified for vendoring under Rack::Utils
26
24
27
25
require 'stringio'
28
26
29
27
# Some parts adapted from
30
- # http ://golang.org/src/pkg /json/decode.go and
31
- # http ://golang.org/src/pkg /utf8/utf8.go
28
+ # https ://golang.org/src/encoding /json/decode.go and
29
+ # https ://golang.org/src/unicode /utf8/utf8.go
32
30
module Rack ::Utils ::OkJson
33
- Upstream = 'LTD7LBKLZWFF7OZK '
31
+ Upstream = '43 '
34
32
extend self
35
33
36
34
@@ -52,12 +50,49 @@ def decode(s)
52
50
end
53
51
54
52
53
+ # Encodes x into a json text. It may contain only
54
+ # Array, Hash, String, Numeric, true, false, nil.
55
+ # (Note, this list excludes Symbol.)
56
+ # X itself must be an Array or a Hash.
57
+ # No other value can be encoded, and an error will
58
+ # be raised if x contains any other value, such as
59
+ # Nan, Infinity, Symbol, and Proc, or if a Hash key
60
+ # is not a String.
61
+ # Strings contained in x must be valid UTF-8.
62
+ def encode ( x )
63
+ case x
64
+ when Hash then objenc ( x )
65
+ when Array then arrenc ( x )
66
+ else
67
+ raise Error , 'root value must be an Array or a Hash'
68
+ end
69
+ end
70
+
71
+
72
+ def valenc ( x )
73
+ case x
74
+ when Hash then objenc ( x )
75
+ when Array then arrenc ( x )
76
+ when String then strenc ( x )
77
+ when Numeric then numenc ( x )
78
+ when true then "true"
79
+ when false then "false"
80
+ when nil then "null"
81
+ else
82
+ raise Error , "cannot encode #{ x . class } : #{ x . inspect } "
83
+ end
84
+ end
85
+
86
+
87
+ private
88
+
89
+
55
90
# Parses a "json text" in the sense of RFC 4627.
56
91
# Returns the parsed value and any trailing tokens.
57
92
# Note: this is almost the same as valparse,
58
93
# except that it does not accept atomic values.
59
94
def textparse ( ts )
60
- if ts . length < 0
95
+ if ts . length <= 0
61
96
raise Error , 'empty'
62
97
end
63
98
@@ -74,7 +109,7 @@ def textparse(ts)
74
109
# Parses a "value" in the sense of RFC 4627.
75
110
# Returns the parsed value and any trailing tokens.
76
111
def valparse ( ts )
77
- if ts . length < 0
112
+ if ts . length <= 0
78
113
raise Error , 'empty'
79
114
end
80
115
@@ -203,21 +238,19 @@ def lex(s)
203
238
# it is the lexeme.
204
239
def tok ( s )
205
240
case s [ 0 ]
206
- when ?{ then [ '{' , s [ 0 , 1 ] , s [ 0 , 1 ] ]
207
- when ?} then [ '}' , s [ 0 , 1 ] , s [ 0 , 1 ] ]
208
- when ?: then [ ':' , s [ 0 , 1 ] , s [ 0 , 1 ] ]
209
- when ?, then [ ',' , s [ 0 , 1 ] , s [ 0 , 1 ] ]
210
- when ?[ then [ '[' , s [ 0 , 1 ] , s [ 0 , 1 ] ]
211
- when ?] then [ ']' , s [ 0 , 1 ] , s [ 0 , 1 ] ]
212
- when ?n then nulltok ( s )
213
- when ?t then truetok ( s )
214
- when ?f then falsetok ( s )
215
- when ?" then strtok ( s )
216
- when Spc then [ :space , s [ 0 , 1 ] , s [ 0 , 1 ] ]
217
- when ?\t then [ :space , s [ 0 , 1 ] , s [ 0 , 1 ] ]
218
- when ?\n then [ :space , s [ 0 , 1 ] , s [ 0 , 1 ] ]
219
- when ?\r then [ :space , s [ 0 , 1 ] , s [ 0 , 1 ] ]
220
- else numtok ( s )
241
+ when ?{ then [ '{' , s [ 0 , 1 ] , s [ 0 , 1 ] ]
242
+ when ?} then [ '}' , s [ 0 , 1 ] , s [ 0 , 1 ] ]
243
+ when ?: then [ ':' , s [ 0 , 1 ] , s [ 0 , 1 ] ]
244
+ when ?, then [ ',' , s [ 0 , 1 ] , s [ 0 , 1 ] ]
245
+ when ?[ then [ '[' , s [ 0 , 1 ] , s [ 0 , 1 ] ]
246
+ when ?] then [ ']' , s [ 0 , 1 ] , s [ 0 , 1 ] ]
247
+ when ?n then nulltok ( s )
248
+ when ?t then truetok ( s )
249
+ when ?f then falsetok ( s )
250
+ when ?" then strtok ( s )
251
+ when Spc , ?\t, ?\n, ?\r then [ :space , s [ 0 , 1 ] , s [ 0 , 1 ] ]
252
+ else
253
+ numtok ( s )
221
254
end
222
255
end
223
256
@@ -230,12 +263,12 @@ def falsetok(s); s[0,5] == 'false' ? [:val, 'false', false] : [] end
230
263
def numtok ( s )
231
264
m = /-?([1-9][0-9]+|[0-9])([.][0-9]+)?([eE][+-]?[0-9]+)?/ . match ( s )
232
265
if m && m . begin ( 0 ) == 0
233
- if m [ 3 ] && !m [ 2 ]
234
- [ :val , m [ 0 ] , Integer ( m [ 1 ] ) * ( 10 ** Integer ( m [ 3 ] [ 1 ..- 1 ] ) ) ]
266
+ if ! m [ 2 ] && !m [ 3 ]
267
+ [ :val , m [ 0 ] , Integer ( m [ 0 ] ) ]
235
268
elsif m [ 2 ]
236
269
[ :val , m [ 0 ] , Float ( m [ 0 ] ) ]
237
270
else
238
- [ :val , m [ 0 ] , Integer ( m [ 0 ] ) ]
271
+ [ :val , m [ 0 ] , Integer ( m [ 1 ] ) * ( 10 ** m [ 3 ] [ 1 ..- 1 ] . to_i ( 10 ) ) ]
239
272
end
240
273
else
241
274
[ ]
@@ -267,17 +300,14 @@ def abbrev(s)
267
300
def unquote ( q )
268
301
q = q [ 1 ...-1 ]
269
302
a = q . dup # allocate a big enough string
270
- rubydoesenc = false
271
303
# In ruby >= 1.9, a[w] is a codepoint, not a byte.
272
- if a . class . method_defined? ( :force_encoding )
304
+ if rubydoesenc?
273
305
a . force_encoding ( 'UTF-8' )
274
- rubydoesenc = true
275
306
end
276
307
r , w = 0 , 0
277
308
while r < q . length
278
309
c = q [ r ]
279
- case true
280
- when c == ?\\
310
+ if c == ?\\
281
311
r += 1
282
312
if r >= q . length
283
313
raise Error , "string literal ends with a \" \\ \" : \" #{ q } \" "
@@ -310,7 +340,7 @@ def unquote(q)
310
340
end
311
341
end
312
342
end
313
- if rubydoesenc
343
+ if rubydoesenc?
314
344
a [ w ] = '' << uchar
315
345
w += 1
316
346
else
@@ -319,7 +349,7 @@ def unquote(q)
319
349
else
320
350
raise Error , "invalid escape char #{ q [ r ] } in \" #{ q } \" "
321
351
end
322
- when c == ?", c < Spc
352
+ elsif c == ?" || c < Spc
323
353
raise Error , "invalid character in string literal \" #{ q } \" "
324
354
else
325
355
# Copy anything else byte-for-byte.
@@ -340,15 +370,14 @@ def unquote(q)
340
370
# bytes in string a at position i.
341
371
# Returns the number of bytes written.
342
372
def ucharenc ( a , i , u )
343
- case true
344
- when u <= Uchar1max
373
+ if u <= Uchar1max
345
374
a [ i ] = ( u & 0xff ) . chr
346
375
1
347
- when u <= Uchar2max
376
+ elsif u <= Uchar2max
348
377
a [ i +0 ] = ( Utag2 | ( ( u >>6 ) &0xff ) ) . chr
349
378
a [ i +1 ] = ( Utagx | ( u &Umaskx ) ) . chr
350
379
2
351
- when u <= Uchar3max
380
+ elsif u <= Uchar3max
352
381
a [ i +0 ] = ( Utag3 | ( ( u >>12 ) &0xff ) ) . chr
353
382
a [ i +1 ] = ( Utagx | ( ( u >>6 ) &Umaskx ) ) . chr
354
383
a [ i +2 ] = ( Utagx | ( u &Umaskx ) ) . chr
@@ -385,50 +414,15 @@ def surrogate?(u)
385
414
386
415
387
416
def nibble ( c )
388
- case true
389
- when ?0 <= c && c <= ?9 then c . ord - ?0. ord
390
- when ?a <= c && c <= ?z then c . ord - ?a. ord + 10
391
- when ?A <= c && c <= ?Z then c . ord - ?A. ord + 10
417
+ if ?0 <= c && c <= ?9 then c . ord - ?0. ord
418
+ elsif ?a <= c && c <= ?z then c . ord - ?a. ord + 10
419
+ elsif ?A <= c && c <= ?Z then c . ord - ?A. ord + 10
392
420
else
393
421
raise Error , "invalid hex code #{ c } "
394
422
end
395
423
end
396
424
397
425
398
- # Encodes x into a json text. It may contain only
399
- # Array, Hash, String, Numeric, true, false, nil.
400
- # (Note, this list excludes Symbol.)
401
- # X itself must be an Array or a Hash.
402
- # No other value can be encoded, and an error will
403
- # be raised if x contains any other value, such as
404
- # Nan, Infinity, Symbol, and Proc, or if a Hash key
405
- # is not a String.
406
- # Strings contained in x must be valid UTF-8.
407
- def encode ( x )
408
- case x
409
- when Hash then objenc ( x )
410
- when Array then arrenc ( x )
411
- else
412
- raise Error , 'root value must be an Array or a Hash'
413
- end
414
- end
415
-
416
-
417
- def valenc ( x )
418
- case x
419
- when Hash then objenc ( x )
420
- when Array then arrenc ( x )
421
- when String then strenc ( x )
422
- when Numeric then numenc ( x )
423
- when true then "true"
424
- when false then "false"
425
- when nil then "null"
426
- else
427
- raise Error , "cannot encode #{ x . class } : #{ x . inspect } "
428
- end
429
- end
430
-
431
-
432
426
def objenc ( x )
433
427
'{' + x . map { |k , v | keyenc ( k ) + ':' + valenc ( v ) } . join ( ',' ) + '}'
434
428
end
@@ -453,9 +447,6 @@ def strenc(s)
453
447
t . putc ( ?")
454
448
r = 0
455
449
456
- # In ruby >= 1.9, s[r] is a codepoint, not a byte.
457
- rubydoesenc = s . class . method_defined? ( :encoding )
458
-
459
450
while r < s . length
460
451
case s [ r ]
461
452
when ?" then t . print ( '\\"' )
@@ -467,15 +458,20 @@ def strenc(s)
467
458
when ?\t then t . print ( '\\t' )
468
459
else
469
460
c = s [ r ]
470
- case true
471
- when rubydoesenc
461
+ # In ruby >= 1.9, s[r] is a codepoint, not a byte.
462
+ if rubydoesenc?
472
463
begin
473
- c . ord # will raise an error if c is invalid UTF-8
464
+ # c.ord will raise an error if c is invalid UTF-8
465
+ if c . ord < Spc . ord
466
+ c = "\\ u%04x" % [ c . ord ]
467
+ end
474
468
t . write ( c )
475
469
rescue
476
470
t . write ( Ustrerr )
477
471
end
478
- when Spc <= c && c <= ?~
472
+ elsif c < Spc
473
+ t . write ( "\\ u%04x" % c )
474
+ elsif Spc <= c && c <= ?~
479
475
t . putc ( c )
480
476
else
481
477
n = ucharcopy ( t , s , r ) # ensure valid UTF-8 output
@@ -567,6 +563,11 @@ def ucharcopy(t, s, i)
567
563
end
568
564
569
565
566
+ def rubydoesenc?
567
+ ::String . method_defined? ( :force_encoding )
568
+ end
569
+
570
+
570
571
class Utf8Error < ::StandardError
571
572
end
572
573
@@ -575,15 +576,15 @@ class Error < ::StandardError
575
576
end
576
577
577
578
578
- Utagx = 0x80 # 1000 0000
579
- Utag2 = 0xc0 # 1100 0000
580
- Utag3 = 0xe0 # 1110 0000
581
- Utag4 = 0xf0 # 1111 0000
582
- Utag5 = 0xF8 # 1111 1000
583
- Umaskx = 0x3f # 0011 1111
584
- Umask2 = 0x1f # 0001 1111
585
- Umask3 = 0x0f # 0000 1111
586
- Umask4 = 0x07 # 0000 0111
579
+ Utagx = 0b1000_0000
580
+ Utag2 = 0b1100_0000
581
+ Utag3 = 0b1110_0000
582
+ Utag4 = 0b1111_0000
583
+ Utag5 = 0b1111_1000
584
+ Umaskx = 0b0011_1111
585
+ Umask2 = 0b0001_1111
586
+ Umask3 = 0b0000_1111
587
+ Umask4 = 0b0000_0111
587
588
Uchar1max = ( 1 <<7 ) - 1
588
589
Uchar2max = ( 1 <<11 ) - 1
589
590
Uchar3max = ( 1 <<16 ) - 1
0 commit comments