Skip to content

Commit 0280837

Browse files
committed
[stdlib] Fixed bugs with string views
Fixes rdar://problem/18435682 Fixes rdar://problem/19238102 Swift SVN r24117
1 parent 1486238 commit 0280837

File tree

5 files changed

+94
-10
lines changed

5 files changed

+94
-10
lines changed

stdlib/core/StringUTF16.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
extension String {
1414
/// A collection of UTF-16 code units that encodes a `String` value.
15-
public struct UTF16View : Sliceable, Reflectable {
15+
public struct UTF16View : Sliceable, Reflectable, Printable, DebugPrintable {
1616
public struct Index {
1717
// Foundation needs access to these fields so it can expose
1818
// random access
@@ -144,6 +144,16 @@ extension String {
144144
return _UTF16ViewMirror(self)
145145
}
146146

147+
public var description: String {
148+
let start = _toInternalIndex(0)
149+
let end = _toInternalIndex(_length)
150+
return String(_core[start..<end])
151+
}
152+
153+
public var debugDescription: String {
154+
return "StringUTF16(\(self.description.debugDescription))"
155+
}
156+
147157
var _offset: Int
148158
var _length: Int
149159
let _core: _StringCore

stdlib/core/StringUTF8.swift

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,28 @@ extension _StringCore {
8383

8484
extension String {
8585
/// A collection of UTF-8 code units that encodes a `String` value.
86-
public struct UTF8View : CollectionType, Reflectable {
86+
public struct UTF8View : CollectionType, Reflectable, Printable,
87+
DebugPrintable {
8788
internal let _core: _StringCore
89+
// These are optional as a work around for a compiler segfault.
90+
internal let _startIndex: Index!
91+
internal let _endIndex: Index!
8892

8993
init(_ _core: _StringCore) {
9094
self._core = _core
95+
self._endIndex = Index(_core, _core.endIndex, Index._emptyBuffer)
96+
if _fastPath(_core.count != 0) {
97+
let (_, buffer) = _core._encodeSomeUTF8(0)
98+
self._startIndex = Index(_core, 0, buffer)
99+
} else {
100+
self._startIndex = self._endIndex
101+
}
102+
}
103+
104+
init(_ _core: _StringCore, _ s: Index, _ e: Index) {
105+
self._core = _core
106+
self._startIndex = s
107+
self._endIndex = e
91108
}
92109

93110
/// A position in a `String.UTF8View`
@@ -179,11 +196,7 @@ extension String {
179196
/// The position of the first code unit if the `String` is
180197
/// non-empty; identical to `endIndex` otherwise.
181198
public var startIndex: Index {
182-
if _fastPath(_core.count != 0) {
183-
let (_, buffer) = _core._encodeSomeUTF8(0)
184-
return Index(_core, 0, buffer)
185-
}
186-
return endIndex
199+
return self._startIndex
187200
}
188201

189202
/// The "past the end" position.
@@ -192,7 +205,7 @@ extension String {
192205
/// reachable from `startIndex` by zero or more applications of
193206
/// `successor()`.
194207
public var endIndex: Index {
195-
return Index(_core, _core.endIndex, Index._emptyBuffer)
208+
return self._endIndex
196209
}
197210

198211
/// Access the element at `position`.
@@ -205,6 +218,15 @@ extension String {
205218
return result
206219
}
207220

221+
/// Access the elements delimited by the given half-open range of
222+
/// indices.
223+
///
224+
/// Complexity: O(1) unless bridging from Objective-C requires an
225+
/// O(N) conversion.
226+
public subscript(subRange: Range<Index>) -> UTF8View {
227+
return UTF8View(_core, subRange.startIndex, subRange.endIndex)
228+
}
229+
208230
/// Return a *generator* over the code points that comprise this
209231
/// *sequence*.
210232
///
@@ -217,6 +239,14 @@ extension String {
217239
public func getMirror() -> MirrorType {
218240
return _UTF8ViewMirror(self)
219241
}
242+
243+
public var description: String {
244+
return String._fromCodeUnitSequenceWithRepair(UTF8.self, input: self).0
245+
}
246+
247+
public var debugDescription: String {
248+
return "UTF8View(\(self.description.debugDescription))"
249+
}
220250
}
221251

222252
/// A UTF-8 encoding of `self`.

stdlib/core/StringUTFViewsMirrors.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ extension String {
3232
return ("[\(i)]", reflect(_value[advance(_value.startIndex, i)]))
3333
}
3434

35-
var summary: String { return String(_value._core) }
35+
var summary: String { return _value.description }
3636

3737
var quickLookObject: QuickLookObject? { return .Some(.Text(summary)) }
3838
}

stdlib/core/StringUnicodeScalarView.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ extension String {
2828
/// A collection of `Unicode scalar values
2929
/// <http://www.unicode.org/glossary/#unicode_scalar_value>`_ that
3030
/// encode a `String` .
31-
public struct UnicodeScalarView : Sliceable, SequenceType, Reflectable {
31+
public struct UnicodeScalarView : Sliceable, SequenceType, Reflectable,
32+
Printable, DebugPrintable {
3233
init(_ _core: _StringCore) {
3334
self._core = _core
3435
}
@@ -210,6 +211,14 @@ extension String {
210211
return _UnicodeScalarViewMirror(self)
211212
}
212213

214+
public var description: String {
215+
return String(_core[self.startIndex._position..<self.endIndex._position])
216+
}
217+
218+
public var debugDescription: String {
219+
return "StringUnicodeScalarView(\(self.description.debugDescription))"
220+
}
221+
213222
var _core: _StringCore
214223
}
215224

test/1_stdlib/String.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,5 +964,40 @@ StringTests.test("uppercaseString") {
964964
expectEqual("\u{0046}\u{0049}", "\u{fb01}".uppercaseString)
965965
}
966966

967+
StringTests.test("unicodeViews") {
968+
// Check the UTF views work with slicing
969+
970+
// U+FFFD REPLACEMENT CHARACTER
971+
// U+1F3C2 SNOWBOARDER
972+
// U+2603 SNOWMAN
973+
let winter = "\u{1F3C2}\u{2603}"
974+
975+
// slices
976+
// It is 4 bytes long, so it should return a replacement character.
977+
expectEqual("\u{FFFD}", toString(winter.utf8[winter.utf8.startIndex ..<
978+
winter.utf8.startIndex.successor().successor()]))
979+
expectEqual("\u{1F3C2}", toString(winter.utf8[winter.utf8.startIndex ..<
980+
advance(winter.utf8.startIndex, 4)]))
981+
982+
expectEqual("\u{1F3C2}", toString(winter.utf16[winter.utf16.startIndex ..<
983+
advance(winter.utf16.startIndex, 2)]))
984+
expectEqual("\u{1F3C2}", toString(winter.unicodeScalars[
985+
winter.unicodeScalars.startIndex ..<
986+
winter.unicodeScalars.startIndex.successor()]))
987+
988+
// views
989+
expectEqual(winter, toString(winter.utf8[winter.utf8.startIndex ..<
990+
advance(winter.utf8.startIndex, 7)]))
991+
expectEqual(winter, toString(winter.utf16[winter.utf16.startIndex ..<
992+
advance(winter.utf16.startIndex, 3)]))
993+
expectEqual(winter, toString(
994+
winter.unicodeScalars[winter.unicodeScalars.startIndex ..<
995+
advance(winter.unicodeScalars.startIndex, 2)]))
996+
997+
let ga = "\u{304b}\u{3099}"
998+
expectEqual(ga, toString(ga.utf8[ga.utf8.startIndex ..<
999+
advance(ga.utf8.startIndex, 6)]))
1000+
}
1001+
9671002
runAllTests()
9681003

0 commit comments

Comments
 (0)