//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// import SwiftShims %{ allFloatBits = [16, 32, 64, 80] def floatName(bits): if bits == 16: return 'Float16' if bits == 32: return 'Float' if bits == 64: return 'Double' if bits == 80: return 'Float80' cFuncSuffix2 = {16: 'f16', 32: 'f', 64: 'd', 80: 'ld'} }% /// Returns `true` if isspace(u) would return nonzero when the current /// locale is the C locale; otherwise, returns false. @inlinable // FIXME(sil-serialize-all) internal func _isspace_clocale(_ u: UTF16.CodeUnit) -> Bool { return "\t\n\u{b}\u{c}\r ".utf16.contains(u) } % for bits in allFloatBits: % Self = floatName(bits) % if bits == 80: #if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64)) % elif bits == 16: #if !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64)) % end %if bits == 16: @available(SwiftStdlib 5.3, *) %end extension ${Self}: LosslessStringConvertible { /// Creates a new instance from the given string. /// /// The string passed as `text` can represent a real number in decimal or /// hexadecimal format or can be in a special format representing infinity /// or NaN ("not a number"). If `text` is not in a recognized format, /// the optional initializer will fail and return `nil`. /// /// The `text` string consists of an optional /// plus or minus sign character (`+` or `-`) /// followed by one of the following: /// /// - A *decimal string* contains a significand consisting of one /// or more decimal digits that may include a decimal point: /// /// let c = ${Self}("-1.0") /// // c == -1.0 /// /// let d = ${Self}("28.375") /// // d == 28.375 /// /// A decimal string may also include an exponent following the /// significand, indicating the power of 10 by which the significand should /// be multiplied. If included, the exponent is separated by a single /// character, `e` or `E`, and consists of an optional plus or minus sign /// character and a sequence of decimal digits. /// /// let e = ${Self}("2837.5e-2") /// // e == 28.375 /// /// - A *hexadecimal string* contains a significand consisting of /// `0X` or `0x` followed by one or more hexadecimal digits that may /// include a decimal point. /// /// let f = ${Self}("0x1c.6") /// // f == 28.375 /// /// A hexadecimal string may also include an exponent /// indicating the power of 2 by which the significand should /// be multiplied. If included, the exponent is separated by a single /// character, `p` or `P`, and consists of an optional plus or minus sign /// character and a sequence of decimal digits. /// /// let g = ${Self}("0x1.c6p4") /// // g == 28.375 /// /// - The input strings `"inf"` or `"infinity"` (case insensitive) /// are converted to an infinite result: /// /// let i = ${Self}("inf") /// // i == ${Self}.infinity /// /// let j = ${Self}("-Infinity") /// // j == -${Self}.infinity /// /// - An input string of `"nan"` (case insensitive) is converted /// into a *NaN* value: /// /// let n = ${Self}("-nan") /// // n?.isNaN == true /// // n?.sign == .minus /// /// A NaN string may also include a payload in parentheses following the /// `"nan"` keyword. The payload consists of a sequence of decimal digits, /// or the characters `0X` or `0x` followed by a sequence of hexadecimal /// digits. If the payload contains any other characters, it is ignored. /// If the value of the payload is larger than can be stored as the /// payload of a `${Self}.nan`, the least significant bits are used. /// /// let p = ${Self}("nan(0x10)") /// // p?.isNaN == true /// // String(p!) == "nan(0x10)" /// /// A string in any other format than those described above /// or containing additional characters /// results in a `nil` value. For example, the following conversions /// result in `nil`: /// /// ${Self}(" 5.0") // Includes whitespace /// ${Self}("±2.0") // Invalid character /// ${Self}("0x1.25e4") // Incorrect exponent format /// /// A decimal or hexadecimal string is converted to a `${Self}` /// instance using the IEEE 754 roundTiesToEven (default) rounding /// attribute. /// Values with absolute value smaller than `${Self}.leastNonzeroMagnitude` /// are rounded to plus or minus zero. /// Values with absolute value larger than `${Self}.greatestFiniteMagnitude` /// are rounded to plus or minus infinity. /// /// let y = ${Self}("1.23e-9999") /// // y == 0.0 /// // y?.sign == .plus /// /// let z = ${Self}("-7.89e-7206") /// // z == -0.0 /// // z?.sign == .minus /// /// let r = ${Self}("1.23e17802") /// // r == ${Self}.infinity /// /// let s = ${Self}("-7.89e7206") /// // s == ${Self}.-infinity /// /// - Note: Prior to Swift 5.4, a decimal or /// hexadecimal input string whose value was too large to represent /// as a finite `${Self}` instance returned `nil` instead of /// `${Self}.infinity`. /// /// - Parameter text: An input string to convert to a `${Self}?` instance. /// @inlinable public init?(_ text: S) { %if bits == 16: self.init(Substring(text)) %else: if #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) { //SwiftStdlib 5.3 self.init(Substring(text)) } else { self = 0.0 let success = withUnsafeMutablePointer(to: &self) { p -> Bool in text.withCString { chars -> Bool in switch chars[0] { case 9, 10, 11, 12, 13, 32: return false // Reject leading whitespace case 0: return false // Reject empty string default: break } let endPtr = _swift_stdlib_strto${cFuncSuffix2[bits]}_clocale(chars, p) // Succeed only if endPtr points to end of C string return endPtr != nil && endPtr![0] == 0 } } if !success { return nil } } %end } // Caveat: This implementation used to be inlineable. // In particular, we still have to export // _swift_stdlib_strtoXYZ_clocale() // as ABI to support old compiled code that still requires it. @available(SwiftStdlib 5.3, *) public init?(_ text: Substring) { self = 0.0 let success = withUnsafeMutablePointer(to: &self) { p -> Bool in text.withCString { chars -> Bool in switch chars[0] { case 9, 10, 11, 12, 13, 32: return false // Reject leading whitespace case 0: return false // Reject empty string default: break } let endPtr = _swift_stdlib_strto${cFuncSuffix2[bits]}_clocale(chars, p) // Succeed only if endPtr points to end of C string return endPtr != nil && endPtr![0] == 0 } } if !success { return nil } } } % if bits in [16,80]: #endif % end % end // ${'Local Variables'}: // eval: (read-only-mode 1) // End: