[stdlib] Document String index conversions

Also rename some parameters to make the documentation read well.

Fixes rdar://18018911

Swift SVN r24512
This commit is contained in:
Dave Abrahams
2015-01-19 18:36:29 +00:00
parent 7446cee72b
commit 2cbdffb09f
4 changed files with 182 additions and 68 deletions

View File

@@ -938,21 +938,31 @@ extension String {
// Index conversions // Index conversions
extension String.Index { extension String.Index {
/// Construct the position in `characters` that corresponds exactly to
/// `unicodeScalarIndex`. If no such position exists, the result is `nil`.
///
/// Requires: `unicodeScalarIndex` is an element of
/// `indices(characters.unicodeScalars)`.
public init?( public init?(
_ sourceIndex: String.UnicodeScalarIndex, _ unicodeScalarIndex: String.UnicodeScalarIndex,
within characters: String within characters: String
) { ) {
if !sourceIndex._isOnGraphemeClusterBoundary { if !unicodeScalarIndex._isOnGraphemeClusterBoundary {
return nil return nil
} }
self.init(_base: sourceIndex) self.init(_base: unicodeScalarIndex)
} }
/// Construct the position in `characters` that corresponds exactly to
/// `utf16Index`. If no such position exists, the result is `nil`.
///
/// Requires: `utf16Index` is an element of
/// `indices(characters.utf16)`.
public init?( public init?(
_ sourceIndex: String.UTF16Index, _ utf16Index: String.UTF16Index,
within characters: String within characters: String
) { ) {
if let me = sourceIndex.samePositionIn( if let me = utf16Index.samePositionIn(
characters.unicodeScalars characters.unicodeScalars
)?.samePositionIn(characters) { )?.samePositionIn(characters) {
self = me self = me
@@ -962,11 +972,16 @@ extension String.Index {
} }
} }
/// Construct the position in `characters` that corresponds exactly to
/// `utf8Index`. If no such position exists, the result is `nil`.
///
/// Requires: `utf8Index` is an element of
/// `indices(characters.utf8)`.
public init?( public init?(
_ sourceIndex: String.UTF8Index, _ utf8Index: String.UTF8Index,
within characters: String within characters: String
) { ) {
if let me = sourceIndex.samePositionIn( if let me = utf8Index.samePositionIn(
characters.unicodeScalars characters.unicodeScalars
)?.samePositionIn(characters) { )?.samePositionIn(characters) {
self = me self = me
@@ -975,20 +990,34 @@ extension String.Index {
return nil return nil
} }
} }
/// Return the position in `utf8` that corresponds exactly
/// to `self`.
///
/// Requires: `self` is an element of `indices(String(utf8))`.
public func samePositionIn( public func samePositionIn(
otherView: String.UTF8View utf8: String.UTF8View
) -> String.UTF8View.Index { ) -> String.UTF8View.Index {
return String.UTF8View.Index(self, within: otherView) return String.UTF8View.Index(self, within: utf8)
} }
/// Return the position in `utf16` that corresponds exactly
/// to `self`.
///
/// Requires: `self` is an element of `indices(String(utf16))`.
public func samePositionIn( public func samePositionIn(
otherView: String.UTF16View utf16: String.UTF16View
) -> String.UTF16View.Index { ) -> String.UTF16View.Index {
return String.UTF16View.Index(self, within: otherView) return String.UTF16View.Index(self, within: utf16)
} }
/// Return the position in `unicodeScalars` that corresponds exactly
/// to `self`.
///
/// Requires: `self` is an element of `indices(String(unicodeScalars))`.
public func samePositionIn( public func samePositionIn(
otherView: String.UnicodeScalarView unicodeScalars: String.UnicodeScalarView
) -> String.UnicodeScalarView.Index { ) -> String.UnicodeScalarView.Index {
return String.UnicodeScalarView.Index(self, within: otherView) return String.UnicodeScalarView.Index(self, within: unicodeScalars)
} }
} }

View File

@@ -232,43 +232,73 @@ public func ~> (
// Index conversions // Index conversions
extension String.UTF16View.Index { extension String.UTF16View.Index {
/// Construct the position in `utf16` that corresponds exactly to
/// `utf8Index`. If no such position exists, the result is `nil`.
///
/// Requires: `utf8Index` is an element of
/// `indices(String(utf16).utf8)`.
public init?( public init?(
_ sourceIndex: String.UTF8Index, within utf16: String.UTF16View _ utf8Index: String.UTF8Index, within utf16: String.UTF16View
) { ) {
let core = utf16._core let core = utf16._core
_precondition( _precondition(
sourceIndex._coreIndex >= 0 && sourceIndex._coreIndex <= core.endIndex, utf8Index._coreIndex >= 0 && utf8Index._coreIndex <= core.endIndex,
"Invalid String.UTF8Index for this UTF-16 view") "Invalid String.UTF8Index for this UTF-16 view")
// Detect positions that have no corresponding index. // Detect positions that have no corresponding index.
if !sourceIndex._isOnUnicodeScalarBoundary { if !utf8Index._isOnUnicodeScalarBoundary {
return nil return nil
} }
self.init(sourceIndex._coreIndex) self.init(utf8Index._coreIndex)
} }
/// Construct the position in `utf16` that corresponds exactly to
/// `unicodeScalarIndex`.
///
/// Requires: `unicodeScalarIndex` is an element of
/// `indices(String(utf16).unicodeScalars)`.
public init( public init(
_ sourceIndex: String.UnicodeScalarIndex, within utf16: String.UTF16View) { _ unicodeScalarIndex: String.UnicodeScalarIndex,
self.init(sourceIndex._position) within utf16: String.UTF16View) {
self.init(unicodeScalarIndex._position)
} }
public init(_ sourceIndex: String.Index, within utf16: String.UTF16View) { /// Construct the position in `utf16` that corresponds exactly to
self.init(sourceIndex._utf16Index) /// `characterIndex`.
///
/// Requires: `characterIndex` is an element of
/// `indices(String(utf16))`.
public init(_ characterIndex: String.Index, within utf16: String.UTF16View) {
self.init(characterIndex._utf16Index)
} }
/// Return the position in `utf8` that corresponds exactly
/// to `self`, or if no such position exists, `nil`.
///
/// Requires: `self` is an element of
/// `indices(String(utf8).utf16)`.
public func samePositionIn( public func samePositionIn(
otherView: String.UTF8View utf8: String.UTF8View
) -> String.UTF8View.Index? { ) -> String.UTF8View.Index? {
return String.UTF8View.Index(self, within: otherView) return String.UTF8View.Index(self, within: utf8)
} }
/// Return the position in `unicodeScalars` that corresponds exactly
/// to `self`, or if no such position exists, `nil`.
///
/// Requires: `self` is an element of
/// `indices(String(unicodeScalars).utf16)`.
public func samePositionIn( public func samePositionIn(
otherView: String.UnicodeScalarView unicodeScalars: String.UnicodeScalarView
) -> String.UnicodeScalarIndex? { ) -> String.UnicodeScalarIndex? {
return String.UnicodeScalarIndex(self, within: otherView) return String.UnicodeScalarIndex(self, within: unicodeScalars)
} }
/// Return the position in `characters` that corresponds exactly
/// to `self`, or if no such position exists, `nil`.
///
/// Requires: `self` is an element of `indices(characters.utf16)`.
public func samePositionIn( public func samePositionIn(
characters: String characters: String
) -> String.Index? { ) -> String.Index? {

View File

@@ -309,58 +309,86 @@ func == (lhs: String.UTF8View.Index, rhs: String.UTF8View.Index) -> Bool {
while true while true
} }
extension String.UTF8Index { // Index conversions
extension String.UTF8View.Index {
internal init(_ core: _StringCore, _utf16Offset: Int) { internal init(_ core: _StringCore, _utf16Offset: Int) {
let (_, buffer) = core._encodeSomeUTF8(_utf16Offset) let (_, buffer) = core._encodeSomeUTF8(_utf16Offset)
self.init(core, _utf16Offset, buffer) self.init(core, _utf16Offset, buffer)
} }
public init?(_ sourceIndex: String.UTF16Index, within utf8: String.UTF8View) { /// Construct the position in `utf8` that corresponds exactly to
let sourceView = String.UTF16View(utf8._core) /// `utf16Index`. If no such position exists, the result is `nil`.
///
/// Requires: `utf8Index` is an element of
/// `indices(String(utf16).utf8)`.
public init?(_ utf16Index: String.UTF16Index, within utf8: String.UTF8View) {
let utf16 = String.UTF16View(utf8._core)
if sourceIndex != sourceView.startIndex if utf16Index != utf16.startIndex
&& sourceIndex != sourceView.endIndex { && utf16Index != utf16.endIndex {
_precondition( _precondition(
sourceIndex >= sourceView.startIndex utf16Index >= utf16.startIndex
&& sourceIndex <= sourceView.endIndex, && utf16Index <= utf16.endIndex,
"Invalid String.UTF16Index for this UTF-8 view") "Invalid String.UTF16Index for this UTF-8 view")
// Detect positions that have no corresponding index. Note that // Detect positions that have no corresponding index. Note that
// we have to check before and after, because an unpaired // we have to check before and after, because an unpaired
// surrogate will be decoded as a single replacement character, // surrogate will be decoded as a single replacement character,
// thus making the corresponding position valid in UTF8. // thus making the corresponding position valid in UTF8.
if UTF16.isTrailSurrogate(sourceView[sourceIndex]) if UTF16.isTrailSurrogate(utf16[utf16Index])
&& UTF16.isLeadSurrogate(sourceView[sourceIndex.predecessor()]) { && UTF16.isLeadSurrogate(utf16[utf16Index.predecessor()]) {
return nil return nil
} }
} }
self.init(utf8._core, _utf16Offset: sourceIndex._offset) self.init(utf8._core, _utf16Offset: utf16Index._offset)
} }
/// Construct the position in `utf8` that corresponds exactly to
/// `unicodeScalarIndex`.
///
/// Requires: `unicodeScalarIndex` is an element of
/// `indices(String(utf8).unicodeScalars)`.
public init( public init(
_ sourceIndex: String.UnicodeScalarIndex, within utf8: String.UTF8View) { _ unicodeScalarIndex: String.UnicodeScalarIndex,
self.init(utf8._core, _utf16Offset: sourceIndex._position) within utf8: String.UTF8View
) {
self.init(utf8._core, _utf16Offset: unicodeScalarIndex._position)
} }
public init(_ sourceIndex: String.Index, within utf8: String.UTF8View) { /// Construct the position in `utf8` that corresponds exactly to
self.init(utf8._core, _utf16Offset: sourceIndex._base._position) /// `characterIndex`.
///
/// Requires: `characterIndex` is an element of
/// `indices(String(utf8))`.
public init(_ characterIndex: String.Index, within utf8: String.UTF8View) {
self.init(utf8._core, _utf16Offset: characterIndex._base._position)
} }
}
// Index conversions /// Return the position in `utf16` that corresponds exactly
extension String.UTF8View.Index { /// to `self`, or if no such position exists, `nil`.
///
/// Requires: `self` is an element of `indices(String(utf16).utf8)`.
public func samePositionIn( public func samePositionIn(
otherView: String.UTF16View utf16: String.UTF16View
) -> String.UTF16View.Index? { ) -> String.UTF16View.Index? {
return String.UTF16View.Index(self, within: otherView) return String.UTF16View.Index(self, within: utf16)
} }
/// Return the position in `unicodeScalars` that corresponds exactly
/// to `self`, or if no such position exists, `nil`.
///
/// Requires: `self` is an element of
/// `indices(String(unicodeScalars).utf8)`.
public func samePositionIn( public func samePositionIn(
otherView: String.UnicodeScalarView unicodeScalars: String.UnicodeScalarView
) -> String.UnicodeScalarIndex? { ) -> String.UnicodeScalarIndex? {
return String.UnicodeScalarIndex(self, within: otherView) return String.UnicodeScalarIndex(self, within: unicodeScalars)
} }
/// Return the position in `characters` that corresponds exactly
/// to `self`, or if no such position exists, `nil`.
///
/// Requires: `self` is an element of `indices(characters.utf8)`.
public func samePositionIn( public func samePositionIn(
characters: String characters: String
) -> String.Index? { ) -> String.Index? {

View File

@@ -349,65 +349,92 @@ extension String.UnicodeScalarView : RangeReplaceableCollectionType {
// Index conversions // Index conversions
extension String.UnicodeScalarIndex { extension String.UnicodeScalarIndex {
/// Construct the position in `unicodeScalars` that corresponds exactly to
/// `utf16Index`. If no such position exists, the result is `nil`.
///
/// Requires: `utf16Index` is an element of
/// `indices(String(unicodeScalars).utf16)`.
public init?( public init?(
_ sourceIndex: String.UTF16Index, _ utf16Index: String.UTF16Index,
within unicodeScalars: String.UnicodeScalarView within unicodeScalars: String.UnicodeScalarView
) { ) {
let sourceView = String.UTF16View(unicodeScalars._core) let utf16 = String.UTF16View(unicodeScalars._core)
if sourceIndex != sourceView.startIndex if utf16Index != utf16.startIndex
&& sourceIndex != sourceView.endIndex { && utf16Index != utf16.endIndex {
_precondition( _precondition(
sourceIndex >= sourceView.startIndex utf16Index >= utf16.startIndex
&& sourceIndex <= sourceView.endIndex, && utf16Index <= utf16.endIndex,
"Invalid String.UTF16Index for this UnicodeScalar view") "Invalid String.UTF16Index for this UnicodeScalar view")
// Detect positions that have no corresponding index. Note that // Detect positions that have no corresponding index. Note that
// we have to check before and after, because an unpaired // we have to check before and after, because an unpaired
// surrogate will be decoded as a single replacement character, // surrogate will be decoded as a single replacement character,
// thus making the corresponding position valid. // thus making the corresponding position valid.
if UTF16.isTrailSurrogate(sourceView[sourceIndex]) if UTF16.isTrailSurrogate(utf16[utf16Index])
&& UTF16.isLeadSurrogate(sourceView[sourceIndex.predecessor()]) { && UTF16.isLeadSurrogate(utf16[utf16Index.predecessor()]) {
return nil return nil
} }
} }
self.init(sourceIndex._offset, unicodeScalars._core) self.init(utf16Index._offset, unicodeScalars._core)
} }
/// Construct the position in `unicodeScalars` that corresponds exactly to
/// `utf8Index`. If no such position exists, the result is `nil`.
///
/// Requires: `utf8Index` is an element of
/// `indices(String(unicodeScalars).utf8)`.
public init?( public init?(
_ sourceIndex: String.UTF8Index, _ utf8Index: String.UTF8Index,
within unicodeScalars: String.UnicodeScalarView within unicodeScalars: String.UnicodeScalarView
) { ) {
let core = unicodeScalars._core let core = unicodeScalars._core
_precondition( _precondition(
sourceIndex._coreIndex >= 0 && sourceIndex._coreIndex <= core.endIndex, utf8Index._coreIndex >= 0 && utf8Index._coreIndex <= core.endIndex,
"Invalid String.UTF8Index for this UnicodeScalar view") "Invalid String.UTF8Index for this UnicodeScalar view")
// Detect positions that have no corresponding index. // Detect positions that have no corresponding index.
if !sourceIndex._isOnUnicodeScalarBoundary { if !utf8Index._isOnUnicodeScalarBoundary {
return nil return nil
} }
self.init(sourceIndex._coreIndex, core) self.init(utf8Index._coreIndex, core)
} }
/// Construct the position in `unicodeScalars` that corresponds
/// exactly to `characterIndex`.
///
/// Requires: `characterIndex` is an element of
/// `indices(String(unicodeScalars))`.
public init( public init(
_ sourceIndex: String.Index, _ characterIndex: String.Index,
within unicodeScalars: String.UnicodeScalarView within unicodeScalars: String.UnicodeScalarView
) { ) {
self.init(sourceIndex._base._position, unicodeScalars._core) self.init(characterIndex._base._position, unicodeScalars._core)
} }
public func samePositionIn( /// Return the position in `utf8` that corresponds exactly
otherView: String.UTF8View /// to `self`.
) -> String.UTF8View.Index { ///
return String.UTF8View.Index(self, within: otherView) /// Requires: `self` is an element of `indices(String(utf8))`.
public func samePositionIn(utf8: String.UTF8View) -> String.UTF8View.Index {
return String.UTF8View.Index(self, within: utf8)
} }
/// Return the position in `utf16` that corresponds exactly
/// to `self`.
///
/// Requires: `self` is an element of `indices(String(utf16))`.
public func samePositionIn( public func samePositionIn(
otherView: String.UTF16View utf16: String.UTF16View
) -> String.UTF16View.Index { ) -> String.UTF16View.Index {
return String.UTF16View.Index(self, within: otherView) return String.UTF16View.Index(self, within: utf16)
} }
/// Return the position in `characters` that corresponds exactly
/// to `self`, or if no such position exists, `nil`.
///
/// Requires: `self` is an element of `indices(characters.unicodeScalars)`.
public func samePositionIn(characters: String) -> String.Index? { public func samePositionIn(characters: String) -> String.Index? {
return String.Index(self, within: characters) return String.Index(self, within: characters)
} }