//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 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 = [32, 64, 80] def floatName(bits): if bits == 32: return 'Float' if bits == 64: return 'Double' if bits == 80: return 'Float80' cFuncSuffix2 = {32: 'f', 64: 'd', 80: 'ld'} }% /// Returns `true` iff isspace(u) would return nonzero when the current /// locale is the C locale. 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) && (arch(i386) || arch(x86_64)) % end //===--- Parsing ----------------------------------------------------------===// 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 special floating-point values for infinity and NaN /// ("not a number"). /// /// The given string may begin with a plus or minus sign character (`+` or /// `-`). The allowed formats for each of these representations is then as /// follows: /// /// - A *decimal value* contains the significand, a sequence of 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 value 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 value* contains the significand, either `0X` or `0x`, /// followed by a sequence of hexadecimal digits. The significand may /// include a decimal point. /// /// let f = ${Self}("0x1c.6") /// // f == 28.375 /// /// A hexadecimal value may also include an exponent following the /// significand, 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 /// /// - A value of *infinity* contains one of the strings `"inf"` or /// `"infinity"`, case insensitive. /// /// let i = ${Self}("inf") /// // i == ${Self}.infinity /// /// let j = ${Self}("-Infinity") /// // j == -${Self}.infinity /// /// - A value of *NaN* contains the string `"nan"`, case insensitive. /// /// let n = ${Self}("-nan") /// // n?.isNaN == true /// // n?.sign == .minus /// /// A NaN value 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)" /// /// Passing any other format or any additional characters as `text` results /// in `nil`. For example, the following conversions result in `nil`: /// /// ${Self}(" 5.0") // Includes whitespace /// ${Self}("±2.0") // Invalid character /// ${Self}("0x1.25e4") // Incorrect exponent format /// /// - Parameter text: The input string to convert to a `${Self}` instance. If /// `text` has invalid characters or is in an invalid format, the result /// is `nil`. public init?(_ text: String) { let u16 = text.utf16 func parseNTBS(_ chars: UnsafePointer) -> (${Self}, Int) { var result: ${Self} = 0 let endPtr = withUnsafeMutablePointer(to: &result) { _swift_stdlib_strto${cFuncSuffix2[bits]}_clocale(chars, $0) } return (result, endPtr == nil ? 0 : endPtr! - chars) } let (result, n) = text.withCString(parseNTBS) if n == 0 || n != u16.count || u16.contains(where: { $0 > 127 || _isspace_clocale($0) }) { return nil } self = result } } % if bits == 80: #endif % end % end