blob: bca1e817f00149b032e5c6ff9fa6dad6105035a0 [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 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
extension String {
/// Creates a new string representing the given string repeated the specified
/// number of times.
///
/// For example, you can use this initializer to create a string with ten
/// `"ab"` strings in a row.
///
/// let s = String(repeating: "ab", count: 10)
/// print(s)
/// // Prints "abababababababababab"
///
/// - Parameters:
/// - repeatedValue: The string to repeat.
/// - count: The number of times to repeat `repeatedValue` in the resulting
/// string.
public init(repeating repeatedValue: String, count: Int) {
if count == 0 {
self = ""
return
}
precondition(count > 0, "Negative count not allowed")
let s = repeatedValue
self = String(_storage: _StringBuffer(
capacity: s._core.count * count,
initialSize: 0,
elementWidth: s._core.elementWidth))
for _ in 0..<count {
self += s
}
}
/// A Boolean value indicating whether a string has no characters.
public var isEmpty: Bool {
return _core.count == 0
}
}
extension String {
public init(_ _c: Unicode.Scalar) {
self = String._fromWellFormedCodeUnitSequence(
UTF32.self,
input: repeatElement(_c.value, count: 1))
}
}
#if _runtime(_ObjC)
/// Determines if `theString` starts with `prefix` comparing the strings under
/// canonical equivalence.
@_silgen_name("swift_stdlib_NSStringHasPrefixNFD")
func _stdlib_NSStringHasPrefixNFD(_ theString: AnyObject, _ prefix: AnyObject) -> Bool
@_silgen_name("swift_stdlib_NSStringHasPrefixNFDPointer")
func _stdlib_NSStringHasPrefixNFDPointer(_ theString: OpaquePointer, _ prefix: OpaquePointer) -> Bool
/// Determines if `theString` ends with `suffix` comparing the strings under
/// canonical equivalence.
@_silgen_name("swift_stdlib_NSStringHasSuffixNFD")
func _stdlib_NSStringHasSuffixNFD(_ theString: AnyObject, _ suffix: AnyObject) -> Bool
@_silgen_name("swift_stdlib_NSStringHasSuffixNFDPointer")
func _stdlib_NSStringHasSuffixNFDPointer(_ theString: OpaquePointer, _ suffix: OpaquePointer) -> Bool
extension String {
/// Returns a Boolean value indicating whether the string begins with the
/// specified prefix.
///
/// The comparison is both case sensitive and Unicode safe. The
/// case-sensitive comparison will only match strings whose corresponding
/// characters have the same case.
///
/// let cafe = "Café du Monde"
///
/// // Case sensitive
/// print(cafe.hasPrefix("café"))
/// // Prints "false"
///
/// The Unicode-safe comparison matches Unicode scalar values rather than the
/// code points used to compose them. The example below uses two strings
/// with different forms of the `"é"` character---the first uses the composed
/// form and the second uses the decomposed form.
///
/// // Unicode safe
/// let composedCafe = "Café"
/// let decomposedCafe = "Cafe\u{0301}"
///
/// print(cafe.hasPrefix(composedCafe))
/// // Prints "true"
/// print(cafe.hasPrefix(decomposedCafe))
/// // Prints "true"
///
/// - Parameter prefix: A possible prefix to test against this string.
/// - Returns: `true` if the string begins with `prefix`; otherwise, `false`.
public func hasPrefix(_ prefix: String) -> Bool {
let selfCore = self._core
let prefixCore = prefix._core
let prefixCount = prefixCore.count
if prefixCount == 0 {
return true
}
if let selfASCIIBuffer = selfCore.asciiBuffer,
let prefixASCIIBuffer = prefixCore.asciiBuffer {
if prefixASCIIBuffer.count > selfASCIIBuffer.count {
// Prefix is longer than self.
return false
}
return _swift_stdlib_memcmp(
selfASCIIBuffer.baseAddress!,
prefixASCIIBuffer.baseAddress!,
prefixASCIIBuffer.count) == (0 as CInt)
}
if selfCore.hasContiguousStorage && prefixCore.hasContiguousStorage {
let lhsStr = _NSContiguousString(selfCore)
let rhsStr = _NSContiguousString(prefixCore)
return lhsStr._unsafeWithNotEscapedSelfPointerPair(rhsStr) {
return _stdlib_NSStringHasPrefixNFDPointer($0, $1)
}
}
return _stdlib_NSStringHasPrefixNFD(
self._bridgeToObjectiveCImpl(), prefix._bridgeToObjectiveCImpl())
}
/// Returns a Boolean value indicating whether the string ends with the
/// specified suffix.
///
/// The comparison is both case sensitive and Unicode safe. The
/// case-sensitive comparison will only match strings whose corresponding
/// characters have the same case.
///
/// let plans = "Let's meet at the café"
///
/// // Case sensitive
/// print(plans.hasSuffix("Café"))
/// // Prints "false"
///
/// The Unicode-safe comparison matches Unicode scalar values rather than the
/// code points used to compose them. The example below uses two strings
/// with different forms of the `"é"` character---the first uses the composed
/// form and the second uses the decomposed form.
///
/// // Unicode safe
/// let composedCafe = "café"
/// let decomposedCafe = "cafe\u{0301}"
///
/// print(plans.hasSuffix(composedCafe))
/// // Prints "true"
/// print(plans.hasSuffix(decomposedCafe))
/// // Prints "true"
///
/// - Parameter suffix: A possible suffix to test against this string.
/// - Returns: `true` if the string ends with `suffix`; otherwise, `false`.
public func hasSuffix(_ suffix: String) -> Bool {
let selfCore = self._core
let suffixCore = suffix._core
let suffixCount = suffixCore.count
if suffixCount == 0 {
return true
}
if let selfASCIIBuffer = selfCore.asciiBuffer,
let suffixASCIIBuffer = suffixCore.asciiBuffer {
if suffixASCIIBuffer.count > selfASCIIBuffer.count {
// Suffix is longer than self.
return false
}
return _swift_stdlib_memcmp(
selfASCIIBuffer.baseAddress!
+ (selfASCIIBuffer.count - suffixASCIIBuffer.count),
suffixASCIIBuffer.baseAddress!,
suffixASCIIBuffer.count) == (0 as CInt)
}
if selfCore.hasContiguousStorage && suffixCore.hasContiguousStorage {
let lhsStr = _NSContiguousString(selfCore)
let rhsStr = _NSContiguousString(suffixCore)
return lhsStr._unsafeWithNotEscapedSelfPointerPair(rhsStr) {
return _stdlib_NSStringHasSuffixNFDPointer($0, $1)
}
}
return _stdlib_NSStringHasSuffixNFD(
self._bridgeToObjectiveCImpl(), suffix._bridgeToObjectiveCImpl())
}
}
#else
// FIXME: Implement hasPrefix and hasSuffix without objc
// rdar://problem/18878343
#endif
// Conversions to string from other types.
extension String {
/// Creates a string representing the given value in base 10, or some other
/// specified base.
///
/// The following example converts the maximal `Int` value to a string and
/// prints its length:
///
/// let max = String(Int.max)
/// print("\(max) has \(max.count) digits.")
/// // Prints "9223372036854775807 has 19 digits."
///
/// Numerals greater than 9 are represented as Roman letters. These letters
/// start with `"A"` if `uppercase` is `true`; otherwise, with `"a"`.
///
/// let v = 999_999
/// print(String(v, radix: 2))
/// // Prints "11110100001000111111"
///
/// print(String(v, radix: 16))
/// // Prints "f423f"
/// print(String(v, radix: 16, uppercase: true))
/// // Prints "F423F"
///
/// - Parameters:
/// - value: The value to convert to a string.
/// - radix: The base to use for the string representation. `radix` must be
/// at least 2 and at most 36. The default is 10.
/// - uppercase: Pass `true` to use uppercase letters to represent numerals
/// greater than 9, or `false` to use lowercase letters. The default is
/// `false`.
// FIXME(integers): support a more general BinaryInteger protocol
// FIXME(integers): support larger bitwidths than 64
public init<T : FixedWidthInteger>(
_ value: T, radix: Int = 10, uppercase: Bool = false
) {
_precondition(radix > 1, "Radix must be greater than 1")
self = _int64ToString(
Int64(value), radix: Int64(radix), uppercase: uppercase)
}
/// Creates a string representing the given value in base 10, or some other
/// specified base.
///
/// The following example converts the maximal `Int` value to a string and
/// prints its length:
///
/// let max = String(Int.max)
/// print("\(max) has \(max.count) digits.")
/// // Prints "9223372036854775807 has 19 digits."
///
/// Numerals greater than 9 are represented as Roman letters. These letters
/// start with `"A"` if `uppercase` is `true`; otherwise, with `"a"`.
///
/// let v = 999_999
/// print(String(v, radix: 2))
/// // Prints "11110100001000111111"
///
/// print(String(v, radix: 16))
/// // Prints "f423f"
/// print(String(v, radix: 16, uppercase: true))
/// // Prints "F423F"
///
/// - Parameters:
/// - value: The value to convert to a string.
/// - radix: The base to use for the string representation. `radix` must be
/// at least 2 and at most 36. The default is 10.
/// - uppercase: Pass `true` to use uppercase letters to represent numerals
/// greater than 9, or `false` to use lowercase letters. The default is
/// `false`.
// FIXME(integers): tiebreaker between T : FixedWidthInteger and other obsoleted
@available(swift, obsoleted: 4)
public init<T : FixedWidthInteger>(
_ value: T, radix: Int = 10, uppercase: Bool = false
) where T : SignedInteger {
_precondition(radix > 1, "Radix must be greater than 1")
self = _int64ToString(
Int64(value), radix: Int64(radix), uppercase: uppercase)
}
/// Creates a string representing the given value in base 10, or some other
/// specified base.
///
/// The following example converts the maximal `Int` value to a string and
/// prints its length:
///
/// let max = String(Int.max)
/// print("\(max) has \(max.count) digits.")
/// // Prints "9223372036854775807 has 19 digits."
///
/// Numerals greater than 9 are represented as Roman letters. These letters
/// start with `"A"` if `uppercase` is `true`; otherwise, with `"a"`.
///
/// let v: UInt = 999_999
/// print(String(v, radix: 2))
/// // Prints "11110100001000111111"
///
/// print(String(v, radix: 16))
/// // Prints "f423f"
/// print(String(v, radix: 16, uppercase: true))
/// // Prints "F423F"
///
/// - Parameters:
/// - value: The value to convert to a string.
/// - radix: The base to use for the string representation. `radix` must be
/// at least 2 and at most 36. The default is 10.
/// - uppercase: Pass `true` to use uppercase letters to represent numerals
/// greater than 9, or `false` to use lowercase letters. The default is
/// `false`.
// FIXME(integers): support a more general BinaryInteger protocol
public init<T : FixedWidthInteger>(
_ value: T, radix: Int = 10, uppercase: Bool = false
) where T : UnsignedInteger {
_precondition(radix > 1, "Radix must be greater than 1")
self = _uint64ToString(
UInt64(value), radix: Int64(radix), uppercase: uppercase)
}
/// Creates a string representing the given value in base 10, or some other
/// specified base.
///
/// The following example converts the maximal `Int` value to a string and
/// prints its length:
///
/// let max = String(Int.max)
/// print("\(max) has \(max.count) digits.")
/// // Prints "9223372036854775807 has 19 digits."
///
/// Numerals greater than 9 are represented as Roman letters. These letters
/// start with `"A"` if `uppercase` is `true`; otherwise, with `"a"`.
///
/// let v = 999_999
/// print(String(v, radix: 2))
/// // Prints "11110100001000111111"
///
/// print(String(v, radix: 16))
/// // Prints "f423f"
/// print(String(v, radix: 16, uppercase: true))
/// // Prints "F423F"
///
/// - Parameters:
/// - value: The value to convert to a string.
/// - radix: The base to use for the string representation. `radix` must be
/// at least 2 and at most 36. The default is 10.
/// - uppercase: Pass `true` to use uppercase letters to represent numerals
/// greater than 9, or `false` to use lowercase letters. The default is
/// `false`.
@available(swift, obsoleted: 4, message: "Please use the version for FixedWidthInteger instead.")
public init<T : SignedInteger>(
_ value: T, radix: Int = 10, uppercase: Bool = false
) {
_precondition(radix > 1, "Radix must be greater than 1")
self = _int64ToString(
Int64(value), radix: Int64(radix), uppercase: uppercase)
}
/// Creates a string representing the given value in base 10, or some other
/// specified base.
///
/// The following example converts the maximal `Int` value to a string and
/// prints its length:
///
/// let max = String(Int.max)
/// print("\(max) has \(max.count) digits.")
/// // Prints "9223372036854775807 has 19 digits."
///
/// Numerals greater than 9 are represented as Roman letters. These letters
/// start with `"A"` if `uppercase` is `true`; otherwise, with `"a"`.
///
/// let v: UInt = 999_999
/// print(String(v, radix: 2))
/// // Prints "11110100001000111111"
///
/// print(String(v, radix: 16))
/// // Prints "f423f"
/// print(String(v, radix: 16, uppercase: true))
/// // Prints "F423F"
///
/// - Parameters:
/// - value: The value to convert to a string.
/// - radix: The base to use for the string representation. `radix` must be
/// at least 2 and at most 36. The default is 10.
/// - uppercase: Pass `true` to use uppercase letters to represent numerals
/// greater than 9, or `false` to use lowercase letters. The default is
/// `false`.
@available(swift, obsoleted: 4, message: "Please use the version for FixedWidthInteger instead.")
public init<T : UnsignedInteger>(
_ value: T, radix: Int = 10, uppercase: Bool = false
) {
_precondition(radix > 1, "Radix must be greater than 1")
self = _uint64ToString(
UInt64(value), radix: Int64(radix), uppercase: uppercase)
}
}