Skip to content

Fix Foundation extensions to Substring #1244

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 2, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 35 additions & 24 deletions Foundation/NSStringAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,6 @@ func _toNSArray<T, U : AnyObject>(_ a: [T], f: (T) -> U) -> NSArray {
return result
}

func _toNSRange(_ r: Range<String.Index>) -> NSRange {
return NSRange(
location: r.lowerBound.encodedOffset,
length: r.upperBound.encodedOffset - r.lowerBound.encodedOffset)
}

#if !DEPLOYMENT_RUNTIME_SWIFT
// We only need this for UnsafeMutablePointer, but there's not currently a way
// to write that constraint.
Expand Down Expand Up @@ -439,10 +433,26 @@ extension StringProtocol where Index == String.Index {
return self._ephemeralString._bridgeToObjectiveC()
}

// self can be a Substring so we need to subtract/add this offset when
// passing _ns to the Foundation APIs. Will be 0 if self is String.
@_inlineable
@_versioned
internal var _substringOffset: Int {
return self.startIndex.encodedOffset
}

/// Return an `Index` corresponding to the given offset in our UTF-16
/// representation.
func _index(_ utf16Index: Int) -> Index {
return Index(encodedOffset: utf16Index)
return Index(encodedOffset: utf16Index + _substringOffset)
}

@_inlineable
@_versioned
internal func _toRelativeNSRange(_ r: Range<String.Index>) -> NSRange {
return NSRange(
location: r.lowerBound.encodedOffset - _substringOffset,
length: r.upperBound.encodedOffset - r.lowerBound.encodedOffset)
}

/// Return a `Range<Index>` corresponding to the given `NSRange` of
Expand Down Expand Up @@ -603,7 +613,7 @@ extension StringProtocol where Index == String.Index {
return locale != nil ? _ns.compare(
aString,
options: mask,
range: _toNSRange(
range: _toRelativeNSRange(
range ?? startIndex..<endIndex
),
locale: locale?._bridgeToObjectiveC()
Expand All @@ -612,7 +622,7 @@ extension StringProtocol where Index == String.Index {
: range != nil ? _ns.compare(
aString,
options: mask,
range: _toNSRange(range!)
range: _toRelativeNSRange(range!)
)

: !mask.isEmpty ? _ns.compare(aString, options: mask)
Expand Down Expand Up @@ -1050,7 +1060,7 @@ extension StringProtocol where Index == String.Index {
T : StringProtocol, R : RangeExpression
>(in range: R, with replacement: T) -> String where R.Bound == Index {
return _ns.replacingCharacters(
in: _toNSRange(range.relative(to: self)),
in: _toRelativeNSRange(range.relative(to: self)),
with: replacement._ephemeralString)
}

Expand Down Expand Up @@ -1083,7 +1093,7 @@ extension StringProtocol where Index == String.Index {
of: target,
with: replacement,
options: options,
range: _toNSRange(
range: _toRelativeNSRange(
searchRange ?? startIndex..<endIndex
)
)
Expand Down Expand Up @@ -1208,7 +1218,7 @@ extension StringProtocol where Index == String.Index {
) where R.Bound == Index {
let range = range.relative(to: self)
_ns.enumerateLinguisticTags(
in: _toNSRange(range),
in: _toRelativeNSRange(range),
scheme: tagScheme._ephemeralString,
options: opts,
orthography: orthography != nil ? orthography! : nil
Expand Down Expand Up @@ -1273,7 +1283,7 @@ extension StringProtocol where Index == String.Index {
) -> Void
) where R.Bound == Index {
_ns.enumerateSubstrings(
in: _toNSRange(range.relative(to: self)), options: opts) {
in: _toRelativeNSRange(range.relative(to: self)), options: opts) {
var stop_ = false

body($0,
Expand Down Expand Up @@ -1346,7 +1356,7 @@ extension StringProtocol where Index == String.Index {
usedLength: usedBufferCount,
encoding: encoding.rawValue,
options: options,
range: _toNSRange(range.relative(to: self)),
range: _toRelativeNSRange(range.relative(to: self)),
remaining: $0)
}
}
Expand All @@ -1373,7 +1383,7 @@ extension StringProtocol where Index == String.Index {
contentsEnd in self._ns.getLineStart(
start, end: end,
contentsEnd: contentsEnd,
for: _toNSRange(range.relative(to: self)))
for: _toRelativeNSRange(range.relative(to: self)))
}
}
}
Expand Down Expand Up @@ -1401,7 +1411,7 @@ extension StringProtocol where Index == String.Index {
contentsEnd in self._ns.getParagraphStart(
start, end: end,
contentsEnd: contentsEnd,
for: _toNSRange(range.relative(to: self)))
for: _toRelativeNSRange(range.relative(to: self)))
}
}
}
Expand All @@ -1428,7 +1438,8 @@ extension StringProtocol where Index == String.Index {
public func lineRange<
R : RangeExpression
>(for aRange: R) -> Range<Index> where R.Bound == Index {
return _range(_ns.lineRange(for: _toNSRange(aRange.relative(to: self))))
return _range(_ns.lineRange(
for: _toRelativeNSRange(aRange.relative(to: self))))
}

#if !DEPLOYMENT_RUNTIME_SWIFT
Expand All @@ -1453,7 +1464,7 @@ extension StringProtocol where Index == String.Index {
var nsTokenRanges: NSArray?
let result = tokenRanges._withNilOrAddress(of: &nsTokenRanges) {
self._ns.linguisticTags(
in: _toNSRange(range.relative(to: self)),
in: _toRelativeNSRange(range.relative(to: self)),
scheme: tagScheme._ephemeralString,
options: opts,
orthography: orthography,
Expand All @@ -1477,7 +1488,7 @@ extension StringProtocol where Index == String.Index {
R : RangeExpression
>(for aRange: R) -> Range<Index> where R.Bound == Index {
return _range(
_ns.paragraphRange(for: _toNSRange(aRange.relative(to: self))))
_ns.paragraphRange(for: _toRelativeNSRange(aRange.relative(to: self))))
}
#endif

Expand All @@ -1504,7 +1515,7 @@ extension StringProtocol where Index == String.Index {
_ns.rangeOfCharacter(
from: aSet,
options: mask,
range: _toNSRange(
range: _toRelativeNSRange(
aRange ?? startIndex..<endIndex
)
)
Expand Down Expand Up @@ -1535,7 +1546,7 @@ extension StringProtocol where Index == String.Index {
// and output ranges due (if nothing else) to locale changes
return _range(
_ns.rangeOfComposedCharacterSequences(
for: _toNSRange(range.relative(to: self))))
for: _toRelativeNSRange(range.relative(to: self))))
}

// - (NSRange)rangeOfString:(NSString *)aString
Expand Down Expand Up @@ -1570,13 +1581,13 @@ extension StringProtocol where Index == String.Index {
locale != nil ? _ns.range(
of: aString,
options: mask,
range: _toNSRange(
range: _toRelativeNSRange(
searchRange ?? startIndex..<endIndex
),
locale: locale
)
: searchRange != nil ? _ns.range(
of: aString, options: mask, range: _toNSRange(searchRange!)
of: aString, options: mask, range: _toRelativeNSRange(searchRange!)
)
: !mask.isEmpty ? _ns.range(of: aString, options: mask)
: _ns.range(of: aString)
Expand Down Expand Up @@ -1687,7 +1698,7 @@ extension StringProtocol where Index == String.Index {
@available(swift, deprecated: 4.0,
message: "Please use String slicing subscript.")
public func substring(with aRange: Range<Index>) -> String {
return _ns.substring(with: _toNSRange(aRange))
return _ns.substring(with: _toRelativeNSRange(aRange))
}
}

Expand Down