@@ -622,19 +622,40 @@ private enum _JSONNumberParser {
622
622
}
623
623
624
624
static func parseFloatingPoint< Floating: BinaryFloatingPoint > ( source: UnsafeBufferPointer < UInt8 > ) -> Floating ? {
625
- var endPtr : UnsafeMutablePointer < CChar > ? = nil
626
- let value : Floating ?
627
- if Floating . self == Double . self {
628
- value = Floating ( exactly: strtod ( source. baseAddress!, & endPtr) )
629
- } else if Floating . self == Float . self {
630
- value = Floating ( exactly: strtof ( source. baseAddress!, & endPtr) )
625
+ // Since source is not NUL terminated, we need to make a temporary storage.
626
+ // Depending on the length of the source, prepare the buffer on stack or heap,
627
+ // then call 'impl(_:)' (defined below) for the actual operation.
628
+ if source. count + 1 <= MemoryLayout< UInt64> . size {
629
+ var stash : UInt64 = 0
630
+ return withUnsafeMutableBytes ( of: & stash) {
631
+ $0. withMemoryRebound ( to: UInt8 . self, impl)
632
+ }
631
633
} else {
632
- fatalError ( " unsupported floating point type " )
634
+ let stash = UnsafeMutableBufferPointer< UInt8> . allocate( capacity: source. count + 1 )
635
+ defer { stash. deallocate ( ) }
636
+ return impl ( stash)
633
637
}
634
- guard endPtr! == source. baseAddress! + source. count else {
635
- return nil
638
+
639
+ func impl( _ stash: UnsafeMutableBufferPointer < UInt8 > ) -> Floating ? {
640
+ // Create a NUL terminated string in the stash.
641
+ assert ( stash. count >= source. count + 1 )
642
+ let end = stash. initialize ( fromContentsOf: source)
643
+ stash. initializeElement ( at: end, to: 0 )
644
+
645
+ var endPtr : UnsafeMutablePointer < CChar > ? = nil
646
+ let value : Floating ?
647
+ if Floating . self == Double . self {
648
+ value = Floating ( exactly: strtod ( stash. baseAddress!, & endPtr) )
649
+ } else if Floating . self == Float . self {
650
+ value = Floating ( exactly: strtof ( stash. baseAddress!, & endPtr) )
651
+ } else {
652
+ preconditionFailure ( " unsupported floating point type " )
653
+ }
654
+ guard let endPtr, endPtr == stash. baseAddress! + source. count else {
655
+ return nil
656
+ }
657
+ return value
636
658
}
637
- return value
638
659
}
639
660
640
661
static func parseHexIntegerDigits< Integer: FixedWidthInteger > ( source: UnsafeBufferPointer < UInt8 > ) -> Integer ? {
0 commit comments