Skip to content

Commit

Permalink
[stdlib] String.CharacterView.SubSequence is Substring.CharacterView
Browse files Browse the repository at this point in the history
This changes String.CharacterView from being its own slice type to
instead use Substring.CharacterView. In the process, this updates
Substring.CharacterView to be RangeReplaceable.

This aligns with the goal of introducing Substring as a separate type
to avoid accidental memory "leaks".
  • Loading branch information
milseman committed Aug 8, 2017
1 parent 3c07122 commit ffb3807
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 18 deletions.
8 changes: 8 additions & 0 deletions stdlib/public/core/StringCharacterView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,8 @@ extension String.CharacterView : RangeReplaceableCollection {

// Algorithms
extension String.CharacterView {
public typealias SubSequence = Substring.CharacterView

/// Accesses the characters in the given range.
///
/// The example below uses this subscript to access the characters up to, but
Expand All @@ -739,6 +741,12 @@ extension String.CharacterView {
///
/// - Complexity: O(*n*) if the underlying string is bridged from
/// Objective-C, where *n* is the length of the string; otherwise, O(1).
@available(swift, introduced: 4.0)
public subscript(bounds: Range<Index>) -> Substring.CharacterView {
return String(self)[bounds].characters
}

@available(swift, obsoleted: 4.0)
public subscript(bounds: Range<Index>) -> String.CharacterView {
return String.CharacterView(
unicodeScalars[bounds]._core,
Expand Down
19 changes: 16 additions & 3 deletions stdlib/public/core/Substring.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ extension StringProtocol {
% ('characters', 'Character')
% ]:
% View = ViewPrefix + 'View'
% RangeReplaceable = 'RangeReplaceable' if property == 'unicodeScalars' else ''
% RangeReplaceable = 'RangeReplaceable' if property == 'unicodeScalars' or property == 'characters' else ''
extension Substring {
public struct ${View} {
var _slice: ${RangeReplaceable}BidirectionalSlice<String.${View}>
Expand Down Expand Up @@ -467,10 +467,10 @@ extension String {
}
% end
}
% end

// FIXME: The other String views should be RangeReplaceable too.
extension Substring.UnicodeScalarView : RangeReplaceableCollection {
% if RangeReplaceable == 'RangeReplaceable':
extension Substring.${View} : RangeReplaceableCollection {
public init() { _slice = RangeReplaceableBidirectionalSlice.init() }

public mutating func replaceSubrange<C : Collection>(
Expand All @@ -479,6 +479,9 @@ extension Substring.UnicodeScalarView : RangeReplaceableCollection {
_slice.replaceSubrange(target, with: replacement)
}
}
% end # if RangeReplaceable

% end # for (property, ViewPrefix) in

#if _runtime(_ObjC)

Expand Down Expand Up @@ -524,6 +527,16 @@ extension Substring : RangeReplaceableCollection {
}
}

extension Substring.CharacterView : _SwiftStringView {
var _persistentContent : String {
return Substring(self)._persistentContent
}
var _ephemeralContent : String {
return Substring(self)._ephemeralContent
}

}

extension Substring {
public func lowercased() -> String {
return String(self).lowercased()
Expand Down
2 changes: 1 addition & 1 deletion test/stdlib/ErrorHandling.swift
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ ErrorHandlingTests.test("ErrorHandling/index(where:)") {

ErrorHandlingTests.test("ErrorHandling/split") {
do {
let _: [String.CharacterView] = try "foo".characters.split { _ in
let _: [Substring] = try "foo".split { _ in
throw SillyError.JazzHands
return false
}
Expand Down
6 changes: 3 additions & 3 deletions test/stdlib/subString.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ SubstringTests.test("CharacterView") {

t.replaceSubrange(t.startIndex...t.startIndex, with: ["C"])
u.replaceSubrange(u.startIndex...u.startIndex, with: ["E"])
expectEqual(String(u), "Efg")
expectEqual(String(t), "Cdefg")
expectEqual(s, "abcdefg")
expectEqual("Efg", String(u))
expectEqual("Cdefg", String(t))
expectEqual("abcdefg", s)
}

SubstringTests.test("UnicodeScalars") {
Expand Down
12 changes: 8 additions & 4 deletions validation-test/stdlib/String.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,43 +56,47 @@ StringTests.test("sizeof") {

StringTests.test("AssociatedTypes-UTF8View") {
typealias View = String.UTF8View
typealias SubView = Substring.UTF8View
expectCollectionAssociatedTypes(
collectionType: View.self,
iteratorType: View.Iterator.self,
subSequenceType: Substring.UTF8View.self,
subSequenceType: SubView.self,
indexType: View.Index.self,
indexDistanceType: Int.self,
indicesType: DefaultBidirectionalIndices<View>.self)
}

StringTests.test("AssociatedTypes-UTF16View") {
typealias View = String.UTF16View
typealias SubView = Substring.UTF16View
expectCollectionAssociatedTypes(
collectionType: View.self,
iteratorType: IndexingIterator<View>.self,
subSequenceType: Substring.UTF16View.self,
subSequenceType: SubView.self,
indexType: View.Index.self,
indexDistanceType: Int.self,
indicesType: View.Indices.self)
}

StringTests.test("AssociatedTypes-UnicodeScalarView") {
typealias View = String.UnicodeScalarView
typealias SubView = Substring.UnicodeScalarView
expectCollectionAssociatedTypes(
collectionType: View.self,
iteratorType: View.Iterator.self,
subSequenceType: Substring.UnicodeScalarView.self,
subSequenceType: SubView.self,
indexType: View.Index.self,
indexDistanceType: Int.self,
indicesType: DefaultBidirectionalIndices<View>.self)
}

StringTests.test("AssociatedTypes-CharacterView") {
typealias View = String.CharacterView
typealias SubView = Substring.CharacterView
expectCollectionAssociatedTypes(
collectionType: View.self,
iteratorType: IndexingIterator<View>.self,
subSequenceType: View.self,
subSequenceType: SubView.self,
indexType: View.Index.self,
indexDistanceType: Int.self,
indicesType: DefaultBidirectionalIndices<View>.self)
Expand Down
14 changes: 7 additions & 7 deletions validation-test/stdlib/StringViews.swift
Original file line number Diff line number Diff line change
Expand Up @@ -482,15 +482,15 @@ tests.test("index-mapping/unicode-scalar-to-character/\(id)") {
"❄️", err("\u{FE0F}"),
replacementCharacter, "\u{20}", replacementCharacter, replacementCharacter
]

let mappedChars = winter.unicodeScalars.indices.map {
i in mapIndex(i, winter).map {
winter[$0]
}
}

expectEqualSequence(
winterUnicodeScalarCharacters,

winter.unicodeScalars.indices.map {
i in mapIndex(i, winter).map {
winter[$0]
}
}, sameValue: ==)
winterUnicodeScalarCharacters, mappedChars, sameValue: ==)

expectEqual(winter.endIndex, mapIndex(winter.unicodeScalars.endIndex, winter)!)

Expand Down

0 comments on commit ffb3807

Please sign in to comment.