mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
188 lines
8.0 KiB
Swift
188 lines
8.0 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2018 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// String is a bidirectional collection of `Character`s, aka graphemes
|
|
extension String: BidirectionalCollection {
|
|
/// A type that represents the number of steps between two `String.Index`
|
|
/// values, where one value is reachable from the other.
|
|
///
|
|
/// In Swift, *reachability* refers to the ability to produce one value from
|
|
/// the other through zero or more applications of `index(after:)`.
|
|
public typealias IndexDistance = Int
|
|
|
|
public typealias SubSequence = Substring
|
|
|
|
/// The position of the first character in a nonempty string.
|
|
///
|
|
/// In an empty string, `startIndex` is equal to `endIndex`.
|
|
@inlinable // FIXME(sil-serialize-all)
|
|
public var startIndex: Index { return Index(encodedOffset: 0) }
|
|
|
|
/// A string's "past the end" position---that is, the position one greater
|
|
/// than the last valid subscript argument.
|
|
///
|
|
/// In an empty string, `endIndex` is equal to `startIndex`.
|
|
@inlinable // FIXME(sil-serialize-all)
|
|
public var endIndex: Index { return Index(encodedOffset: _guts.count) }
|
|
|
|
/// The number of characters in a string.
|
|
public var count: Int {
|
|
return distance(from: startIndex, to: endIndex)
|
|
}
|
|
|
|
/// Returns the position immediately after the given index.
|
|
///
|
|
/// - Parameter i: A valid index of the collection. `i` must be less than
|
|
/// `endIndex`.
|
|
/// - Returns: The index value immediately after `i`.
|
|
public func index(after i: Index) -> Index {
|
|
return _visitGuts(_guts, args: i,
|
|
ascii: { ascii, i in ascii.characterIndex(after: i) },
|
|
utf16: { utf16, i in utf16.characterIndex(after: i) },
|
|
opaque: { opaque, i in opaque.characterIndex(after: i) })
|
|
}
|
|
|
|
/// Returns the position immediately before the given index.
|
|
///
|
|
/// - Parameter i: A valid index of the collection. `i` must be greater than
|
|
/// `startIndex`.
|
|
/// - Returns: The index value immediately before `i`.
|
|
public func index(before i: Index) -> Index {
|
|
return _visitGuts(_guts, args: i,
|
|
ascii: { ascii, i in ascii.characterIndex(before: i) },
|
|
utf16: { utf16, i in utf16.characterIndex(before: i) },
|
|
opaque: { opaque, i in opaque.characterIndex(before: i) })
|
|
}
|
|
|
|
/// Returns an index that is the specified distance from the given index.
|
|
///
|
|
/// The following example obtains an index advanced four positions from a
|
|
/// string's starting index and then prints the character at that position.
|
|
///
|
|
/// let s = "Swift"
|
|
/// let i = s.index(s.startIndex, offsetBy: 4)
|
|
/// print(s[i])
|
|
/// // Prints "t"
|
|
///
|
|
/// The value passed as `distance` must not offset `i` beyond the bounds of
|
|
/// the collection.
|
|
///
|
|
/// - Parameters:
|
|
/// - i: A valid index of the collection.
|
|
/// - distance: The distance to offset `i`.
|
|
/// - Returns: An index offset by `distance` from the index `i`. If
|
|
/// `distance` is positive, this is the same value as the result of
|
|
/// `distance` calls to `index(after:)`. If `distance` is negative, this
|
|
/// is the same value as the result of `abs(distance)` calls to
|
|
/// `index(before:)`.
|
|
///
|
|
/// - Complexity: O(*k*), where *k* is the absolute value of `distance`.
|
|
public func index(_ i: Index, offsetBy distance: IndexDistance) -> Index {
|
|
return _visitGuts(_guts, args: (i, distance),
|
|
ascii: { ascii, args in let (i, n) = args
|
|
return ascii.characterIndex(i, offsetBy: n) },
|
|
utf16: { utf16, args in let (i, n) = args
|
|
return utf16.characterIndex(i, offsetBy: n) },
|
|
opaque: { opaque, args in let (i, n) = args
|
|
return opaque.characterIndex(i, offsetBy: n) })
|
|
}
|
|
|
|
/// Returns an index that is the specified distance from the given index,
|
|
/// unless that distance is beyond a given limiting index.
|
|
///
|
|
/// The following example obtains an index advanced four positions from a
|
|
/// string's starting index and then prints the character at that position.
|
|
/// The operation doesn't require going beyond the limiting `s.endIndex`
|
|
/// value, so it succeeds.
|
|
///
|
|
/// let s = "Swift"
|
|
/// if let i = s.index(s.startIndex, offsetBy: 4, limitedBy: s.endIndex) {
|
|
/// print(s[i])
|
|
/// }
|
|
/// // Prints "t"
|
|
///
|
|
/// The next example attempts to retrieve an index six positions from
|
|
/// `s.startIndex` but fails, because that distance is beyond the index
|
|
/// passed as `limit`.
|
|
///
|
|
/// let j = s.index(s.startIndex, offsetBy: 6, limitedBy: s.endIndex)
|
|
/// print(j)
|
|
/// // Prints "nil"
|
|
///
|
|
/// The value passed as `distance` must not offset `i` beyond the bounds of the
|
|
/// collection, unless the index passed as `limit` prevents offsetting
|
|
/// beyond those bounds.
|
|
///
|
|
/// - Parameters:
|
|
/// - i: A valid index of the collection.
|
|
/// - distance: The distance to offset `i`.
|
|
/// - limit: A valid index of the collection to use as a limit. If `distance > 0`,
|
|
/// a limit that is less than `i` has no effect. Likewise, if `distance < 0`, a
|
|
/// limit that is greater than `i` has no effect.
|
|
/// - Returns: An index offset by `distance` from the index `i`, unless that index
|
|
/// would be beyond `limit` in the direction of movement. In that case,
|
|
/// the method returns `nil`.
|
|
///
|
|
/// - Complexity: O(*k*), where *k* is the absolute value of `distance`.
|
|
public func index(
|
|
_ i: Index, offsetBy distance: IndexDistance, limitedBy limit: Index
|
|
) -> Index? {
|
|
return _visitGuts(_guts, args: (i, distance, limit),
|
|
ascii: { ascii, args in let (i, n, limit) = args
|
|
return ascii.characterIndex(i, offsetBy: n, limitedBy: limit) },
|
|
utf16: { utf16, args in let (i, n, limit) = args
|
|
return utf16.characterIndex(i, offsetBy: n, limitedBy: limit) },
|
|
opaque: { opaque, args in let (i, n, limit) = args
|
|
return opaque.characterIndex(i, offsetBy: n, limitedBy: limit) })
|
|
}
|
|
|
|
/// Returns the distance between two indices.
|
|
///
|
|
/// - Parameters:
|
|
/// - start: A valid index of the collection.
|
|
/// - end: Another valid index of the collection. If `end` is equal to
|
|
/// `start`, the result is zero.
|
|
/// - Returns: The distance between `start` and `end`.
|
|
///
|
|
/// - Complexity: O(*k*), where *k* is the resulting distance.
|
|
public func distance(from start: Index, to end: Index) -> IndexDistance {
|
|
return _visitGuts(_guts, args: (start, end),
|
|
ascii: { ascii, args in let (start, end) = args
|
|
return ascii.characterDistance(from: start, to: end) },
|
|
utf16: { utf16, args in let (start, end) = args
|
|
return utf16.characterDistance(from: start, to: end) },
|
|
opaque: { opaque, args in let (start, end) = args
|
|
return opaque.characterDistance(from: start, to: end) })
|
|
}
|
|
|
|
/// Accesses the character at the given position.
|
|
///
|
|
/// You can use the same indices for subscripting a string and its substring.
|
|
/// For example, this code finds the first letter after the first space:
|
|
///
|
|
/// let str = "Greetings, friend! How are you?"
|
|
/// let firstSpace = str.firstIndex(of: " ") ?? str.endIndex
|
|
/// let substr = str[firstSpace...]
|
|
/// if let nextCapital = substr.firstIndex(where: { $0 >= "A" && $0 <= "Z" }) {
|
|
/// print("Capital after a space: \(str[nextCapital])")
|
|
/// }
|
|
/// // Prints "Capital after a space: H"
|
|
///
|
|
/// - Parameter i: A valid index of the string. `i` must be less than the
|
|
/// string's end index.
|
|
public subscript(i: Index) -> Character {
|
|
return _visitGuts(_guts, args: i,
|
|
ascii: { ascii, i in return ascii.character(at: i) },
|
|
utf16: { utf16, i in return utf16.character(at: i) },
|
|
opaque: { opaque, i in return opaque.character(at: i) })
|
|
}
|
|
} |