mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[stdlib] Failable String inits from UTF8/16 views
String.UTF8View and String.UTF16View may be slices that don't both start and end on Unicode scalar boundaries, in which case conversion to a String must fail. Swift SVN r24669
This commit is contained in:
@@ -165,9 +165,18 @@ extension String {
|
||||
}
|
||||
|
||||
/// Construct the `String` corresponding to the given sequence of
|
||||
/// UTF16 code units.
|
||||
public init(_ utf16: UTF16View) {
|
||||
self.init(utf16._core[utf16._offset..<utf16._offset+utf16._length])
|
||||
/// UTF-16 code units. If `utf16` contains unpaired surrogates, the
|
||||
/// result is `nil`.
|
||||
public init?(_ utf16: UTF16View) {
|
||||
let wholeString = String(utf16._core)
|
||||
|
||||
if let start = utf16.startIndex.samePositionIn(wholeString) {
|
||||
if let end = utf16.endIndex.samePositionIn(wholeString) {
|
||||
self = wholeString[start..<end]
|
||||
return
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/// The index type for subscripting a `String`\ 's `utf16` view.
|
||||
@@ -242,7 +251,7 @@ extension String.UTF16View.Index {
|
||||
/// `utf8Index`. If no such position exists, the result is `nil`.
|
||||
///
|
||||
/// Requires: `utf8Index` is an element of
|
||||
/// `indices(String(utf16).utf8)`.
|
||||
/// `indices(String(utf16)!.utf8)`.
|
||||
public init?(
|
||||
_ utf8Index: String.UTF8Index, within utf16: String.UTF16View
|
||||
) {
|
||||
@@ -263,7 +272,7 @@ extension String.UTF16View.Index {
|
||||
/// `unicodeScalarIndex`.
|
||||
///
|
||||
/// Requires: `unicodeScalarIndex` is an element of
|
||||
/// `indices(String(utf16).unicodeScalars)`.
|
||||
/// `indices(String(utf16)!.unicodeScalars)`.
|
||||
public init(
|
||||
_ unicodeScalarIndex: String.UnicodeScalarIndex,
|
||||
within utf16: String.UTF16View) {
|
||||
@@ -274,7 +283,7 @@ extension String.UTF16View.Index {
|
||||
/// `characterIndex`.
|
||||
///
|
||||
/// Requires: `characterIndex` is an element of
|
||||
/// `indices(String(utf16))`.
|
||||
/// `indices(String(utf16)!)`.
|
||||
public init(_ characterIndex: String.Index, within utf16: String.UTF16View) {
|
||||
_offset = characterIndex._utf16Index
|
||||
}
|
||||
@@ -283,7 +292,7 @@ extension String.UTF16View.Index {
|
||||
/// to `self`, or if no such position exists, `nil`.
|
||||
///
|
||||
/// Requires: `self` is an element of
|
||||
/// `indices(String(utf8).utf16)`.
|
||||
/// `indices(String(utf8)!.utf16)`.
|
||||
public func samePositionIn(
|
||||
utf8: String.UTF8View
|
||||
) -> String.UTF8View.Index? {
|
||||
|
||||
@@ -273,9 +273,18 @@ extension String {
|
||||
}
|
||||
|
||||
/// Construct the `String` corresponding to the given sequence of
|
||||
/// UTF8 code units.
|
||||
public init(_ utf8: UTF8View) {
|
||||
self.init(utf8._core)
|
||||
/// UTF-8 code units. If `utf8` contains unpaired surrogates, the
|
||||
/// result is `nil`.
|
||||
public init?(_ utf8: UTF8View) {
|
||||
let wholeString = String(utf8._core)
|
||||
|
||||
if let start = utf8.startIndex.samePositionIn(wholeString) {
|
||||
if let end = utf8.endIndex.samePositionIn(wholeString) {
|
||||
self = wholeString[start..<end]
|
||||
return
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/// The index type for subscripting a `String`\ 's `.utf8` view.
|
||||
@@ -327,7 +336,7 @@ extension String.UTF8View.Index {
|
||||
/// `utf16Index`. If no such position exists, the result is `nil`.
|
||||
///
|
||||
/// Requires: `utf8Index` is an element of
|
||||
/// `indices(String(utf16).utf8)`.
|
||||
/// `indices(String(utf16)!.utf8)`.
|
||||
public init?(_ utf16Index: String.UTF16Index, within utf8: String.UTF8View) {
|
||||
let utf16 = String.UTF16View(utf8._core)
|
||||
|
||||
@@ -354,7 +363,7 @@ extension String.UTF8View.Index {
|
||||
/// `unicodeScalarIndex`.
|
||||
///
|
||||
/// Requires: `unicodeScalarIndex` is an element of
|
||||
/// `indices(String(utf8).unicodeScalars)`.
|
||||
/// `indices(String(utf8)!.unicodeScalars)`.
|
||||
public init(
|
||||
_ unicodeScalarIndex: String.UnicodeScalarIndex,
|
||||
within utf8: String.UTF8View
|
||||
@@ -366,7 +375,7 @@ extension String.UTF8View.Index {
|
||||
/// `characterIndex`.
|
||||
///
|
||||
/// Requires: `characterIndex` is an element of
|
||||
/// `indices(String(utf8))`.
|
||||
/// `indices(String(utf8)!)`.
|
||||
public init(_ characterIndex: String.Index, within utf8: String.UTF8View) {
|
||||
self.init(utf8._core, _utf16Offset: characterIndex._base._position)
|
||||
}
|
||||
@@ -374,7 +383,7 @@ extension String.UTF8View.Index {
|
||||
/// Return the position in `utf16` that corresponds exactly
|
||||
/// to `self`, or if no such position exists, `nil`.
|
||||
///
|
||||
/// Requires: `self` is an element of `indices(String(utf16).utf8)`.
|
||||
/// Requires: `self` is an element of `indices(String(utf16)!.utf8)`.
|
||||
public func samePositionIn(
|
||||
utf16: String.UTF16View
|
||||
) -> String.UTF16View.Index? {
|
||||
|
||||
@@ -415,7 +415,7 @@ extension String.UnicodeScalarIndex {
|
||||
/// Return the position in `utf8` that corresponds exactly
|
||||
/// to `self`.
|
||||
///
|
||||
/// Requires: `self` is an element of `indices(String(utf8))`.
|
||||
/// 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)
|
||||
}
|
||||
@@ -423,7 +423,7 @@ extension String.UnicodeScalarIndex {
|
||||
/// Return the position in `utf16` that corresponds exactly
|
||||
/// to `self`.
|
||||
///
|
||||
/// Requires: `self` is an element of `indices(String(utf16))`.
|
||||
/// Requires: `self` is an element of `indices(String(utf16)!)`.
|
||||
public func samePositionIn(
|
||||
utf16: String.UTF16View
|
||||
) -> String.UTF16View.Index {
|
||||
|
||||
@@ -697,25 +697,35 @@ tests.test("UTF8 indexes") {
|
||||
tests.test("UTF16->String") {
|
||||
let s = summer + winter + winter + summer
|
||||
let v = s.utf16
|
||||
for i in indices(s) {
|
||||
for j in i..<s.endIndex {
|
||||
expectEqual(
|
||||
s[i..<j],
|
||||
String(v[i.samePositionIn(v)..<j.samePositionIn(v)])
|
||||
)
|
||||
for i in indices(v) {
|
||||
for j in i..<v.endIndex {
|
||||
if let si = i.samePositionIn(s) {
|
||||
if let sj = j.samePositionIn(s) {
|
||||
expectEqual(i, i1)
|
||||
expectEqual(j, j1)
|
||||
expectEqual(s[si..<sj], String(v[i..<j]))
|
||||
continue
|
||||
}
|
||||
}
|
||||
expectEmpty(String(v[i..<j]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tests.test("UTF8->String") {
|
||||
let s = summer + winter + winter + summer
|
||||
let v = s.utf16
|
||||
for i in indices(s) {
|
||||
for j in i..<s.endIndex {
|
||||
expectEqual(
|
||||
s[i..<j],
|
||||
String(v[i.samePositionIn(v)..<j.samePositionIn(v)])
|
||||
)
|
||||
let v = s.utf8
|
||||
for i in indices(v) {
|
||||
for j in i..<v.endIndex {
|
||||
if let si = i.samePositionIn(s) {
|
||||
if let sj = j.samePositionIn(s) {
|
||||
expectEqual(i, i1)
|
||||
expectEqual(j, j1)
|
||||
expectEqual(s[si..<sj], String(v[i..<j]))
|
||||
continue
|
||||
}
|
||||
}
|
||||
expectEmpty(String(v[i..<j]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user