@@ -622,19 +622,40 @@ private enum _JSONNumberParser {
622622 }
623623
624624 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+ }
631633 } 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)
633637 }
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
636658 }
637- return value
638659 }
639660
640661 static func parseHexIntegerDigits< Integer: FixedWidthInteger > ( source: UnsafeBufferPointer < UInt8 > ) -> Integer ? {
0 commit comments