| //===----------------------------------------------------------------------===// |
| // |
| // 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 http://swift.org/LICENSE.txt for license information |
| // See http://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 infinty 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`: |
| /// |
| /// Double(" 5.0") // Includes whitespace |
| /// Double("±2.0") // Invalid character |
| /// Double("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<CChar>) -> (${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 |