| //===----------------------------------------------------------------------===// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| extension String.Index { |
| /// Creates an index in the given string that corresponds exactly to the |
| /// specified `UnicodeScalarView` position. |
| /// |
| /// The following example converts the position of the Unicode scalar `"e"` |
| /// into its corresponding position in the string. The character at that |
| /// position is the composed `"é"` character. |
| /// |
| /// let cafe = "Cafe\u{0301}" |
| /// print(cafe) |
| /// // Prints "Café" |
| /// |
| /// let scalarsIndex = cafe.unicodeScalars.index(of: "e")! |
| /// let stringIndex = String.Index(scalarsIndex, within: cafe)! |
| /// |
| /// print(cafe[...stringIndex]) |
| /// // Prints "Café" |
| /// |
| /// If the position passed in `unicodeScalarIndex` doesn't have an exact |
| /// corresponding position in `other`, the result of the initializer is |
| /// `nil`. For example, an attempt to convert the position of the combining |
| /// acute accent (`"\u{0301}"`) fails. Combining Unicode scalars do not have |
| /// their own position in a string. |
| /// |
| /// let nextIndex = String.Index(cafe.unicodeScalars.index(after: scalarsIndex), |
| /// within: cafe) |
| /// print(nextIndex) |
| /// // Prints "nil" |
| /// |
| /// - Parameters: |
| /// - unicodeScalarIndex: A position in the `unicodeScalars` view of the |
| /// `other` parameter. |
| /// - other: The string referenced by both `unicodeScalarIndex` and the |
| /// resulting index. |
| public init?( |
| _ unicodeScalarIndex: String.UnicodeScalarIndex, |
| within other: String |
| ) { |
| if !other.unicodeScalars._isOnGraphemeClusterBoundary(unicodeScalarIndex) { |
| return nil |
| } |
| self.init(_base: unicodeScalarIndex, in: other.characters) |
| } |
| |
| /// Creates an index in the given string that corresponds exactly to the |
| /// specified `UTF16View` position. |
| /// |
| /// The following example finds the position of a space in a string's `utf16` |
| /// view and then converts that position to an index in the string. The |
| /// value `32` is the UTF-16 encoded value of a space character. |
| /// |
| /// let cafe = "Café 🍵" |
| /// |
| /// let utf16Index = cafe.utf16.index(of: 32)! |
| /// let stringIndex = String.Index(utf16Index, within: cafe)! |
| /// |
| /// print(cafe[..<stringIndex]) |
| /// // Prints "Café" |
| /// |
| /// If the position passed in `utf16Index` doesn't have an exact |
| /// corresponding position in `other`, the result of the initializer is |
| /// `nil`. For example, an attempt to convert the position of the trailing |
| /// surrogate of a UTF-16 surrogate pair fails. |
| /// |
| /// The next example attempts to convert the indices of the two UTF-16 code |
| /// points that represent the teacup emoji (`"🍵"`). The index of the lead |
| /// surrogate is successfully converted to a position in `other`, but the |
| /// index of the trailing surrogate is not. |
| /// |
| /// let emojiHigh = cafe.utf16.index(after: utf16Index) |
| /// print(String.Index(emojiHigh, within: cafe)) |
| /// // Prints "Optional(String.Index(...))" |
| /// |
| /// let emojiLow = cafe.utf16.index(after: emojiHigh) |
| /// print(String.Index(emojiLow, within: cafe)) |
| /// // Prints "nil" |
| /// |
| /// - Parameters: |
| /// - utf16Index: A position in the `utf16` view of the `other` parameter. |
| /// - other: The string referenced by both `utf16Index` and the resulting |
| /// index. |
| public init?( |
| _ utf16Index: String.UTF16Index, |
| within other: String |
| ) { |
| if let me = utf16Index.samePosition( |
| in: other.unicodeScalars |
| )?.samePosition(in: other) { |
| self = me |
| } |
| else { |
| return nil |
| } |
| } |
| |
| /// Creates an index in the given string that corresponds exactly to the |
| /// specified `UTF8View` position. |
| /// |
| /// If the position passed in `utf8Index` doesn't have an exact corresponding |
| /// position in `other`, the result of the initializer is `nil`. For |
| /// example, an attempt to convert the position of a UTF-8 continuation byte |
| /// returns `nil`. |
| /// |
| /// - Parameters: |
| /// - utf8Index: A position in the `utf8` view of the `other` parameter. |
| /// - other: The string referenced by both `utf8Index` and the resulting |
| /// index. |
| public init?( |
| _ utf8Index: String.UTF8Index, |
| within other: String |
| ) { |
| if let me = utf8Index.samePosition( |
| in: other.unicodeScalars |
| )?.samePosition(in: other) { |
| self = me |
| } |
| else { |
| return nil |
| } |
| } |
| |
| /// Returns the position in the given UTF-8 view that corresponds exactly to |
| /// this index. |
| /// |
| /// The index must be a valid index of `String(utf8)`. |
| /// |
| /// This example first finds the position of the character `"é"` and then uses |
| /// this method find the same position in the string's `utf8` view. |
| /// |
| /// let cafe = "Café" |
| /// if let i = cafe.index(of: "é") { |
| /// let j = i.samePosition(in: cafe.utf8) |
| /// print(Array(cafe.utf8[j...])) |
| /// } |
| /// // Prints "[195, 169]" |
| /// |
| /// - Parameter utf8: The view to use for the index conversion. |
| /// - Returns: The position in `utf8` that corresponds exactly to this index. |
| public func samePosition( |
| in utf8: String.UTF8View |
| ) -> String.UTF8View.Index { |
| return String.UTF8View.Index(self, within: utf8) |
| } |
| |
| /// Returns the position in the given UTF-16 view that corresponds exactly to |
| /// this index. |
| /// |
| /// The index must be a valid index of `String(utf16)`. |
| /// |
| /// This example first finds the position of the character `"é"` and then uses |
| /// this method find the same position in the string's `utf16` view. |
| /// |
| /// let cafe = "Café" |
| /// if let i = cafe.index(of: "é") { |
| /// let j = i.samePosition(in: cafe.utf16) |
| /// print(cafe.utf16[j]) |
| /// } |
| /// // Prints "233" |
| /// |
| /// - Parameter utf16: The view to use for the index conversion. |
| /// - Returns: The position in `utf16` that corresponds exactly to this index. |
| public func samePosition( |
| in utf16: String.UTF16View |
| ) -> String.UTF16View.Index { |
| return String.UTF16View.Index(self, within: utf16) |
| } |
| |
| /// Returns the position in the given view of Unicode scalars that |
| /// corresponds exactly to this index. |
| /// |
| /// The index must be a valid index of `String(unicodeScalars)`. |
| /// |
| /// This example first finds the position of the character `"é"` and then uses |
| /// this method find the same position in the string's `unicodeScalars` |
| /// view. |
| /// |
| /// let cafe = "Café" |
| /// if let i = cafe.index(of: "é") { |
| /// let j = i.samePosition(in: cafe.unicodeScalars) |
| /// print(cafe.unicodeScalars[j]) |
| /// } |
| /// // Prints "é" |
| /// |
| /// - Parameter unicodeScalars: The view to use for the index conversion. |
| /// - Returns: The position in `unicodeScalars` that corresponds exactly to |
| /// this index. |
| public func samePosition( |
| in unicodeScalars: String.UnicodeScalarView |
| ) -> String.UnicodeScalarView.Index { |
| return String.UnicodeScalarView.Index(self, within: unicodeScalars) |
| } |
| } |
| |