@@ -63,7 +63,9 @@ open class JSONSerialization : NSObject {
63
63
}
64
64
65
65
// object is Swift.String, NSNull, Int, Bool, or UInt
66
- if obj is String || obj is NSNull || obj is Int || obj is Bool || obj is UInt {
66
+ if obj is String || obj is NSNull || obj is Int || obj is Bool || obj is UInt ||
67
+ obj is Int8 || obj is Int16 || obj is Int32 || obj is Int64 ||
68
+ obj is UInt8 || obj is UInt16 || obj is UInt32 || obj is UInt64 {
67
69
return true
68
70
}
69
71
@@ -76,6 +78,10 @@ open class JSONSerialization : NSObject {
76
78
return number. isFinite
77
79
}
78
80
81
+ if let number = obj as? Decimal {
82
+ return number. isFinite
83
+ }
84
+
79
85
// object is Swift.Array
80
86
if let array = obj as? [ Any ? ] {
81
87
for element in array {
@@ -99,8 +105,11 @@ open class JSONSerialization : NSObject {
99
105
// object is NSNumber and is not NaN or infinity
100
106
// For better performance, this (most expensive) test should be last.
101
107
if let number = _SwiftValue. store ( obj) as? NSNumber {
102
- let invalid = number. doubleValue. isInfinite || number. doubleValue. isNaN
103
- return !invalid
108
+ if CFNumberIsFloatType ( number. _cfObject) {
109
+ return number. doubleValue. isFinite
110
+ } else {
111
+ return true
112
+ }
104
113
}
105
114
106
115
// invalid object
@@ -285,9 +294,7 @@ internal extension JSONSerialization {
285
294
286
295
//MARK: - JSONSerializer
287
296
private struct JSONWriter {
288
-
289
- private let maxUIntLength = String ( describing: UInt . max) . count
290
- private let maxIntLength = String ( describing: Int . max) . count
297
+
291
298
var indent = 0
292
299
let pretty : Bool
293
300
let sortedKeys : Bool
@@ -320,13 +327,37 @@ private struct JSONWriter {
320
327
case let boolValue as Bool :
321
328
serializeBool ( boolValue)
322
329
case let num as Int :
323
- try serializeInt ( value: num)
330
+ serializeInteger ( value: num)
331
+ case let num as Int8 :
332
+ serializeInteger ( value: num)
333
+ case let num as Int16 :
334
+ serializeInteger ( value: num)
335
+ case let num as Int32 :
336
+ serializeInteger ( value: num)
337
+ case let num as Int64 :
338
+ serializeInteger ( value: num)
324
339
case let num as UInt :
325
- try serializeUInt ( value: num)
340
+ serializeInteger ( value: num)
341
+ case let num as UInt8 :
342
+ serializeInteger ( value: num)
343
+ case let num as UInt16 :
344
+ serializeInteger ( value: num)
345
+ case let num as UInt32 :
346
+ serializeInteger ( value: num)
347
+ case let num as UInt64 :
348
+ serializeInteger ( value: num)
326
349
case let array as Array < Any ? > :
327
350
try serializeArray ( array)
328
351
case let dict as Dictionary < AnyHashable , Any ? > :
329
352
try serializeDictionary ( dict)
353
+ case let num as Float :
354
+ try serializeNumber ( NSNumber ( value: num) )
355
+ case let num as Double :
356
+ try serializeNumber ( NSNumber ( value: num) )
357
+ case let num as Decimal :
358
+ writer ( num. description)
359
+ case let num as NSDecimalNumber :
360
+ writer ( num. description)
330
361
case is NSNull :
331
362
try serializeNull ( )
332
363
case _ where _SwiftValue. store ( obj) is NSNumber :
@@ -336,92 +367,33 @@ private struct JSONWriter {
336
367
}
337
368
}
338
369
339
- private func serializeUInt( value: UInt ) throws {
340
- if value == 0 {
341
- writer ( " 0 " )
342
- return
343
- }
344
- var array : [ UInt ] = [ ]
345
- var stringResult = " "
346
- //Maximum length of an UInt
347
- array. reserveCapacity ( maxUIntLength)
348
- stringResult. reserveCapacity ( maxUIntLength)
349
- var number = value
350
-
351
- while number != 0 {
352
- array. append ( number % 10 )
370
+ private func serializeInteger< T: UnsignedInteger > ( value: T , isNegative: Bool = false ) {
371
+ let maxIntLength = 22 // 20 digits in UInt64 + optional sign + trailing '\0'
372
+ let ZERO : CChar = 0x30 // ASCII '0' == 0x30
373
+ let MINUS : CChar = 0x2d // ASCII '-' == 0x2d
374
+
375
+ var number = UInt64 ( value)
376
+ var buffer = Array < CChar > ( repeating: 0 , count: maxIntLength)
377
+ var pos = maxIntLength - 1
378
+
379
+ repeat {
380
+ pos -= 1
381
+ buffer [ pos] = ZERO + CChar( number % 10 )
353
382
number /= 10
383
+ } while number != 0
384
+
385
+ if isNegative {
386
+ pos -= 1
387
+ buffer [ pos] = MINUS
354
388
}
355
-
356
- /*
357
- Step backwards through the array and append the values to the string. This way the values are appended in the correct order.
358
- */
359
- var counter = array. count
360
- while counter > 0 {
361
- counter -= 1
362
- let digit : UInt = array [ counter]
363
- switch digit {
364
- case 0 : stringResult. append ( " 0 " )
365
- case 1 : stringResult. append ( " 1 " )
366
- case 2 : stringResult. append ( " 2 " )
367
- case 3 : stringResult. append ( " 3 " )
368
- case 4 : stringResult. append ( " 4 " )
369
- case 5 : stringResult. append ( " 5 " )
370
- case 6 : stringResult. append ( " 6 " )
371
- case 7 : stringResult. append ( " 7 " )
372
- case 8 : stringResult. append ( " 8 " )
373
- case 9 : stringResult. append ( " 9 " )
374
- default : fatalError ( )
375
- }
376
- }
377
-
378
- writer ( stringResult)
389
+ let output = String ( cString: Array ( buffer. suffix ( from: pos) ) )
390
+ writer ( output)
379
391
}
380
-
381
- private func serializeInt( value: Int ) throws {
382
- if value == 0 {
383
- writer ( " 0 " )
384
- return
385
- }
386
- var array : [ Int ] = [ ]
387
- var stringResult = " "
388
- array. reserveCapacity ( maxIntLength)
389
- //Account for a negative sign
390
- stringResult. reserveCapacity ( maxIntLength + 1 )
391
- var number = value
392
-
393
- while number != 0 {
394
- array. append ( number % 10 )
395
- number /= 10
396
- }
397
- //If negative add minus sign before adding any values
398
- if value < 0 {
399
- stringResult. append ( " - " )
400
- }
401
- /*
402
- Step backwards through the array and append the values to the string. This way the values are appended in the correct order.
403
- */
404
- var counter = array. count
405
- while counter > 0 {
406
- counter -= 1
407
- let digit = array [ counter]
408
- switch digit {
409
- case 0 : stringResult. append ( " 0 " )
410
- case 1 , - 1 : stringResult. append ( " 1 " )
411
- case 2 , - 2 : stringResult. append ( " 2 " )
412
- case 3 , - 3 : stringResult. append ( " 3 " )
413
- case 4 , - 4 : stringResult. append ( " 4 " )
414
- case 5 , - 5 : stringResult. append ( " 5 " )
415
- case 6 , - 6 : stringResult. append ( " 6 " )
416
- case 7 , - 7 : stringResult. append ( " 7 " )
417
- case 8 , - 8 : stringResult. append ( " 8 " )
418
- case 9 , - 9 : stringResult. append ( " 9 " )
419
- default : fatalError ( )
420
- }
421
- }
422
- writer ( stringResult)
392
+
393
+ private func serializeInteger< T: SignedInteger > ( value: T ) {
394
+ serializeInteger ( value: UInt64 ( value. magnitude) , isNegative: value < 0 )
423
395
}
424
-
396
+
425
397
func serializeString( _ str: String ) throws {
426
398
writer ( " \" " )
427
399
for scalar in str. unicodeScalars {
@@ -462,15 +434,20 @@ private struct JSONWriter {
462
434
}
463
435
464
436
mutating func serializeNumber( _ num: NSNumber ) throws {
465
- if num. doubleValue. isInfinite || num. doubleValue. isNaN {
466
- throw NSError ( domain: NSCocoaErrorDomain, code: CocoaError . propertyListReadCorrupt. rawValue, userInfo: [ " NSDebugDescription " : " Number cannot be infinity or NaN " ] )
467
- }
468
-
469
- switch num. _cfTypeID {
470
- case CFBooleanGetTypeID ( ) :
471
- serializeBool ( num. boolValue)
472
- default :
473
- writer ( _serializationString ( for: num) )
437
+ if CFNumberIsFloatType ( num. _cfObject) {
438
+ if !num. doubleValue. isFinite {
439
+ throw NSError ( domain: NSCocoaErrorDomain, code: CocoaError . propertyListReadCorrupt. rawValue, userInfo: [ " NSDebugDescription " : " Number cannot be infinity or NaN " ] )
440
+ }
441
+
442
+ let string = CFNumberFormatterCreateStringWithNumber ( nil , _numberformatter, num. _cfObject) . _swiftObject
443
+ writer ( string)
444
+ } else {
445
+ switch num. _cfTypeID {
446
+ case CFBooleanGetTypeID ( ) :
447
+ serializeBool ( num. boolValue)
448
+ default :
449
+ writer ( num. stringValue)
450
+ }
474
451
}
475
452
}
476
453
@@ -578,13 +555,6 @@ private struct JSONWriter {
578
555
}
579
556
}
580
557
581
- //[SR-2151] https://bugs.swift.org/browse/SR-2151
582
- private mutating func _serializationString( for number: NSNumber ) -> String {
583
- if !CFNumberIsFloatType( number. _cfObject) {
584
- return number. stringValue
585
- }
586
- return CFNumberFormatterCreateStringWithNumber ( nil , _numberformatter, number. _cfObject) . _swiftObject
587
- }
588
558
}
589
559
590
560
//MARK: - JSONDeserializer
0 commit comments