mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
stdlib: move the bulk of SequenceType algorithms to protocol extensions
rdar://19895265 Swift SVN r27269
This commit is contained in:
@@ -25,9 +25,9 @@ import ObjectiveC
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
public struct SourceLoc {
|
public struct SourceLoc {
|
||||||
let file: String
|
public let file: String
|
||||||
let line: UWord
|
public let line: UWord
|
||||||
let comment: String?
|
public let comment: String?
|
||||||
|
|
||||||
public init(_ file: String, _ line: UWord, comment: String? = nil) {
|
public init(_ file: String, _ line: UWord, comment: String? = nil) {
|
||||||
self.file = file
|
self.file = file
|
||||||
@@ -135,13 +135,15 @@ public func expectEqual<T>(
|
|||||||
public func expectNotEqual<T : Equatable>(
|
public func expectNotEqual<T : Equatable>(
|
||||||
expected: T, actual: T,
|
expected: T, actual: T,
|
||||||
stackTrace: SourceLocStack? = nil,
|
stackTrace: SourceLocStack? = nil,
|
||||||
file: String = __FILE__, line: UWord = __LINE__
|
file: String = __FILE__, line: UWord = __LINE__,
|
||||||
|
collectMoreInfo: (()->String)? = nil
|
||||||
) {
|
) {
|
||||||
if expected == actual {
|
if expected == actual {
|
||||||
_anyExpectFailed = true
|
_anyExpectFailed = true
|
||||||
println("check failed at \(file), line \(line)")
|
println("check failed at \(file), line \(line)")
|
||||||
_printStackTrace(stackTrace)
|
_printStackTrace(stackTrace)
|
||||||
println("unexpected value: \"\(actual)\" (of type \(_stdlib_getDemangledTypeName(actual)))")
|
println("unexpected value: \"\(actual)\" (of type \(_stdlib_getDemangledTypeName(actual)))")
|
||||||
|
if collectMoreInfo != nil { println(collectMoreInfo!()) }
|
||||||
println()
|
println()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,11 +152,13 @@ public func expectNotEqual<T : Equatable>(
|
|||||||
// <rdar://problem/17015923> Array->NSArray implicit conversion insanity
|
// <rdar://problem/17015923> Array->NSArray implicit conversion insanity
|
||||||
public func expectOptionalEqual<T : Equatable>(
|
public func expectOptionalEqual<T : Equatable>(
|
||||||
expected: T, actual: T?,
|
expected: T, actual: T?,
|
||||||
|
stackTrace: SourceLocStack? = nil,
|
||||||
file: String = __FILE__, line: UWord = __LINE__
|
file: String = __FILE__, line: UWord = __LINE__
|
||||||
) {
|
) {
|
||||||
if (actual == nil) || expected != actual! {
|
if (actual == nil) || expected != actual! {
|
||||||
_anyExpectFailed = true
|
_anyExpectFailed = true
|
||||||
println("check failed at \(file), line \(line)")
|
println("check failed at \(file), line \(line)")
|
||||||
|
_printStackTrace(stackTrace)
|
||||||
println("expected: \"\(expected)\" (of type \(_stdlib_getDemangledTypeName(expected)))")
|
println("expected: \"\(expected)\" (of type \(_stdlib_getDemangledTypeName(expected)))")
|
||||||
println("actual: \"\(actual)\" (of type \(_stdlib_getDemangledTypeName(actual)))")
|
println("actual: \"\(actual)\" (of type \(_stdlib_getDemangledTypeName(actual)))")
|
||||||
println()
|
println()
|
||||||
@@ -163,12 +167,14 @@ public func expectOptionalEqual<T : Equatable>(
|
|||||||
|
|
||||||
public func expectEqual<T : Equatable>(
|
public func expectEqual<T : Equatable>(
|
||||||
expected: T?, actual: T?,
|
expected: T?, actual: T?,
|
||||||
|
stackTrace: SourceLocStack? = nil,
|
||||||
file: String = __FILE__, line: UWord = __LINE__
|
file: String = __FILE__, line: UWord = __LINE__
|
||||||
) {
|
) {
|
||||||
if (actual == nil) != (expected == nil)
|
if (actual == nil) != (expected == nil)
|
||||||
|| actual != nil && expected! != actual! {
|
|| actual != nil && expected! != actual! {
|
||||||
_anyExpectFailed = true
|
_anyExpectFailed = true
|
||||||
println("check failed at \(file), line \(line)")
|
println("check failed at \(file), line \(line)")
|
||||||
|
_printStackTrace(stackTrace)
|
||||||
println("expected: \"\(expected)\" (of type \(_stdlib_getDemangledTypeName(expected)))")
|
println("expected: \"\(expected)\" (of type \(_stdlib_getDemangledTypeName(expected)))")
|
||||||
println("actual: \"\(actual)\" (of type \(_stdlib_getDemangledTypeName(actual)))")
|
println("actual: \"\(actual)\" (of type \(_stdlib_getDemangledTypeName(actual)))")
|
||||||
println()
|
println()
|
||||||
@@ -182,8 +188,7 @@ public func expectEqual<T : Equatable>(
|
|||||||
% ('<T : Equatable>', '_UnitTestArray<T>'),
|
% ('<T : Equatable>', '_UnitTestArray<T>'),
|
||||||
% ('<T : Equatable>', 'ArraySlice<T>'),
|
% ('<T : Equatable>', 'ArraySlice<T>'),
|
||||||
% ('<T : Equatable>', 'Array<T>'),
|
% ('<T : Equatable>', 'Array<T>'),
|
||||||
% ('<T, U : Equatable>', 'Dictionary<T, U>'),
|
% ('<T, U : Equatable>', 'Dictionary<T, U>')]:
|
||||||
% ('<T : ForwardIndexType>', 'T')]:
|
|
||||||
|
|
||||||
public func expectEqual${Generic}(
|
public func expectEqual${Generic}(
|
||||||
expected: ${EquatableType}, actual: ${EquatableType},
|
expected: ${EquatableType}, actual: ${EquatableType},
|
||||||
@@ -219,12 +224,14 @@ public func expectEqualSequence${Generic}(
|
|||||||
|
|
||||||
func _expectNotEqual${Generic}(
|
func _expectNotEqual${Generic}(
|
||||||
expected: ${EquatableType}, actual: ${EquatableType},
|
expected: ${EquatableType}, actual: ${EquatableType},
|
||||||
file: String = __FILE__, line: UWord = __LINE__
|
file: String = __FILE__, line: UWord = __LINE__,
|
||||||
|
collectMoreInfo: (()->String)? = nil
|
||||||
) {
|
) {
|
||||||
if expected == actual {
|
if expected == actual {
|
||||||
_anyExpectFailed = true
|
_anyExpectFailed = true
|
||||||
println("check failed at \(file), line \(line)")
|
println("check failed at \(file), line \(line)")
|
||||||
println("unexpected value: \"\(actual)\" (of type \(_stdlib_getDemangledTypeName(actual)))")
|
println("unexpected value: \"\(actual)\" (of type \(_stdlib_getDemangledTypeName(actual)))")
|
||||||
|
if collectMoreInfo != nil { println(collectMoreInfo!()) }
|
||||||
println()
|
println()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,27 +254,35 @@ public func expectOptionalEqual${Generic}(
|
|||||||
%for ComparableType in ['Int']:
|
%for ComparableType in ['Int']:
|
||||||
|
|
||||||
public func expectLE(
|
public func expectLE(
|
||||||
expected: ${ComparableType}, actual: ${ComparableType},
|
expected: ${ComparableType}, actual: ${ComparableType},
|
||||||
file: String = __FILE__, line: UWord = __LINE__
|
stackTrace: SourceLocStack? = nil,
|
||||||
|
file: String = __FILE__, line: UWord = __LINE__,
|
||||||
|
collectMoreInfo: (()->String)? = nil
|
||||||
) {
|
) {
|
||||||
if !(expected <= actual) {
|
if !(expected <= actual) {
|
||||||
_anyExpectFailed = true
|
_anyExpectFailed = true
|
||||||
println("check failed at \(file), line \(line)")
|
println("check failed at \(file), line \(line)")
|
||||||
|
_printStackTrace(stackTrace)
|
||||||
println("expected: \"\(expected)\"")
|
println("expected: \"\(expected)\"")
|
||||||
println("actual: \"\(actual)\"")
|
println("actual: \"\(actual)\"")
|
||||||
|
if collectMoreInfo != nil { println(collectMoreInfo!()) }
|
||||||
println()
|
println()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func expectGE(
|
public func expectGE(
|
||||||
expected: ${ComparableType}, actual: ${ComparableType},
|
expected: ${ComparableType}, actual: ${ComparableType},
|
||||||
file: String = __FILE__, line: UWord = __LINE__
|
stackTrace: SourceLocStack? = nil,
|
||||||
|
file: String = __FILE__, line: UWord = __LINE__,
|
||||||
|
collectMoreInfo: (()->String)? = nil
|
||||||
) {
|
) {
|
||||||
if !(expected >= actual) {
|
if !(expected >= actual) {
|
||||||
_anyExpectFailed = true
|
_anyExpectFailed = true
|
||||||
println("check failed at \(file), line \(line)")
|
println("check failed at \(file), line \(line)")
|
||||||
|
_printStackTrace(stackTrace)
|
||||||
println("expected: \"\(expected)\"")
|
println("expected: \"\(expected)\"")
|
||||||
println("actual: \"\(actual)\"")
|
println("actual: \"\(actual)\"")
|
||||||
|
if collectMoreInfo != nil { println(collectMoreInfo!()) }
|
||||||
println()
|
println()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -361,7 +376,8 @@ public func expectFalse(
|
|||||||
public func expectEmpty<T>(
|
public func expectEmpty<T>(
|
||||||
value: Optional<T>,
|
value: Optional<T>,
|
||||||
stackTrace: SourceLocStack? = nil,
|
stackTrace: SourceLocStack? = nil,
|
||||||
file: String = __FILE__, line: UWord = __LINE__
|
file: String = __FILE__, line: UWord = __LINE__,
|
||||||
|
collectMoreInfo: (()->String)? = nil
|
||||||
) {
|
) {
|
||||||
if value != nil {
|
if value != nil {
|
||||||
_anyExpectFailed = true
|
_anyExpectFailed = true
|
||||||
@@ -369,6 +385,7 @@ public func expectEmpty<T>(
|
|||||||
_printStackTrace(stackTrace)
|
_printStackTrace(stackTrace)
|
||||||
println("expected optional to be empty")
|
println("expected optional to be empty")
|
||||||
println("actual: \"\(value)\"")
|
println("actual: \"\(value)\"")
|
||||||
|
if collectMoreInfo != nil { println(collectMoreInfo!()) }
|
||||||
println()
|
println()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1341,6 +1358,19 @@ public func checkComparable<T : Comparable>(
|
|||||||
collectMoreInfo: collectMoreInfo)
|
collectMoreInfo: collectMoreInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct CollectionMisuseResiliencyChecks {
|
||||||
|
public var callNextOnExhaustedGenerator: Bool = true
|
||||||
|
|
||||||
|
public static var all: CollectionMisuseResiliencyChecks {
|
||||||
|
return CollectionMisuseResiliencyChecks()
|
||||||
|
}
|
||||||
|
|
||||||
|
public static var none: CollectionMisuseResiliencyChecks {
|
||||||
|
return CollectionMisuseResiliencyChecks(
|
||||||
|
callNextOnExhaustedGenerator: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Generate two overloads: one for _UnitTestArray (which will get
|
// Generate two overloads: one for _UnitTestArray (which will get
|
||||||
// picked up when the caller passes a literal), and another that
|
// picked up when the caller passes a literal), and another that
|
||||||
// accepts any appropriate Collection type.
|
// accepts any appropriate Collection type.
|
||||||
@@ -1351,10 +1381,14 @@ public func checkComparable<T : Comparable>(
|
|||||||
|
|
||||||
public func checkGenerator<
|
public func checkGenerator<
|
||||||
G : GeneratorType, ${genericParam}
|
G : GeneratorType, ${genericParam}
|
||||||
where ${Element} == G.Element, ${Element} : Equatable
|
where ${Element} == G.Element
|
||||||
>(
|
>(
|
||||||
expected: ${Expected},
|
expected: ${Expected},
|
||||||
generator: G, stackTrace: SourceLocStack
|
generator: G,
|
||||||
|
sameValue: (${Element}, ${Element}) -> Bool,
|
||||||
|
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
|
||||||
|
stackTrace: SourceLocStack,
|
||||||
|
collectMoreInfo: (()->String)? = nil
|
||||||
) {
|
) {
|
||||||
// Copying a `GeneratorType` is allowed.
|
// Copying a `GeneratorType` is allowed.
|
||||||
var mutableGen = generator
|
var mutableGen = generator
|
||||||
@@ -1362,73 +1396,322 @@ public func checkGenerator<
|
|||||||
while let e? = mutableGen.next() {
|
while let e? = mutableGen.next() {
|
||||||
actual.append(e)
|
actual.append(e)
|
||||||
}
|
}
|
||||||
expectEqualSequence(expected, actual, stackTrace: stackTrace.withCurrentLoc())
|
expectEqualSequence(
|
||||||
|
expected, actual, sameValue,
|
||||||
|
stackTrace: stackTrace.withCurrentLoc(),
|
||||||
|
collectMoreInfo: collectMoreInfo)
|
||||||
|
|
||||||
// Having returned `.None` once, a `GeneratorType` should not generate more
|
if resiliencyChecks.callNextOnExhaustedGenerator {
|
||||||
// elements.
|
// Having returned `.None` once, a `GeneratorType` should not generate more
|
||||||
for i in 0..<10 {
|
// elements.
|
||||||
expectEmpty(mutableGen.next(), stackTrace: stackTrace.withCurrentLoc())
|
for i in 0..<10 {
|
||||||
|
expectEmpty(
|
||||||
|
mutableGen.next(),
|
||||||
|
stackTrace: stackTrace.withCurrentLoc(),
|
||||||
|
collectMoreInfo: collectMoreInfo)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func checkGenerator<
|
||||||
|
G : GeneratorType, ${genericParam}
|
||||||
|
where ${Element} == G.Element, ${Element} : Equatable
|
||||||
|
>(
|
||||||
|
expected: ${Expected},
|
||||||
|
generator: G,
|
||||||
|
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
|
||||||
|
stackTrace: SourceLocStack,
|
||||||
|
collectMoreInfo: (()->String)? = nil
|
||||||
|
) {
|
||||||
|
checkGenerator(
|
||||||
|
expected, generator, { $0 == $1 },
|
||||||
|
resiliencyChecks: resiliencyChecks,
|
||||||
|
stackTrace.withCurrentLoc(),
|
||||||
|
collectMoreInfo: collectMoreInfo)
|
||||||
|
}
|
||||||
|
|
||||||
public func checkSequence<
|
public func checkSequence<
|
||||||
${genericParam}, S : SequenceType
|
${genericParam}, S : SequenceType
|
||||||
where S.Generator.Element == ${Element}, ${Element} : Equatable
|
where S.Generator.Element == ${Element}
|
||||||
>(
|
>(
|
||||||
expected: ${Expected},
|
expected: ${Expected},
|
||||||
sequence: S, stackTrace: SourceLocStack
|
sequence: S,
|
||||||
|
sameValue: (${Element}, ${Element}) -> Bool,
|
||||||
|
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
|
||||||
|
stackTrace: SourceLocStack,
|
||||||
|
collectMoreInfo: (()->String)? = nil
|
||||||
) {
|
) {
|
||||||
let expectedCount: Int = numericCast(count(expected))
|
let expectedCount: Int = numericCast(count(expected))
|
||||||
checkGenerator(expected, sequence.generate(), stackTrace.withCurrentLoc())
|
checkGenerator(
|
||||||
expectGE(expectedCount, underestimateCount(sequence))
|
expected, sequence.generate(), sameValue,
|
||||||
|
resiliencyChecks: resiliencyChecks,
|
||||||
|
stackTrace.withCurrentLoc())
|
||||||
|
expectGE(
|
||||||
|
expectedCount, underestimateCount(sequence),
|
||||||
|
stackTrace: stackTrace.withCurrentLoc(),
|
||||||
|
collectMoreInfo: collectMoreInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func checkCollection<
|
public func checkSequence<
|
||||||
${genericParam}, C : CollectionType
|
${genericParam}, S : SequenceType
|
||||||
where C.Generator.Element == ${Element}, ${Element} : Equatable
|
where S.Generator.Element == ${Element}
|
||||||
>(
|
>(
|
||||||
expected: ${Expected},
|
expected: ${Expected},
|
||||||
collection: C, stackTrace: SourceLocStack
|
sequence: S,
|
||||||
|
sameValue: (${Element}, ${Element}) -> Bool,
|
||||||
|
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
|
||||||
|
file: String = __FILE__, line: UWord = __LINE__,
|
||||||
|
collectMoreInfo: (()->String)? = nil
|
||||||
|
) {
|
||||||
|
checkSequence(
|
||||||
|
expected, sequence, sameValue,
|
||||||
|
resiliencyChecks: resiliencyChecks,
|
||||||
|
SourceLocStack().with(SourceLoc(file, line)),
|
||||||
|
collectMoreInfo: collectMoreInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func checkSequence<
|
||||||
|
${genericParam}, S : SequenceType
|
||||||
|
where S.Generator.Element == ${Element}, ${Element} : Equatable
|
||||||
|
>(
|
||||||
|
expected: ${Expected},
|
||||||
|
sequence: S,
|
||||||
|
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
|
||||||
|
stackTrace: SourceLocStack,
|
||||||
|
collectMoreInfo: (()->String)? = nil
|
||||||
|
) {
|
||||||
|
checkSequence(
|
||||||
|
expected, sequence, { $0 == $1 },
|
||||||
|
resiliencyChecks: resiliencyChecks,
|
||||||
|
stackTrace.withCurrentLoc(),
|
||||||
|
collectMoreInfo: collectMoreInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func checkSequence<
|
||||||
|
${genericParam}, S : SequenceType
|
||||||
|
where S.Generator.Element == ${Element}, ${Element} : Equatable
|
||||||
|
>(
|
||||||
|
expected: ${Expected},
|
||||||
|
sequence: S,
|
||||||
|
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
|
||||||
|
file: String = __FILE__, line: UWord = __LINE__,
|
||||||
|
collectMoreInfo: (()->String)? = nil
|
||||||
|
) {
|
||||||
|
checkSequence(
|
||||||
|
expected, sequence, { $0 == $1 },
|
||||||
|
resiliencyChecks: resiliencyChecks,
|
||||||
|
SourceLocStack().with(SourceLoc(file, line)),
|
||||||
|
collectMoreInfo: collectMoreInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
%for traversal in [ 'Forward', 'Bidirectional', 'RandomAccess' ]:
|
||||||
|
|
||||||
|
public func check${traversal}Collection<
|
||||||
|
${genericParam}, C : CollectionType
|
||||||
|
where
|
||||||
|
C.Generator.Element == ${Element},
|
||||||
|
C.Index : ${traversal}IndexType
|
||||||
|
>(
|
||||||
|
expected: ${Expected},
|
||||||
|
collection: C,
|
||||||
|
sameValue: (${Element}, ${Element}) -> Bool,
|
||||||
|
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
|
||||||
|
stackTrace: SourceLocStack,
|
||||||
|
collectMoreInfo: (()->String)? = nil
|
||||||
) {
|
) {
|
||||||
// A `CollectionType` is a multi-pass `SequenceType`.
|
// A `CollectionType` is a multi-pass `SequenceType`.
|
||||||
for i in 0..<3 {
|
for i in 0..<3 {
|
||||||
checkSequence(expected, collection, stackTrace.withCurrentLoc())
|
checkSequence(
|
||||||
|
expected, collection, sameValue,
|
||||||
|
resiliencyChecks: resiliencyChecks,
|
||||||
|
stackTrace.withCurrentLoc(),
|
||||||
|
collectMoreInfo: collectMoreInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
expectEqual(count(expected).toIntMax(), count(collection).toIntMax(),
|
let expectedArray = Array(expected)
|
||||||
stackTrace: stackTrace.withCurrentLoc())
|
|
||||||
|
expectEqual(
|
||||||
|
count(expectedArray).toIntMax(),
|
||||||
|
count(collection).toIntMax(),
|
||||||
|
stackTrace: stackTrace.withCurrentLoc(),
|
||||||
|
collectMoreInfo: collectMoreInfo)
|
||||||
|
|
||||||
for i in 0..<3 {
|
for i in 0..<3 {
|
||||||
let startIndex = collection.startIndex
|
if true {
|
||||||
let endIndex = collection.endIndex
|
let startIndex = collection.startIndex
|
||||||
|
let endIndex = collection.endIndex
|
||||||
|
|
||||||
var actual: _UnitTestArray<${Element}> = []
|
for i in indices(collection) {
|
||||||
var index = collection.startIndex
|
expectEqual(startIndex, collection.startIndex,
|
||||||
while index != collection.endIndex {
|
stackTrace: stackTrace.withCurrentLoc()) {
|
||||||
// Iteration should not change `startIndex` or `endIndex`.
|
"Iteration should not change startIndex"
|
||||||
expectEqual(startIndex, collection.startIndex)
|
}
|
||||||
expectEqual(endIndex, collection.endIndex)
|
expectEqual(endIndex, collection.endIndex,
|
||||||
|
stackTrace: stackTrace.withCurrentLoc()) {
|
||||||
actual.append(collection[index])
|
"Iteration should not change endIndex"
|
||||||
++index
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expectEqualSequence(
|
var allIndices: [C.Index] = []
|
||||||
expected, actual, stackTrace: stackTrace.withCurrentLoc())
|
for i in indices(collection) {
|
||||||
|
allIndices.append(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
if count(expectedArray) >= 2 {
|
||||||
|
for i in 0..<allIndices.count-1 {
|
||||||
|
var successor1 = allIndices[i].successor()
|
||||||
|
var successor2 = allIndices[i]
|
||||||
|
successor2++
|
||||||
|
var successor3 = allIndices[i]
|
||||||
|
++successor3
|
||||||
|
for s in [ successor1, successor2, successor3 ] {
|
||||||
|
expectEqual(
|
||||||
|
allIndices[i + 1], s,
|
||||||
|
stackTrace: stackTrace.withCurrentLoc())
|
||||||
|
expectEqual(
|
||||||
|
expectedArray[i + 1],
|
||||||
|
collection[s],
|
||||||
|
sameValue,
|
||||||
|
stackTrace: stackTrace.withCurrentLoc())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
% if traversal == "Bidirectional":
|
||||||
|
for i in 1..<allIndices.count {
|
||||||
|
var predecessor1 = allIndices[i].predecessor()
|
||||||
|
var predecessor2 = allIndices[i]
|
||||||
|
predecessor2--
|
||||||
|
var predecessor3 = allIndices[i]
|
||||||
|
--predecessor3
|
||||||
|
for p in [ predecessor1, predecessor2, predecessor3 ] {
|
||||||
|
expectEqual(
|
||||||
|
allIndices[i - 1], p,
|
||||||
|
stackTrace: stackTrace.withCurrentLoc())
|
||||||
|
expectEqual(
|
||||||
|
expectedArray[i - 1], collection[p],
|
||||||
|
sameValue,
|
||||||
|
stackTrace: stackTrace.withCurrentLoc())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i in 1..<allIndices.count {
|
||||||
|
var index = allIndices[i]
|
||||||
|
--index
|
||||||
|
++index
|
||||||
|
expectEqual(
|
||||||
|
allIndices[i], index,
|
||||||
|
stackTrace: stackTrace.withCurrentLoc())
|
||||||
|
expectEqual(
|
||||||
|
expectedArray[i], collection[index],
|
||||||
|
sameValue,
|
||||||
|
stackTrace: stackTrace.withCurrentLoc())
|
||||||
|
}
|
||||||
|
% end
|
||||||
|
}
|
||||||
|
|
||||||
|
if true {
|
||||||
|
var allIndices2: [C.Index] = []
|
||||||
|
for i in indices(collection) {
|
||||||
|
allIndices2.append(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectEqualSequence(
|
||||||
|
allIndices, allIndices2,
|
||||||
|
stackTrace: stackTrace.withCurrentLoc()) {
|
||||||
|
"iteration should not invalidate indices"
|
||||||
|
}
|
||||||
|
|
||||||
|
expectEqualSequence(
|
||||||
|
expectedArray,
|
||||||
|
allIndices._prext_map { collection[$0] },
|
||||||
|
sameValue,
|
||||||
|
stackTrace: stackTrace.withCurrentLoc())
|
||||||
|
expectEqualSequence(
|
||||||
|
expectedArray,
|
||||||
|
allIndices2._prext_map { collection[$0] },
|
||||||
|
sameValue,
|
||||||
|
stackTrace: stackTrace.withCurrentLoc())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: more checks for bidirectional and random access collections.
|
||||||
}
|
}
|
||||||
|
|
||||||
public func checkSliceableWithBidirectionalIndex<
|
public func check${traversal}Collection<
|
||||||
${genericParam}, S : Sliceable
|
${genericParam}, C : CollectionType
|
||||||
where S.Generator.Element == ${Element},
|
where
|
||||||
S.SubSlice.Generator.Element == ${Element},
|
C.Generator.Element == ${Element},
|
||||||
S.Index : BidirectionalIndexType,
|
C.Index : ${traversal}IndexType
|
||||||
${Element} : Equatable
|
|
||||||
>(
|
>(
|
||||||
expected: ${Expected},
|
expected: ${Expected},
|
||||||
sliceable: S, stackTrace: SourceLocStack) {
|
collection: C,
|
||||||
|
sameValue: (${Element}, ${Element}) -> Bool,
|
||||||
|
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
|
||||||
|
file: String = __FILE__, line: UWord = __LINE__,
|
||||||
|
collectMoreInfo: (()->String)? = nil
|
||||||
|
) {
|
||||||
|
check${traversal}Collection(
|
||||||
|
expected, collection, sameValue,
|
||||||
|
resiliencyChecks: resiliencyChecks,
|
||||||
|
SourceLocStack().with(SourceLoc(file, line)),
|
||||||
|
collectMoreInfo: collectMoreInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func check${traversal}Collection<
|
||||||
|
${genericParam}, C : CollectionType
|
||||||
|
where
|
||||||
|
C.Generator.Element == ${Element},
|
||||||
|
C.Index : ${traversal}IndexType,
|
||||||
|
${Element} : Equatable
|
||||||
|
>(
|
||||||
|
expected: ${Expected},
|
||||||
|
collection: C,
|
||||||
|
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
|
||||||
|
stackTrace: SourceLocStack,
|
||||||
|
collectMoreInfo: (()->String)? = nil
|
||||||
|
) {
|
||||||
|
check${traversal}Collection(
|
||||||
|
expected, collection, { $0 == $1 },
|
||||||
|
resiliencyChecks: resiliencyChecks,
|
||||||
|
stackTrace.withCurrentLoc(),
|
||||||
|
collectMoreInfo: collectMoreInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func check${traversal}Collection<
|
||||||
|
${genericParam}, C : CollectionType
|
||||||
|
where
|
||||||
|
C.Generator.Element == ${Element},
|
||||||
|
C.Index : ${traversal}IndexType,
|
||||||
|
${Element} : Equatable
|
||||||
|
>(
|
||||||
|
expected: ${Expected},
|
||||||
|
collection: C,
|
||||||
|
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
|
||||||
|
file: String = __FILE__, line: UWord = __LINE__,
|
||||||
|
collectMoreInfo: (()->String)? = nil
|
||||||
|
) {
|
||||||
|
check${traversal}Collection(
|
||||||
|
expected, collection, { $0 == $1 },
|
||||||
|
resiliencyChecks: resiliencyChecks,
|
||||||
|
SourceLocStack().with(SourceLoc(file, line)),
|
||||||
|
collectMoreInfo: collectMoreInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
% end
|
||||||
|
|
||||||
|
public func checkSliceableWithBidirectionalIndex<
|
||||||
|
${genericParam}, S : Sliceable
|
||||||
|
where
|
||||||
|
S.Generator.Element == ${Element},
|
||||||
|
S.SubSlice.Generator.Element == ${Element},
|
||||||
|
S.Index : BidirectionalIndexType,
|
||||||
|
S.SubSlice.Index : BidirectionalIndexType,
|
||||||
|
${Element} : Equatable
|
||||||
|
>(
|
||||||
|
expected: ${Expected},
|
||||||
|
sliceable: S, stackTrace: SourceLocStack
|
||||||
|
) {
|
||||||
// A `Sliceable` is a `CollectionType`.
|
// A `Sliceable` is a `CollectionType`.
|
||||||
checkCollection(expected, sliceable, stackTrace.withCurrentLoc())
|
checkBidirectionalCollection(expected, sliceable, stackTrace.withCurrentLoc())
|
||||||
|
|
||||||
let expectedArray = _UnitTestArray(expected)
|
let expectedArray = _UnitTestArray(expected)
|
||||||
|
|
||||||
@@ -1450,7 +1733,8 @@ public func checkSliceableWithBidirectionalIndex<
|
|||||||
}
|
}
|
||||||
let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
|
let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
|
||||||
let slice = sliceable[start..<end]
|
let slice = sliceable[start..<end]
|
||||||
checkCollection(expectedSlice, slice, stackTrace.withCurrentLoc())
|
checkBidirectionalCollection(
|
||||||
|
expectedSlice, slice, stackTrace.withCurrentLoc())
|
||||||
|
|
||||||
if end != sliceable.endIndex {
|
if end != sliceable.endIndex {
|
||||||
++end
|
++end
|
||||||
@@ -1549,6 +1833,25 @@ public func expectEqualSequence<
|
|||||||
file: file, line: line, collectMoreInfo: collectMoreInfo)
|
file: file, line: line, collectMoreInfo: collectMoreInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func expectEqualSequence<
|
||||||
|
Expected : SequenceType,
|
||||||
|
Actual : SequenceType,
|
||||||
|
T : Equatable,
|
||||||
|
U : Equatable
|
||||||
|
where Expected.Generator.Element == Actual.Generator.Element,
|
||||||
|
Expected.Generator.Element == (T, U)
|
||||||
|
>(
|
||||||
|
expected: Expected, actual: Actual,
|
||||||
|
stackTrace: SourceLocStack? = nil,
|
||||||
|
file: String = __FILE__, line: UWord = __LINE__,
|
||||||
|
collectMoreInfo: (()->String)? = nil
|
||||||
|
) {
|
||||||
|
expectEqualSequence(
|
||||||
|
expected, actual, { $0.0 == $1.0 && $0.1 == $1.1 },
|
||||||
|
stackTrace: stackTrace, file: file, line: line,
|
||||||
|
collectMoreInfo: collectMoreInfo)
|
||||||
|
}
|
||||||
|
|
||||||
public func expectEqualSequence<
|
public func expectEqualSequence<
|
||||||
Expected: SequenceType,
|
Expected: SequenceType,
|
||||||
Actual: SequenceType
|
Actual: SequenceType
|
||||||
@@ -1901,26 +2204,26 @@ public func ~> <T> (
|
|||||||
|
|
||||||
public struct MinimalForwardIndex : ForwardIndexType {
|
public struct MinimalForwardIndex : ForwardIndexType {
|
||||||
public init(position: Int, endIndex: Int) {
|
public init(position: Int, endIndex: Int) {
|
||||||
self._position = position
|
self.position = position
|
||||||
self._endIndex = endIndex
|
self.endIndex = endIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(position: Int, startIndex _: Int, endIndex: Int) {
|
public init(position: Int, startIndex _: Int, endIndex: Int) {
|
||||||
self._position = position
|
self.position = position
|
||||||
self._endIndex = endIndex
|
self.endIndex = endIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
public func successor() -> MinimalForwardIndex {
|
public func successor() -> MinimalForwardIndex {
|
||||||
expectNotEqual(_endIndex, _position)
|
expectNotEqual(endIndex, position)
|
||||||
return MinimalForwardIndex(position: _position + 1, endIndex: _endIndex)
|
return MinimalForwardIndex(position: position + 1, endIndex: endIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal var _position: Int
|
public let position: Int
|
||||||
internal var _endIndex: Int
|
public let endIndex: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
public func == (lhs: MinimalForwardIndex, rhs: MinimalForwardIndex) -> Bool {
|
public func == (lhs: MinimalForwardIndex, rhs: MinimalForwardIndex) -> Bool {
|
||||||
return lhs._position == rhs._position
|
return lhs.position == rhs.position
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@@ -1929,33 +2232,33 @@ public func == (lhs: MinimalForwardIndex, rhs: MinimalForwardIndex) -> Bool {
|
|||||||
|
|
||||||
public struct MinimalBidirectionalIndex : BidirectionalIndexType {
|
public struct MinimalBidirectionalIndex : BidirectionalIndexType {
|
||||||
public init(position: Int, startIndex: Int, endIndex: Int) {
|
public init(position: Int, startIndex: Int, endIndex: Int) {
|
||||||
self._position = position
|
self.position = position
|
||||||
self._startIndex = startIndex
|
self.startIndex = startIndex
|
||||||
self._endIndex = endIndex
|
self.endIndex = endIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
public func successor() -> MinimalBidirectionalIndex {
|
public func successor() -> MinimalBidirectionalIndex {
|
||||||
expectNotEqual(_endIndex, _position)
|
expectNotEqual(endIndex, position)
|
||||||
return MinimalBidirectionalIndex(
|
return MinimalBidirectionalIndex(
|
||||||
position: _position + 1, startIndex: _startIndex, endIndex: _endIndex)
|
position: position + 1, startIndex: startIndex, endIndex: endIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func predecessor() -> MinimalBidirectionalIndex {
|
public func predecessor() -> MinimalBidirectionalIndex {
|
||||||
expectNotEqual(_startIndex, _position)
|
expectNotEqual(startIndex, position)
|
||||||
return MinimalBidirectionalIndex(
|
return MinimalBidirectionalIndex(
|
||||||
position: _position - 1, startIndex: _startIndex, endIndex: _endIndex)
|
position: position - 1, startIndex: startIndex, endIndex: endIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal var _position: Int
|
public let position: Int
|
||||||
internal var _startIndex: Int
|
public let startIndex: Int
|
||||||
internal var _endIndex: Int
|
public let endIndex: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
public func == (
|
public func == (
|
||||||
lhs: MinimalBidirectionalIndex,
|
lhs: MinimalBidirectionalIndex,
|
||||||
rhs: MinimalBidirectionalIndex
|
rhs: MinimalBidirectionalIndex
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
return lhs._position == rhs._position
|
return lhs.position == rhs.position
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@@ -1964,46 +2267,46 @@ public func == (
|
|||||||
|
|
||||||
public struct MinimalRandomAccessIndex : RandomAccessIndexType {
|
public struct MinimalRandomAccessIndex : RandomAccessIndexType {
|
||||||
public init(position: Int, startIndex: Int, endIndex: Int) {
|
public init(position: Int, startIndex: Int, endIndex: Int) {
|
||||||
self._position = position
|
self.position = position
|
||||||
self._startIndex = startIndex
|
self.startIndex = startIndex
|
||||||
self._endIndex = endIndex
|
self.endIndex = endIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
public func successor() -> MinimalRandomAccessIndex {
|
public func successor() -> MinimalRandomAccessIndex {
|
||||||
expectNotEqual(_endIndex, _position)
|
expectNotEqual(endIndex, position)
|
||||||
return MinimalRandomAccessIndex(
|
return MinimalRandomAccessIndex(
|
||||||
position: _position + 1, startIndex: _startIndex, endIndex: _endIndex)
|
position: position + 1, startIndex: startIndex, endIndex: endIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func predecessor() -> MinimalRandomAccessIndex {
|
public func predecessor() -> MinimalRandomAccessIndex {
|
||||||
expectNotEqual(_startIndex, _position)
|
expectNotEqual(startIndex, position)
|
||||||
return MinimalRandomAccessIndex(
|
return MinimalRandomAccessIndex(
|
||||||
position: _position - 1, startIndex: _startIndex, endIndex: _endIndex)
|
position: position - 1, startIndex: startIndex, endIndex: endIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func distanceTo(other: MinimalRandomAccessIndex) -> Int {
|
public func distanceTo(other: MinimalRandomAccessIndex) -> Int {
|
||||||
return other._position - _position
|
return other.position - position
|
||||||
}
|
}
|
||||||
|
|
||||||
public func advancedBy(n: Int) -> MinimalRandomAccessIndex {
|
public func advancedBy(n: Int) -> MinimalRandomAccessIndex {
|
||||||
expectNotEqual(_endIndex, _position)
|
expectNotEqual(endIndex, position)
|
||||||
let newPosition = _position + n
|
let newPosition = position + n
|
||||||
expectLE(_startIndex, newPosition)
|
expectLE(startIndex, newPosition)
|
||||||
expectGE(_endIndex, newPosition)
|
expectGE(endIndex, newPosition)
|
||||||
return MinimalRandomAccessIndex(
|
return MinimalRandomAccessIndex(
|
||||||
position: newPosition, startIndex: _startIndex, endIndex: _endIndex)
|
position: newPosition, startIndex: startIndex, endIndex: endIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal var _position: Int
|
public let position: Int
|
||||||
internal var _startIndex: Int
|
public let startIndex: Int
|
||||||
internal var _endIndex: Int
|
public let endIndex: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
public func == (
|
public func == (
|
||||||
lhs: MinimalRandomAccessIndex,
|
lhs: MinimalRandomAccessIndex,
|
||||||
rhs: MinimalRandomAccessIndex
|
rhs: MinimalRandomAccessIndex
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
return lhs._position == rhs._position
|
return lhs.position == rhs.position
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@@ -2014,20 +2317,20 @@ public func == (
|
|||||||
% Self = 'Minimal%sCollection' % traversal
|
% Self = 'Minimal%sCollection' % traversal
|
||||||
% Index = 'Minimal%sIndex' % traversal
|
% Index = 'Minimal%sIndex' % traversal
|
||||||
|
|
||||||
/// A minimal implementation of CollectionType with extra checks.
|
/// A minimal implementation of `CollectionType` with extra checks.
|
||||||
public struct ${Self}<T> : CollectionType {
|
public struct ${Self}<T> : CollectionType {
|
||||||
public init<S : SequenceType where S.Generator.Element == T>(
|
public init<S : SequenceType where S.Generator.Element == T>(
|
||||||
_ s: S,
|
_ s: S,
|
||||||
underestimatedCount: UnderestimateCountBehavior = .Value(0)
|
underestimatedCount: UnderestimateCountBehavior = .Value(0)
|
||||||
) {
|
) {
|
||||||
self._data = Array(s)
|
self._elements = Array(s)
|
||||||
|
|
||||||
switch underestimatedCount {
|
switch underestimatedCount {
|
||||||
case .Precise:
|
case .Precise:
|
||||||
self.underestimatedCount = _data.count
|
self.underestimatedCount = _elements.count
|
||||||
|
|
||||||
case .Overestimate:
|
case .Overestimate:
|
||||||
self.underestimatedCount = _data.count * 3 + 5
|
self.underestimatedCount = _elements.count * 3 + 5
|
||||||
|
|
||||||
case .Value(let count):
|
case .Value(let count):
|
||||||
self.underestimatedCount = count
|
self.underestimatedCount = count
|
||||||
@@ -2035,25 +2338,151 @@ public struct ${Self}<T> : CollectionType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func generate() -> MinimalGenerator<T> {
|
public func generate() -> MinimalGenerator<T> {
|
||||||
return MinimalGenerator(_data)
|
return MinimalGenerator(_elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
public var startIndex: ${Index} {
|
public var startIndex: ${Index} {
|
||||||
return ${Index}(position: 0, startIndex: 0, endIndex: _data.endIndex)
|
return ${Index}(
|
||||||
|
position: 0,
|
||||||
|
startIndex: 0,
|
||||||
|
endIndex: _elements.endIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
public var endIndex: ${Index} {
|
public var endIndex: ${Index} {
|
||||||
return ${Index}(
|
return ${Index}(
|
||||||
position: _data.endIndex, startIndex: 0, endIndex: _data.endIndex)
|
position: _elements.endIndex,
|
||||||
|
startIndex: 0,
|
||||||
|
endIndex: _elements.endIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
public subscript(i: ${Index}) -> T {
|
public subscript(i: ${Index}) -> T {
|
||||||
return _data[i._position]
|
return _elements[i.position]
|
||||||
}
|
}
|
||||||
|
|
||||||
public var underestimatedCount: Int
|
public var underestimatedCount: Int
|
||||||
|
|
||||||
internal let _data: [T]
|
internal let _elements: [T]
|
||||||
|
}
|
||||||
|
|
||||||
|
public func ~> <T> (
|
||||||
|
c: ${Self}<T>, _: (_UnderestimateCount, ())
|
||||||
|
) -> Int {
|
||||||
|
return c.underestimatedCount
|
||||||
|
}
|
||||||
|
|
||||||
|
%end
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Minimal***RangeReplaceableCollectionType
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
%for traversal in [ 'Forward', 'Bidirectional', 'RandomAccess' ]:
|
||||||
|
% Self = 'Minimal%sRangeReplaceableCollectionType' % traversal
|
||||||
|
% Index = 'Minimal%sIndex' % traversal
|
||||||
|
|
||||||
|
/// A minimal implementation of `RangeReplaceableCollectionType` with extra
|
||||||
|
/// checks.
|
||||||
|
public struct ${Self}<T> : RangeReplaceableCollectionType {
|
||||||
|
|
||||||
|
public init<S : SequenceType where S.Generator.Element == T>(
|
||||||
|
_ s: S,
|
||||||
|
underestimatedCount: UnderestimateCountBehavior = .Value(0)
|
||||||
|
) {
|
||||||
|
self.elements = Array(s)
|
||||||
|
|
||||||
|
switch underestimatedCount {
|
||||||
|
case .Precise:
|
||||||
|
self.underestimatedCount = elements.count
|
||||||
|
|
||||||
|
case .Overestimate:
|
||||||
|
self.underestimatedCount = elements.count * 3 + 5
|
||||||
|
|
||||||
|
case .Value(let count):
|
||||||
|
self.underestimatedCount = count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
self.underestimatedCount = 0
|
||||||
|
self.elements = []
|
||||||
|
}
|
||||||
|
|
||||||
|
public func generate() -> MinimalGenerator<T> {
|
||||||
|
return MinimalGenerator(elements)
|
||||||
|
}
|
||||||
|
|
||||||
|
public var startIndex: ${Index} {
|
||||||
|
return ${Index}(
|
||||||
|
position: 0,
|
||||||
|
startIndex: 0,
|
||||||
|
endIndex: elements.endIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
public var endIndex: ${Index} {
|
||||||
|
return ${Index}(
|
||||||
|
position: elements.endIndex,
|
||||||
|
startIndex: 0,
|
||||||
|
endIndex: elements.endIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
public subscript(i: ${Index}) -> T {
|
||||||
|
return elements[i.position]
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func reserveCapacity(n: Int) {
|
||||||
|
elements.reserveCapacity(n)
|
||||||
|
reservedCapacity = max(reservedCapacity, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func append(x: T) {
|
||||||
|
elements.append(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func extend<
|
||||||
|
S : SequenceType where S.Generator.Element == T
|
||||||
|
>(newElements: S) {
|
||||||
|
elements.extend(newElements)
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func replaceRange<
|
||||||
|
C : CollectionType where C.Generator.Element == T
|
||||||
|
>(
|
||||||
|
subRange: Range<${Index}>, with newElements: C
|
||||||
|
) {
|
||||||
|
elements.replaceRange(
|
||||||
|
subRange.startIndex.position..<subRange.endIndex.position,
|
||||||
|
with: newElements)
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func insert(newElement: T, atIndex i: ${Index}) {
|
||||||
|
elements.insert(newElement, atIndex: i.position)
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func splice<
|
||||||
|
S : CollectionType where S.Generator.Element == T
|
||||||
|
>(newElements: S, atIndex i: ${Index}) {
|
||||||
|
elements.splice(newElements, atIndex: i.position)
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func removeAtIndex(i: ${Index}) -> T {
|
||||||
|
return elements.removeAtIndex(i.position)
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func removeRange(subRange: Range<${Index}>) {
|
||||||
|
elements.removeRange(
|
||||||
|
subRange.startIndex.position..<subRange.endIndex.position
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func removeAll(keepCapacity: Bool = false) {
|
||||||
|
// Ignore the value of `keepCapacity`.
|
||||||
|
elements.removeAll(keepCapacity: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
public var underestimatedCount: Int
|
||||||
|
public var reservedCapacity: Int = 0
|
||||||
|
|
||||||
|
public var elements: [T]
|
||||||
}
|
}
|
||||||
|
|
||||||
public func ~> <T> (
|
public func ~> <T> (
|
||||||
|
|||||||
@@ -16,12 +16,8 @@ public func minElement<
|
|||||||
R : SequenceType
|
R : SequenceType
|
||||||
where R.Generator.Element : Comparable>(elements: R)
|
where R.Generator.Element : Comparable>(elements: R)
|
||||||
-> R.Generator.Element {
|
-> R.Generator.Element {
|
||||||
var g = elements.generate()
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
var result = g.next()!
|
return elements._prext_minElement()!
|
||||||
for e in GeneratorSequence(g) {
|
|
||||||
if e < result { result = e }
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the maximum element in `elements`. Requires:
|
/// Returns the maximum element in `elements`. Requires:
|
||||||
@@ -30,12 +26,8 @@ public func maxElement<
|
|||||||
R : SequenceType
|
R : SequenceType
|
||||||
where R.Generator.Element : Comparable>(elements: R)
|
where R.Generator.Element : Comparable>(elements: R)
|
||||||
-> R.Generator.Element {
|
-> R.Generator.Element {
|
||||||
var g = elements.generate()
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
var result = g.next()!
|
return elements._prext_maxElement()!
|
||||||
for e in GeneratorSequence(g) {
|
|
||||||
if e > result { result = e }
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the first index where `value` appears in `domain` or `nil` if
|
/// Returns the first index where `value` appears in `domain` or `nil` if
|
||||||
@@ -45,12 +37,8 @@ public func maxElement<
|
|||||||
public func find<
|
public func find<
|
||||||
C: CollectionType where C.Generator.Element : Equatable
|
C: CollectionType where C.Generator.Element : Equatable
|
||||||
>(domain: C, value: C.Generator.Element) -> C.Index? {
|
>(domain: C, value: C.Generator.Element) -> C.Index? {
|
||||||
for i in indices(domain) {
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
if domain[i] == value {
|
return domain._prext_find(value)
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the lesser of `x` and `y`
|
/// Return the lesser of `x` and `y`
|
||||||
@@ -167,16 +155,8 @@ public func startsWith<
|
|||||||
S0.Generator.Element : Equatable
|
S0.Generator.Element : Equatable
|
||||||
>(s: S0, prefix: S1) -> Bool
|
>(s: S0, prefix: S1) -> Bool
|
||||||
{
|
{
|
||||||
var prefixGenerator = prefix.generate()
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
return s._prext_startsWith(prefix)
|
||||||
for e0 in s {
|
|
||||||
var e1 = prefixGenerator.next()
|
|
||||||
if e1 == nil { return true }
|
|
||||||
if e0 != e1! {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return prefixGenerator.next() != nil ? false : true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true iff `s` begins with elements equivalent to those of
|
/// Return true iff `s` begins with elements equivalent to those of
|
||||||
@@ -192,16 +172,8 @@ public func startsWith<
|
|||||||
@noescape isEquivalent: (S1.Generator.Element, S1.Generator.Element) -> Bool)
|
@noescape isEquivalent: (S1.Generator.Element, S1.Generator.Element) -> Bool)
|
||||||
-> Bool
|
-> Bool
|
||||||
{
|
{
|
||||||
var prefixGenerator = prefix.generate()
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
return s._prext_startsWith(prefix, isEquivalent: isEquivalent)
|
||||||
for e0 in s {
|
|
||||||
var e1 = prefixGenerator.next()
|
|
||||||
if e1 == nil { return true }
|
|
||||||
if !isEquivalent(e0, e1!) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return prefixGenerator.next() != nil ? false : true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The `GeneratorType` for `EnumerateSequence`. `EnumerateGenerator`
|
/// The `GeneratorType` for `EnumerateSequence`. `EnumerateGenerator`
|
||||||
@@ -290,7 +262,8 @@ public struct EnumerateSequence<Base : SequenceType> : SequenceType {
|
|||||||
public func enumerate<Seq : SequenceType>(
|
public func enumerate<Seq : SequenceType>(
|
||||||
base: Seq
|
base: Seq
|
||||||
) -> EnumerateSequence<Seq> {
|
) -> EnumerateSequence<Seq> {
|
||||||
return EnumerateSequence(base)
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
return base._prext_enumerate()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` iff `a1` and `a2` contain the same elements in the
|
/// Return `true` iff `a1` and `a2` contain the same elements in the
|
||||||
@@ -300,22 +273,9 @@ public func equal<
|
|||||||
where
|
where
|
||||||
S1.Generator.Element == S2.Generator.Element,
|
S1.Generator.Element == S2.Generator.Element,
|
||||||
S1.Generator.Element : Equatable
|
S1.Generator.Element : Equatable
|
||||||
>(a1: S1, a2: S2) -> Bool
|
>(a1: S1, a2: S2) -> Bool {
|
||||||
{
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
var g1 = a1.generate()
|
return a1._prext_equalElements(a2)
|
||||||
var g2 = a2.generate()
|
|
||||||
while true {
|
|
||||||
var e1 = g1.next()
|
|
||||||
var e2 = g2.next()
|
|
||||||
if (e1 != nil) && (e2 != nil) {
|
|
||||||
if e1! != e2! {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return (e1 == nil) == (e2 == nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true iff `a1` and `a2` contain equivalent elements, using
|
/// Return true iff `a1` and `a2` contain equivalent elements, using
|
||||||
@@ -328,22 +288,9 @@ public func equal<
|
|||||||
S1.Generator.Element == S2.Generator.Element
|
S1.Generator.Element == S2.Generator.Element
|
||||||
>(a1: S1, a2: S2,
|
>(a1: S1, a2: S2,
|
||||||
@noescape isEquivalent: (S1.Generator.Element, S1.Generator.Element) -> Bool)
|
@noescape isEquivalent: (S1.Generator.Element, S1.Generator.Element) -> Bool)
|
||||||
-> Bool
|
-> Bool {
|
||||||
{
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
var g1 = a1.generate()
|
return a1._prext_equalElements(a2, isEquivalent: isEquivalent)
|
||||||
var g2 = a2.generate()
|
|
||||||
while true {
|
|
||||||
var e1 = g1.next()
|
|
||||||
var e2 = g2.next()
|
|
||||||
if (e1 != nil) && (e2 != nil) {
|
|
||||||
if !isEquivalent(e1!, e2!) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return (e1 == nil) == (e2 == nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true iff a1 precedes a2 in a lexicographical ("dictionary")
|
/// Return true iff a1 precedes a2 in a lexicographical ("dictionary")
|
||||||
@@ -354,26 +301,8 @@ public func lexicographicalCompare<
|
|||||||
S1.Generator.Element == S2.Generator.Element,
|
S1.Generator.Element == S2.Generator.Element,
|
||||||
S1.Generator.Element : Comparable>(
|
S1.Generator.Element : Comparable>(
|
||||||
a1: S1, a2: S2) -> Bool {
|
a1: S1, a2: S2) -> Bool {
|
||||||
var g1 = a1.generate()
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
var g2 = a2.generate()
|
return a1._prext_lexicographicalCompare(a2)
|
||||||
while true {
|
|
||||||
var e1_ = g1.next()
|
|
||||||
var e2_ = g2.next()
|
|
||||||
if let e1? = e1_ {
|
|
||||||
if let e2? = e2_ {
|
|
||||||
if e1 < e2 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if e2 < e1 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
continue // equivalent
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return e2_ != nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true iff `a1` precedes `a2` in a lexicographical ("dictionary")
|
/// Return true iff `a1` precedes `a2` in a lexicographical ("dictionary")
|
||||||
@@ -391,44 +320,24 @@ public func lexicographicalCompare<
|
|||||||
@noescape isOrderedBefore less: (S1.Generator.Element, S1.Generator.Element)
|
@noescape isOrderedBefore less: (S1.Generator.Element, S1.Generator.Element)
|
||||||
-> Bool
|
-> Bool
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
var g1 = a1.generate()
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
var g2 = a2.generate()
|
return a1._prext_lexicographicalCompare(a2, isOrderedBefore: less)
|
||||||
while true {
|
|
||||||
var e1_ = g1.next()
|
|
||||||
var e2_ = g2.next()
|
|
||||||
if let e1? = e1_ {
|
|
||||||
if let e2? = e2_ {
|
|
||||||
if less(e1, e2) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if less(e2, e1) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
continue // equivalent
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return e2_ != nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` iff an element in `seq` satisfies `predicate`.
|
/// Return `true` iff an element in `seq` satisfies `predicate`.
|
||||||
public func contains<
|
public func contains<
|
||||||
S : SequenceType, L : BooleanType
|
S : SequenceType, L : BooleanType
|
||||||
>(seq: S, @noescape predicate: (S.Generator.Element) -> L) -> Bool {
|
>(seq: S, @noescape predicate: (S.Generator.Element) -> L) -> Bool {
|
||||||
for a in seq {
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
if predicate(a) {
|
return seq._prext_contains({ predicate($0).boolValue })
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` iff `x` is in `seq`.
|
/// Return `true` iff `x` is in `seq`.
|
||||||
public func contains<
|
public func contains<
|
||||||
S : SequenceType where S.Generator.Element : Equatable
|
S : SequenceType where S.Generator.Element : Equatable
|
||||||
>(seq: S, x: S.Generator.Element) -> Bool {
|
>(seq: S, x: S.Generator.Element) -> Bool {
|
||||||
return contains(seq, { $0 == x })
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
return seq._prext_contains(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the result of repeatedly calling `combine` with an
|
/// Return the result of repeatedly calling `combine` with an
|
||||||
@@ -437,9 +346,6 @@ public func contains<
|
|||||||
public func reduce<S : SequenceType, U>(
|
public func reduce<S : SequenceType, U>(
|
||||||
sequence: S, initial: U, @noescape combine: (U, S.Generator.Element) -> U
|
sequence: S, initial: U, @noescape combine: (U, S.Generator.Element) -> U
|
||||||
) -> U {
|
) -> U {
|
||||||
var result = initial
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
for element in sequence {
|
return sequence._prext_reduce(initial, combine: combine)
|
||||||
result = combine(result, element)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -494,16 +494,23 @@ extension ${Self} : _ArrayType {
|
|||||||
|
|
||||||
/// `true` if and only if the `${Self}` is empty
|
/// `true` if and only if the `${Self}` is empty
|
||||||
public var isEmpty: Bool {
|
public var isEmpty: Bool {
|
||||||
return count == 0
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
return self._prext_isEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The first element, or `nil` if the array is empty
|
/// The first element, or `nil` if the array is empty
|
||||||
public var first: Element? {
|
public var first: Element? {
|
||||||
return Swift.first(self)
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
return self._prext_first
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The last element, or `nil` if the array is empty
|
/// The last element, or `nil` if the array is empty
|
||||||
public var last: Element? {
|
public var last: Element? {
|
||||||
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
|
||||||
|
// FIXME: we can't use the commented-out code because the optimizer
|
||||||
|
// crashes. <rdar://problem/20514925> Optimizer crashes [...]
|
||||||
|
// return self._prext_last
|
||||||
return Swift.last(self)
|
return Swift.last(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -656,7 +663,8 @@ extension ${Self} : _ArrayType {
|
|||||||
/// `combine(combine(...combine(combine(initial, self[0]),
|
/// `combine(combine(...combine(combine(initial, self[0]),
|
||||||
/// self[1]),...self[count-2]), self[count-1])`.
|
/// self[1]),...self[count-2]), self[count-1])`.
|
||||||
public func reduce<U>(initial: U, @noescape combine: (U, T) -> U) -> U {
|
public func reduce<U>(initial: U, @noescape combine: (U, T) -> U) -> U {
|
||||||
return Swift.reduce(self, initial, combine)
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
return self._prext_reduce(initial, combine: combine)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sort `self` in-place according to `isOrderedBefore`. Requires:
|
/// Sort `self` in-place according to `isOrderedBefore`. Requires:
|
||||||
@@ -684,34 +692,28 @@ extension ${Self} : _ArrayType {
|
|||||||
/// Return ${a_Self} containing the results of calling
|
/// Return ${a_Self} containing the results of calling
|
||||||
/// `transform(x)` on each element `x` of `self`
|
/// `transform(x)` on each element `x` of `self`
|
||||||
public func map<U>(transform: (T) -> U) -> ${Self}<U> {
|
public func map<U>(transform: (T) -> U) -> ${Self}<U> {
|
||||||
// Should call Swift.map here, but there's a compiler bug:
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
// <rdar://problem/19763792> Calling Swift.map from Array.map causes
|
return ${Self}<U>(self._prext_map(transform))
|
||||||
// Assertion failed: UnresolvedDot in wrong phase
|
|
||||||
return ${Self}<U>(lazy(self).map(transform))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return ${a_Self} containing the results of calling
|
/// Return ${a_Self} containing the results of calling
|
||||||
/// `transform(x)` on each element `x` of `self` and flattening the result.
|
/// `transform(x)` on each element `x` of `self` and flattening the result.
|
||||||
public func flatMap<U>(@noescape transform: (T) -> ${Self}<U>) -> ${Self}<U> {
|
public func flatMap<U>(@noescape transform: (T) -> ${Self}<U>) -> ${Self}<U> {
|
||||||
var result: ${Self}<U> = []
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
for element in self {
|
return ${Self}<U>(self._prext_flatMap(transform))
|
||||||
result.extend(transform(element))
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A ${Self} containing the elements of `self` in reverse order
|
/// A ${Self} containing the elements of `self` in reverse order
|
||||||
public func reverse() -> ${Self} {
|
public func reverse() -> ${Self} {
|
||||||
return ${Self}(lazy(self).reverse())
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
return ${Self}(self._prext_reverse())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return ${a_Self} containing the elements `x` of `self` for which
|
/// Return ${a_Self} containing the elements `x` of `self` for which
|
||||||
/// `includeElement(x)` is `true`
|
/// `includeElement(x)` is `true`
|
||||||
public func filter(includeElement: (T) -> Bool) -> ${Self} {
|
public func filter(includeElement: (T) -> Bool) -> ${Self} {
|
||||||
// Should call Swift.filter() here, but there's a compiler bug:
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
// <rdar://problem/19763792> Calling Swift.map from Array.map causes
|
return self._prext_filter(includeElement)
|
||||||
// Assertion failed: UnresolvedDot in wrong phase
|
|
||||||
return ${Self}(lazy(self).filter(includeElement))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ set(SWIFTLIB_ESSENTIAL
|
|||||||
OutputStream.swift
|
OutputStream.swift
|
||||||
Pointer.swift
|
Pointer.swift
|
||||||
Policy.swift
|
Policy.swift
|
||||||
|
ProtocolExtensions.swift.gyb
|
||||||
REPL.swift
|
REPL.swift
|
||||||
Range.swift
|
Range.swift
|
||||||
RangeMirrors.swift.gyb
|
RangeMirrors.swift.gyb
|
||||||
|
|||||||
@@ -66,6 +66,12 @@ public protocol _CollectionType : _SequenceType {
|
|||||||
subscript(_i: Index) -> _Element {get}
|
subscript(_i: Index) -> _Element {get}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public protocol _CollectionDefaultsType : _CollectionType {
|
||||||
|
}
|
||||||
|
|
||||||
|
extension _CollectionDefaultsType {
|
||||||
|
}
|
||||||
|
|
||||||
/// A multi-pass *sequence* with addressable positions.
|
/// A multi-pass *sequence* with addressable positions.
|
||||||
///
|
///
|
||||||
/// Positions are represented by an associated `Index` type. Whereas
|
/// Positions are represented by an associated `Index` type. Whereas
|
||||||
@@ -80,13 +86,15 @@ public protocol _CollectionType : _SequenceType {
|
|||||||
/// for i in startIndex..<endIndex {
|
/// for i in startIndex..<endIndex {
|
||||||
/// let x = self[i]
|
/// let x = self[i]
|
||||||
/// }
|
/// }
|
||||||
public protocol CollectionType : _CollectionType, SequenceType {
|
public protocol CollectionType
|
||||||
|
: _CollectionType, _CollectionDefaultsType, SequenceType {
|
||||||
|
|
||||||
/// Access the element indicated by `position`.
|
/// Access the element indicated by `position`.
|
||||||
///
|
///
|
||||||
/// Requires: `position` indicates a valid position in `self` and
|
/// Requires: `position` indicates a valid position in `self` and
|
||||||
/// `position != endIndex`.
|
/// `position != endIndex`.
|
||||||
subscript(position: Index) -> Generator.Element {get}
|
subscript(position: Index) -> Generator.Element {get}
|
||||||
|
|
||||||
// Do not use this operator directly; call `count(x)` instead
|
// Do not use this operator directly; call `count(x)` instead
|
||||||
func ~> (_:Self, _:(_Count, ())) -> Index.Distance
|
func ~> (_:Self, _:(_Count, ())) -> Index.Distance
|
||||||
}
|
}
|
||||||
@@ -124,12 +132,14 @@ public func ~> <T : _CollectionType, R>(
|
|||||||
|
|
||||||
/// Returns `true` iff `x` is empty.
|
/// Returns `true` iff `x` is empty.
|
||||||
public func isEmpty<C: CollectionType>(x: C) -> Bool {
|
public func isEmpty<C: CollectionType>(x: C) -> Bool {
|
||||||
return x.startIndex == x.endIndex
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
return x._prext_isEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the first element of `x`, or `nil` if `x` is empty.
|
/// Returns the first element of `x`, or `nil` if `x` is empty.
|
||||||
public func first<C: CollectionType>(x: C) -> C.Generator.Element? {
|
public func first<C: CollectionType>(x: C) -> C.Generator.Element? {
|
||||||
return isEmpty(x) ? nil : x[x.startIndex]
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
return x._prext_first
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the last element of `x`, or `nil` if `x` is empty.
|
/// Returns the last element of `x`, or `nil` if `x` is empty.
|
||||||
@@ -213,7 +223,8 @@ public struct IndexingGenerator<
|
|||||||
/// all valid subscript arguments for `x`, omitting its `endIndex`.
|
/// all valid subscript arguments for `x`, omitting its `endIndex`.
|
||||||
public func indices<
|
public func indices<
|
||||||
C : CollectionType>(x: C) -> Range<C.Index> {
|
C : CollectionType>(x: C) -> Range<C.Index> {
|
||||||
return Range(start: x.startIndex, end: x.endIndex)
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
return x._prext_indices
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A *generator* that adapts a *collection* `C` and any *sequence* of
|
/// A *generator* that adapts a *collection* `C` and any *sequence* of
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public protocol _SequenceType {
|
|||||||
///
|
///
|
||||||
/// Its requirements are inherited by `SequenceType` and thus must
|
/// Its requirements are inherited by `SequenceType` and thus must
|
||||||
/// be satisfied by types conforming to that protocol.
|
/// be satisfied by types conforming to that protocol.
|
||||||
public protocol _Sequence_Type : _SequenceType {
|
public protocol _Sequence_Type : _SequenceType, _SequenceDefaultsType {
|
||||||
/// A type whose instances can produce the elements of this
|
/// A type whose instances can produce the elements of this
|
||||||
/// sequence, in order.
|
/// sequence, in order.
|
||||||
typealias Generator : GeneratorType
|
typealias Generator : GeneratorType
|
||||||
@@ -79,6 +79,25 @@ public protocol _Sequence_Type : _SequenceType {
|
|||||||
func generate() -> Generator
|
func generate() -> Generator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public protocol _SequenceDefaultsType {
|
||||||
|
/// A type that provides the *sequence*\ 's iteration interface and
|
||||||
|
/// encapsulates its iteration state.
|
||||||
|
typealias Generator : GeneratorType
|
||||||
|
|
||||||
|
/// Return a *generator* over the elements of this *sequence*. The
|
||||||
|
/// *generator*\ 's next element is the first element of the
|
||||||
|
/// sequence.
|
||||||
|
///
|
||||||
|
/// Complexity: O(1)
|
||||||
|
func generate() -> Generator
|
||||||
|
}
|
||||||
|
|
||||||
|
extension _SequenceDefaultsType {
|
||||||
|
}
|
||||||
|
|
||||||
|
extension _SequenceDefaultsType {
|
||||||
|
}
|
||||||
|
|
||||||
/// A type that can be iterated with a `for`\ ...\ `in` loop.
|
/// A type that can be iterated with a `for`\ ...\ `in` loop.
|
||||||
///
|
///
|
||||||
/// `SequenceType` makes no requirement on conforming types regarding
|
/// `SequenceType` makes no requirement on conforming types regarding
|
||||||
|
|||||||
@@ -172,7 +172,8 @@ public struct FilterCollectionView<Base : CollectionType> : CollectionType {
|
|||||||
public func filter<S : SequenceType>(
|
public func filter<S : SequenceType>(
|
||||||
source: S, includeElement: (S.Generator.Element) -> Bool
|
source: S, includeElement: (S.Generator.Element) -> Bool
|
||||||
) -> [S.Generator.Element] {
|
) -> [S.Generator.Element] {
|
||||||
return lazy(source).filter(includeElement).array
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
return source._prext_filter(includeElement)
|
||||||
}
|
}
|
||||||
|
|
||||||
% traversals = ('Forward', 'Bidirectional', 'RandomAccess')
|
% traversals = ('Forward', 'Bidirectional', 'RandomAccess')
|
||||||
@@ -200,6 +201,7 @@ extension ${Self} {
|
|||||||
public func filter<C : CollectionType>(
|
public func filter<C : CollectionType>(
|
||||||
source: C, includeElement: (C.Generator.Element)->Bool
|
source: C, includeElement: (C.Generator.Element)->Bool
|
||||||
) -> FilterCollectionView<C> {
|
) -> FilterCollectionView<C> {
|
||||||
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
return FilterCollectionView(_base: source, _include: includeElement)
|
return FilterCollectionView(_base: source, _include: includeElement)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public struct MapSequenceView<Base : SequenceType, T> : SequenceType {
|
|||||||
return MapSequenceGenerator(
|
return MapSequenceGenerator(
|
||||||
_base: _base.generate(), _transform: _transform)
|
_base: _base.generate(), _transform: _transform)
|
||||||
}
|
}
|
||||||
|
|
||||||
var _base: Base
|
var _base: Base
|
||||||
var _transform: (Base.Generator.Element)->T
|
var _transform: (Base.Generator.Element)->T
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,8 @@ public func ~> <Base : SequenceType, T> (
|
|||||||
public func map<S : SequenceType, T>(
|
public func map<S : SequenceType, T>(
|
||||||
source: S, transform: (S.Generator.Element) -> T
|
source: S, transform: (S.Generator.Element) -> T
|
||||||
) -> [T] {
|
) -> [T] {
|
||||||
return lazy(source).map(transform).array
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
return source._prext_map(transform)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return an `Array` containing the results of mapping `transform`
|
/// Return an `Array` containing the results of mapping `transform`
|
||||||
@@ -78,11 +79,8 @@ public func map<S : SequenceType, T>(
|
|||||||
public func flatMap<S : SequenceType, T>(
|
public func flatMap<S : SequenceType, T>(
|
||||||
source: S, @noescape transform: (S.Generator.Element) -> [T]
|
source: S, @noescape transform: (S.Generator.Element) -> [T]
|
||||||
) -> [T] {
|
) -> [T] {
|
||||||
var result: [T] = []
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
for element in source {
|
return source._prext_flatMap(transform)
|
||||||
result.extend(transform(element))
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===--- Collections ------------------------------------------------------===//
|
//===--- Collections ------------------------------------------------------===//
|
||||||
@@ -138,7 +136,8 @@ public func ~> <Base: CollectionType, T> (
|
|||||||
public func map<C : CollectionType, T>(
|
public func map<C : CollectionType, T>(
|
||||||
source: C, transform: (C.Generator.Element) -> T
|
source: C, transform: (C.Generator.Element) -> T
|
||||||
) -> [T] {
|
) -> [T] {
|
||||||
return lazy(source).map(transform).array
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
return source._prext_map(transform)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return an `Array` containing the results of mapping `transform`
|
/// Return an `Array` containing the results of mapping `transform`
|
||||||
@@ -146,11 +145,8 @@ public func map<C : CollectionType, T>(
|
|||||||
public func flatMap<C : CollectionType, T>(
|
public func flatMap<C : CollectionType, T>(
|
||||||
source: C, transform: (C.Generator.Element) -> [T]
|
source: C, transform: (C.Generator.Element) -> [T]
|
||||||
) -> [T] {
|
) -> [T] {
|
||||||
var result: [T] = []
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
for elements in map(source, transform) {
|
return source._prext_flatMap(transform)
|
||||||
result.extend(elements)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===--- Support for lazy(s) ----------------------------------------------===//
|
//===--- Support for lazy(s) ----------------------------------------------===//
|
||||||
|
|||||||
527
stdlib/public/core/ProtocolExtensions.swift.gyb
Normal file
527
stdlib/public/core/ProtocolExtensions.swift.gyb
Normal file
@@ -0,0 +1,527 @@
|
|||||||
|
//===--- ProtocolExtensions.swift.gyb -------------------------------------===//
|
||||||
|
//
|
||||||
|
// This source file is part of the Swift.org open source project
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
||||||
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||||
|
//
|
||||||
|
// See http://swift.org/LICENSE.txt for license information
|
||||||
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
%{
|
||||||
|
|
||||||
|
# We know we will eventually get a SequenceType.Element type. Define
|
||||||
|
# a shorthand that we can use today.
|
||||||
|
GElement = "Generator.Element"
|
||||||
|
|
||||||
|
}%
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// enumerate()
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
extension SequenceType {
|
||||||
|
/// Return a lazy `SequenceType` containing pairs (*n*, *x*), where
|
||||||
|
/// *n*\ s are consecutive `Int`\ s starting at zero, and *x*\ s are
|
||||||
|
/// the elements of `base`::
|
||||||
|
///
|
||||||
|
/// > for (n, c) in enumerate("Swift") { println("\(n): '\(c)'" ) }
|
||||||
|
/// 0: 'S'
|
||||||
|
/// 1: 'w'
|
||||||
|
/// 2: 'i'
|
||||||
|
/// 3: 'f'
|
||||||
|
/// 4: 't'
|
||||||
|
final public func _prext_enumerate() -> EnumerateSequence<Self> {
|
||||||
|
return EnumerateSequence(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// minElement(), maxElement()
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
% # Generate two versions: with explicit predicates and with
|
||||||
|
% # a Comparable requirement.
|
||||||
|
% for preds in [ True, False ]:
|
||||||
|
|
||||||
|
extension SequenceType ${"" if preds else "where Self.Generator.Element : Comparable"} {
|
||||||
|
|
||||||
|
/// Returns the minimum element in `self`.
|
||||||
|
///
|
||||||
|
/// Complexity: O(count(elements))
|
||||||
|
% if preds:
|
||||||
|
///
|
||||||
|
/// Requires: `isOrderedBefore` is a `strict weak ordering
|
||||||
|
/// <http://en.wikipedia.org/wiki/Strict_weak_order#Strict_weak_orderings>`__
|
||||||
|
/// over `self`."""
|
||||||
|
% end
|
||||||
|
final public func _prext_minElement(
|
||||||
|
% if preds:
|
||||||
|
@noescape isOrderedBefore: (${GElement}, ${GElement}) -> Bool
|
||||||
|
% end
|
||||||
|
) -> ${GElement}? {
|
||||||
|
var g = generate()
|
||||||
|
if var result? = g.next() {
|
||||||
|
for e in GeneratorSequence(g) {
|
||||||
|
% if preds:
|
||||||
|
if isOrderedBefore(e, result) { result = e }
|
||||||
|
% else:
|
||||||
|
if e < result { result = e }
|
||||||
|
% end
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the maximum element in `self`.
|
||||||
|
///
|
||||||
|
/// Complexity: O(count(elements))
|
||||||
|
% if preds:
|
||||||
|
///
|
||||||
|
/// Requires: `isOrderedBefore` is a `strict weak ordering
|
||||||
|
/// <http://en.wikipedia.org/wiki/Strict_weak_order#Strict_weak_orderings>`__
|
||||||
|
/// over `self`."""
|
||||||
|
% end
|
||||||
|
final public func _prext_maxElement(
|
||||||
|
% if preds:
|
||||||
|
@noescape isOrderedBefore: (${GElement}, ${GElement}) -> Bool
|
||||||
|
% end
|
||||||
|
) -> ${GElement}? {
|
||||||
|
var g = generate()
|
||||||
|
if var result? = g.next() {
|
||||||
|
for e in GeneratorSequence(g) {
|
||||||
|
% if preds:
|
||||||
|
if isOrderedBefore(result, e) { result = e }
|
||||||
|
% else:
|
||||||
|
if e > result { result = e }
|
||||||
|
% end
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
% end
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// startsWith()
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
% # Generate two versions: with explicit predicates and with
|
||||||
|
% # an Equatable requirement.
|
||||||
|
% for preds in [ True, False ]:
|
||||||
|
|
||||||
|
extension SequenceType ${"" if preds else "where Self.Generator.Element : Equatable"} {
|
||||||
|
|
||||||
|
% if preds:
|
||||||
|
/// Return true iff `s` begins with elements equivalent to those of
|
||||||
|
/// `prefix`, using `isEquivalent` as the equivalence test.
|
||||||
|
///
|
||||||
|
/// Requires: `isEquivalent` is an `equivalence relation
|
||||||
|
/// <http://en.wikipedia.org/wiki/Equivalence_relation>`_
|
||||||
|
% else:
|
||||||
|
/// Return true iff the the initial elements of `s` are equal to `prefix`.
|
||||||
|
% end
|
||||||
|
final public func _prext_startsWith<
|
||||||
|
S : SequenceType where S.${GElement} == ${GElement}
|
||||||
|
>(
|
||||||
|
prefix: S${"," if preds else ""}
|
||||||
|
% if preds:
|
||||||
|
@noescape isEquivalent: (${GElement}, ${GElement}) -> Bool
|
||||||
|
% end
|
||||||
|
) -> Bool {
|
||||||
|
var prefixGenerator = prefix.generate()
|
||||||
|
for e0 in self {
|
||||||
|
if let e1? = prefixGenerator.next() {
|
||||||
|
if ${"!isEquivalent(e0, e1)" if preds else "e0 != e1"} {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prefixGenerator.next() != nil ? false : true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
% end
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// equalElements()
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
% # Generate two versions: with explicit predicates and with
|
||||||
|
% # an Equatable requirement.
|
||||||
|
% for preds in [ True, False ]:
|
||||||
|
|
||||||
|
extension SequenceType ${"" if preds else "where Self.Generator.Element : Equatable"} {
|
||||||
|
|
||||||
|
% if preds:
|
||||||
|
/// Return true iff `a1` and `a2` contain equivalent elements, using
|
||||||
|
/// `isEquivalent` as the equivalence test.
|
||||||
|
///
|
||||||
|
/// Requires: `isEquivalent` is an `equivalence relation
|
||||||
|
/// <http://en.wikipedia.org/wiki/Equivalence_relation>`_
|
||||||
|
% else:
|
||||||
|
/// Return `true` iff `self` and `s` contain the same elements in the
|
||||||
|
/// same order.
|
||||||
|
% end
|
||||||
|
final public func _prext_equalElements<
|
||||||
|
S : SequenceType where S.${GElement} == ${GElement}
|
||||||
|
>(
|
||||||
|
s: S${"," if preds else ""}
|
||||||
|
% if preds:
|
||||||
|
@noescape isEquivalent: (${GElement}, ${GElement}) -> Bool
|
||||||
|
% end
|
||||||
|
) -> Bool {
|
||||||
|
var g1 = self.generate()
|
||||||
|
var g2 = s.generate()
|
||||||
|
while true {
|
||||||
|
switch (g1.next(), g2.next()) {
|
||||||
|
case let (e1?, e2?):
|
||||||
|
% if preds:
|
||||||
|
if !isEquivalent(e1, e2) {
|
||||||
|
% else:
|
||||||
|
if e1 != e2 {
|
||||||
|
% end
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case (_?, nil),
|
||||||
|
(nil, _?):
|
||||||
|
return false
|
||||||
|
case (nil, nil):
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
% end
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// lexicographicalCompare()
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
% # Generate two versions: with explicit predicates and with
|
||||||
|
% # Comparable requirement.
|
||||||
|
% for preds in [ True, False ]:
|
||||||
|
|
||||||
|
% if preds:
|
||||||
|
/// Return true iff `a1` precedes `a2` in a lexicographical ("dictionary")
|
||||||
|
/// ordering, using `isOrderedBefore` as the comparison between elements.
|
||||||
|
///
|
||||||
|
/// Requires: isOrderedBefore` is a `strict weak ordering
|
||||||
|
/// <http://en.wikipedia.org/wiki/Strict_weak_order#Strict_weak_orderings>`__
|
||||||
|
/// over the elements of `a1` and `a2`.
|
||||||
|
% else:
|
||||||
|
/// Return true iff a1 precedes a2 in a lexicographical ("dictionary")
|
||||||
|
/// ordering, using "<" as the comparison between elements.
|
||||||
|
% end
|
||||||
|
extension SequenceType ${"" if preds else "where Self.Generator.Element : Comparable"} {
|
||||||
|
final public func _prext_lexicographicalCompare<
|
||||||
|
S : SequenceType where S.${GElement} == ${GElement}
|
||||||
|
>(
|
||||||
|
s: S${"," if preds else ""}
|
||||||
|
% if preds:
|
||||||
|
@noescape isOrderedBefore less: (${GElement}, ${GElement}) -> Bool
|
||||||
|
% end
|
||||||
|
) -> Bool {
|
||||||
|
var g1 = self.generate()
|
||||||
|
var g2 = s.generate()
|
||||||
|
while true {
|
||||||
|
if let e1? = g1.next() {
|
||||||
|
if let e2? = g2.next() {
|
||||||
|
if ${"less(e1, e2)" if preds else "e1 < e2"} {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if ${"less(e2, e1)" if preds else "e2 < e1"} {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
continue // equivalent
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return g2.next() != nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
% end
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// contains()
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
extension SequenceType where Self.Generator.Element : Equatable {
|
||||||
|
/// Return `true` iff `x` is in `self`.
|
||||||
|
final public func _prext_contains(element: ${GElement}) -> Bool {
|
||||||
|
// FIXME: dynamic dispatch for Set and Dictionary.
|
||||||
|
for e in self {
|
||||||
|
if e == element {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SequenceType {
|
||||||
|
/// Return `true` iff an element in `self` satisfies `predicate`.
|
||||||
|
final public func _prext_contains(
|
||||||
|
@noescape predicate: (${GElement}) -> Bool
|
||||||
|
) -> Bool {
|
||||||
|
for e in self {
|
||||||
|
if predicate(e) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// reduce()
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
extension SequenceType {
|
||||||
|
/// Return the result of repeatedly calling `combine` with an
|
||||||
|
/// accumulated value initialized to `initial` and each element of
|
||||||
|
/// `self`, in turn, i.e. return
|
||||||
|
/// `combine(combine(...combine(combine(initial, self[0]),
|
||||||
|
/// self[1]),...self[count-2]), self[count-1])`.
|
||||||
|
final public func _prext_reduce<T>(
|
||||||
|
initial: T, @noescape combine: (T, ${GElement}) -> T
|
||||||
|
) -> T {
|
||||||
|
var result = initial
|
||||||
|
for element in self {
|
||||||
|
result = combine(result, element)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// reverse()
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
extension SequenceType {
|
||||||
|
/// Return an `Array` containing the elements of `self` in reverse
|
||||||
|
/// order.
|
||||||
|
final public func _prext_reverse() -> [${GElement}] {
|
||||||
|
// FIXME(performance): optimize to 1 pass? But Array(self) can be
|
||||||
|
// optimized to a memcpy() sometimes. Those cases are usually collections,
|
||||||
|
// though.
|
||||||
|
var result = Array(self)
|
||||||
|
let count = result.count
|
||||||
|
for i in 0..<count/2 {
|
||||||
|
swap(&result[i], &result[count - i - 1])
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CollectionType where Self.Index : BidirectionalIndexType {
|
||||||
|
/// Return a lazy `CollectionType` containing the elements of `self`
|
||||||
|
/// in reverse order.
|
||||||
|
final public func _prext_reverse() -> BidirectionalReverseView<Self> {
|
||||||
|
return BidirectionalReverseView(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CollectionType where Self.Index : RandomAccessIndexType {
|
||||||
|
/// Return a lazy `CollectionType` containing the elements of `self`
|
||||||
|
/// in reverse order.
|
||||||
|
final public func _prext_reverse() -> RandomAccessReverseView<Self> {
|
||||||
|
return RandomAccessReverseView(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// filter()
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// We would like to make filter() a protocol requirement, and dynamically
|
||||||
|
// dispatched, but Swift generics don't allow us to express this.
|
||||||
|
// rdar://20477576
|
||||||
|
|
||||||
|
extension SequenceType {
|
||||||
|
/// Return an `Array` containing the elements of `self`,
|
||||||
|
/// in order, that satisfy the predicate `includeElement`.
|
||||||
|
final public func _prext_filter(
|
||||||
|
@noescape includeElement: (${GElement}) -> Bool
|
||||||
|
) -> [${GElement}] {
|
||||||
|
var result: [${GElement}] = []
|
||||||
|
for e in self {
|
||||||
|
if includeElement(e) {
|
||||||
|
result.append(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension RangeReplaceableCollectionType {
|
||||||
|
/// Return an `Array` containing the elements of `self`,
|
||||||
|
/// in order, that satisfy the predicate `includeElement`.
|
||||||
|
final public func _prext_filter(
|
||||||
|
@noescape includeElement: (${GElement}) -> Bool
|
||||||
|
) -> Self {
|
||||||
|
var result = Self()
|
||||||
|
for e in self {
|
||||||
|
if includeElement(e) {
|
||||||
|
result.append(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// map()
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
extension SequenceType {
|
||||||
|
/// Return an `Array` containing the results of mapping `transform`
|
||||||
|
/// over `self`.
|
||||||
|
final public func _prext_map<T>(
|
||||||
|
@noescape transform: (${GElement}) -> T
|
||||||
|
) -> [T] {
|
||||||
|
var result: [T] = []
|
||||||
|
result.reserveCapacity(underestimateCount(self))
|
||||||
|
for element in self {
|
||||||
|
result.append(transform(element))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// flatMap()
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
extension SequenceType {
|
||||||
|
/// Return an `Array` containing the results of mapping `transform`
|
||||||
|
/// over `self` and flattening the result.
|
||||||
|
final public func _prext_flatMap<S : SequenceType>(
|
||||||
|
@noescape transform: (${GElement}) -> S
|
||||||
|
) -> [S.${GElement}] {
|
||||||
|
var result: [S.${GElement}] = []
|
||||||
|
for element in self {
|
||||||
|
result.extend(transform(element))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SequenceType {
|
||||||
|
/// Return an `Array` containing the non-nil results of mapping `transform`
|
||||||
|
/// over `self`.
|
||||||
|
final public func _prext_flatMap<T>(
|
||||||
|
@noescape transform: (${GElement}) -> T?
|
||||||
|
) -> [T] {
|
||||||
|
var result: [T] = []
|
||||||
|
for element in self {
|
||||||
|
if let newElement? = transform(element) {
|
||||||
|
result.append(newElement)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// zip()
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
extension SequenceType {
|
||||||
|
/// Returns a sequence of pairs built out of two underlying sequences,
|
||||||
|
/// where the elements of the `i`\ th pair are the `i`\ th elements
|
||||||
|
/// of each underlying sequence.
|
||||||
|
final public func _prext_zip<S : SequenceType>(s: S) -> Zip2<Self, S> {
|
||||||
|
return Zip2(self, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: we could have an overload on collections that returns a collection
|
||||||
|
// and preserves the index kind. Zip2 is only a sequence.
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// isEmpty
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
extension CollectionType {
|
||||||
|
// FIXME: dynamic dispatch for Set and Dictionary.
|
||||||
|
final public var _prext_isEmpty: Bool {
|
||||||
|
return startIndex == endIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// first
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
extension CollectionType {
|
||||||
|
final public var _prext_first: Generator.Element? {
|
||||||
|
return _prext_isEmpty ? nil : self[startIndex]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// find()
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
extension CollectionType where Self.${GElement} : Equatable {
|
||||||
|
/// Returns the first index where `value` appears in `self` or `nil` if
|
||||||
|
/// `value` is not found.
|
||||||
|
///
|
||||||
|
/// Complexity: O(\ `self.count()`\ )
|
||||||
|
final public func _prext_find(element: ${GElement}) -> Index? {
|
||||||
|
// FIXME: dynamic dispatch for Set and Dictionary.
|
||||||
|
// FIXME: _prext_indices
|
||||||
|
for i in indices(self) {
|
||||||
|
if self[i] == element {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CollectionType {
|
||||||
|
/// Returns the first index where `predicate` returns `true` for the
|
||||||
|
/// corresponding value, or `nil` if such value is not found.
|
||||||
|
///
|
||||||
|
/// Complexity: O(\ `self.count()`\ )
|
||||||
|
final public func _prext_find(
|
||||||
|
@noescape predicate: (${GElement}) -> Bool
|
||||||
|
) -> Index? {
|
||||||
|
for i in indices(self) {
|
||||||
|
if predicate(self[i]) {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// indices()
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
extension CollectionType {
|
||||||
|
/// Return the range of valid index values.
|
||||||
|
///
|
||||||
|
/// The result's `endIndex` is the same as that of `self`. Because
|
||||||
|
/// `Range` is half-open, iterating the values of the result produces
|
||||||
|
/// all valid subscript arguments for `self`, omitting its `endIndex`.
|
||||||
|
final public var _prext_indices: Range<Index> {
|
||||||
|
return Range(start: startIndex, end: endIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -241,6 +241,7 @@ extension Range {
|
|||||||
/// Return an array containing the results of calling
|
/// Return an array containing the results of calling
|
||||||
/// `transform(x)` on each element `x` of `self`.
|
/// `transform(x)` on each element `x` of `self`.
|
||||||
public func map<U>(transform: (T)->U) -> [U] {
|
public func map<U>(transform: (T)->U) -> [U] {
|
||||||
return Swift.map(self, transform)
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
return self._prext_map(transform)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public protocol RangeReplaceableCollectionType : ExtensibleCollectionType {
|
|||||||
/// `subRange.endIndex == self.endIndex` and `isEmpty(newElements)`,
|
/// `subRange.endIndex == self.endIndex` and `isEmpty(newElements)`,
|
||||||
/// O(\ `count(self)` + `count(newElements)`\ ) otherwise.
|
/// O(\ `count(self)` + `count(newElements)`\ ) otherwise.
|
||||||
mutating func replaceRange<
|
mutating func replaceRange<
|
||||||
C: CollectionType where C.Generator.Element == Self.Generator.Element
|
C : CollectionType where C.Generator.Element == Self.Generator.Element
|
||||||
>(
|
>(
|
||||||
subRange: Range<Index>, with newElements: C
|
subRange: Range<Index>, with newElements: C
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -16,10 +16,10 @@
|
|||||||
public func reverse<C:CollectionType where C.Index: BidirectionalIndexType>(
|
public func reverse<C:CollectionType where C.Index: BidirectionalIndexType>(
|
||||||
source: C
|
source: C
|
||||||
) -> [C.Generator.Element] {
|
) -> [C.Generator.Element] {
|
||||||
return lazy(source).reverse().array
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
return Array(source._prext_reverse())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
% for traversal in ('Bidirectional', 'RandomAccess'):
|
% for traversal in ('Bidirectional', 'RandomAccess'):
|
||||||
% View = '%sReverseView' % traversal
|
% View = '%sReverseView' % traversal
|
||||||
% Self = 'Lazy%sCollection' % traversal
|
% Self = 'Lazy%sCollection' % traversal
|
||||||
|
|||||||
@@ -252,6 +252,16 @@ public final class _stdlib_AtomicInt {
|
|||||||
public func addAndFetch(operand: Int) -> Int {
|
public func addAndFetch(operand: Int) -> Int {
|
||||||
return fetchAndAdd(operand) + operand
|
return fetchAndAdd(operand) + operand
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func compareExchange(inout #expected: Int, desired: Int) -> Bool {
|
||||||
|
var expectedVar = expected
|
||||||
|
let result = _stdlib_atomicCompareExchangeStrongInt(
|
||||||
|
object: _valuePtr,
|
||||||
|
expected: &expectedVar,
|
||||||
|
desired: desired)
|
||||||
|
expected = expectedVar
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|||||||
@@ -15,7 +15,8 @@
|
|||||||
/// underlying sequence.
|
/// underlying sequence.
|
||||||
public func zip<S0: SequenceType, S1: SequenceType>(
|
public func zip<S0: SequenceType, S1: SequenceType>(
|
||||||
s0: S0, s1: S1) -> Zip2<S0, S1> {
|
s0: S0, s1: S1) -> Zip2<S0, S1> {
|
||||||
return Zip2(s0, s1)
|
// FIXME(prext): remove this function when protocol extensions land.
|
||||||
|
return s0._prext_zip(s1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A generator for the `Zip2` sequence
|
/// A generator for the `Zip2` sequence
|
||||||
@@ -37,14 +38,31 @@ public struct ZipGenerator2<
|
|||||||
/// since the copy was made, and no preceding call to `self.next()`
|
/// since the copy was made, and no preceding call to `self.next()`
|
||||||
/// has returned `nil`.
|
/// has returned `nil`.
|
||||||
public mutating func next() -> Element? {
|
public mutating func next() -> Element? {
|
||||||
|
// The next() function needs to track if it has reached the end. If we
|
||||||
|
// didn't, and the first sequence is shorter than the second, then, when we
|
||||||
|
// have already exhausted the second sequence, on every subsequent call to
|
||||||
|
// next() we would consume and discard one additional element from the
|
||||||
|
// first sequence, even though next() return nil.
|
||||||
|
|
||||||
|
if reachedEnd {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var e0 = baseStreams.0.next()
|
var e0 = baseStreams.0.next()
|
||||||
if e0 == nil { return .None }
|
if e0 == nil {
|
||||||
|
reachedEnd = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
var e1 = baseStreams.1.next()
|
var e1 = baseStreams.1.next()
|
||||||
if e1 == nil { return .None }
|
if e1 == nil {
|
||||||
|
reachedEnd = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return .Some((e0!, e1!))
|
return .Some((e0!, e1!))
|
||||||
}
|
}
|
||||||
|
|
||||||
var baseStreams : (E0,E1)
|
var baseStreams: (E0, E1)
|
||||||
|
var reachedEnd: Bool = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A sequence of pairs built out of two underlying sequences, where
|
/// A sequence of pairs built out of two underlying sequences, where
|
||||||
|
|||||||
@@ -1,517 +0,0 @@
|
|||||||
// RUN: %target-run-simple-swift
|
|
||||||
|
|
||||||
import StdlibUnittest
|
|
||||||
import SwiftPrivate
|
|
||||||
|
|
||||||
var Algorithm = TestSuite("Algorithm")
|
|
||||||
|
|
||||||
extension String.UnicodeScalarView : Equatable {}
|
|
||||||
|
|
||||||
public func == (
|
|
||||||
lhs: String.UnicodeScalarView, rhs: String.UnicodeScalarView) -> Bool {
|
|
||||||
return Array(lhs) == Array(rhs)
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("split") {
|
|
||||||
expectEqual(
|
|
||||||
[ "foo", " bar baz " ].map { $0.unicodeScalars },
|
|
||||||
split(" foo bar baz ".unicodeScalars, maxSplit: 1) { $0._isSpace() })
|
|
||||||
|
|
||||||
expectEqual(
|
|
||||||
[ "foo", "bar", "baz" ].map { $0.unicodeScalars },
|
|
||||||
split(
|
|
||||||
" foo bar baz ".unicodeScalars, allowEmptySlices: false) {
|
|
||||||
$0._isSpace()
|
|
||||||
})
|
|
||||||
|
|
||||||
expectEqual(
|
|
||||||
[ "", "", "foo", "", "", "bar", "baz", "" ].map { $0.unicodeScalars },
|
|
||||||
split(
|
|
||||||
" foo bar baz ".unicodeScalars, allowEmptySlices: true) {
|
|
||||||
$0._isSpace()
|
|
||||||
})
|
|
||||||
|
|
||||||
expectEqual(
|
|
||||||
[ "", "", "foo bar baz " ].map { $0.unicodeScalars },
|
|
||||||
split(
|
|
||||||
" foo bar baz ".unicodeScalars, allowEmptySlices: true, maxSplit: 2,
|
|
||||||
isSeparator: { $0._isSpace() }))
|
|
||||||
}
|
|
||||||
|
|
||||||
struct StartsWithTest {
|
|
||||||
let expected: Bool
|
|
||||||
let sequence: [Int]
|
|
||||||
let prefix: [Int]
|
|
||||||
let loc: SourceLoc
|
|
||||||
|
|
||||||
init(
|
|
||||||
_ expected: Bool, _ sequence: [Int], _ prefix: [Int],
|
|
||||||
file: String = __FILE__, line: UWord = __LINE__
|
|
||||||
) {
|
|
||||||
self.expected = expected
|
|
||||||
self.sequence = sequence
|
|
||||||
self.prefix = prefix
|
|
||||||
self.loc = SourceLoc(file, line, comment: "test data")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let startsWithTests = [
|
|
||||||
StartsWithTest(true, [], []),
|
|
||||||
StartsWithTest(false, [], [ 1 ]),
|
|
||||||
StartsWithTest(true, [ 1 ], []),
|
|
||||||
StartsWithTest(true, [ 0, 1, 3, 5 ], [ 0, 1 ]),
|
|
||||||
StartsWithTest(true, [ 0, 1 ], [ 0, 1 ]),
|
|
||||||
StartsWithTest(false, [ 0, 1, 3, 5 ], [ 0, 1, 4 ]),
|
|
||||||
StartsWithTest(false, [ 0, 1 ], [ 0, 1, 4 ]),
|
|
||||||
]
|
|
||||||
|
|
||||||
func checkStartsWith(
|
|
||||||
expected: Bool, sequence: [Int], prefix: [Int],
|
|
||||||
stackTrace: SourceLocStack
|
|
||||||
) {
|
|
||||||
expectEqual(expected, startsWith(sequence, prefix), stackTrace: stackTrace)
|
|
||||||
expectEqual(
|
|
||||||
expected, startsWith(sequence, prefix, (==)),
|
|
||||||
stackTrace: stackTrace)
|
|
||||||
expectEqual(
|
|
||||||
expected, startsWith(map(sequence) { $0 * 2 }, prefix) { $0 / 2 == $1 },
|
|
||||||
stackTrace: stackTrace)
|
|
||||||
|
|
||||||
// Test using different types for the sequence and prefix.
|
|
||||||
expectEqual(
|
|
||||||
expected, startsWith(ContiguousArray(sequence), prefix),
|
|
||||||
stackTrace: stackTrace)
|
|
||||||
expectEqual(
|
|
||||||
expected, startsWith(ContiguousArray(sequence), prefix, (==)),
|
|
||||||
stackTrace: stackTrace)
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("startsWith") {
|
|
||||||
for test in startsWithTests {
|
|
||||||
checkStartsWith(
|
|
||||||
test.expected, test.sequence, test.prefix, test.loc.withCurrentLoc())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("enumerate") {
|
|
||||||
var result = [String]()
|
|
||||||
for (i, s) in enumerate( "You will never retrieve the necronomicon!"._split(" ") ) {
|
|
||||||
result.append("\(i) \(s)")
|
|
||||||
}
|
|
||||||
expectEqual(
|
|
||||||
[ "0 You", "1 will", "2 never", "3 retrieve", "4 the", "5 necronomicon!" ],
|
|
||||||
result)
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("equal") {
|
|
||||||
var _0_4 = [0, 1, 2, 3]
|
|
||||||
expectFalse(equal(_0_4, 0..<3))
|
|
||||||
expectTrue(equal(_0_4, 0..<4))
|
|
||||||
expectFalse(equal(_0_4, 0..<5))
|
|
||||||
expectFalse(equal(_0_4, 1..<4))
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("equal/predicate") {
|
|
||||||
func compare(lhs: (Int, Int), rhs: (Int, Int)) -> Bool {
|
|
||||||
return lhs.0 == rhs.0 && lhs.1 == rhs.1
|
|
||||||
}
|
|
||||||
|
|
||||||
var _0_4 = [(0, 10), (1, 11), (2, 12), (3, 13)]
|
|
||||||
expectFalse(equal(_0_4, [(0, 10), (1, 11), (2, 12)], compare))
|
|
||||||
expectTrue(equal(_0_4, [(0, 10), (1, 11), (2, 12), (3, 13)], compare))
|
|
||||||
expectFalse(equal(_0_4, [(0, 10), (1, 11), (2, 12), (3, 13), (4, 14)], compare))
|
|
||||||
expectFalse(equal(_0_4, [(1, 11), (2, 12), (3, 13)], compare))
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("contains") {
|
|
||||||
let _0_4 = [0, 1, 2, 3]
|
|
||||||
expectFalse(contains(_0_4, 7))
|
|
||||||
expectTrue(contains(_0_4, 2))
|
|
||||||
expectFalse(contains(_0_4, { $0 - 10 > 0 }))
|
|
||||||
expectTrue(contains(_0_4, { $0 % 3 == 0 }))
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("min,max") {
|
|
||||||
expectEqual(2, min(3, 2))
|
|
||||||
expectEqual(3, min(3, 7, 5))
|
|
||||||
expectEqual(3, max(3, 2))
|
|
||||||
expectEqual(7, max(3, 7, 5))
|
|
||||||
|
|
||||||
// FIXME: add tests that check that min/max return the
|
|
||||||
// first element of the sequence (by reference equailty) that satisfy the
|
|
||||||
// condition.
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("minElement,maxElement") {
|
|
||||||
var arr = [Int](count: 10, repeatedValue: 0)
|
|
||||||
for i in 0..<10 {
|
|
||||||
arr[i] = i % 7 + 2
|
|
||||||
}
|
|
||||||
expectEqual([2, 3, 4, 5, 6, 7, 8, 2, 3, 4], arr)
|
|
||||||
|
|
||||||
expectEqual(2, minElement(arr))
|
|
||||||
expectEqual(8, maxElement(arr))
|
|
||||||
|
|
||||||
// min and max element of a slice
|
|
||||||
expectEqual(3, minElement(arr[1..<5]))
|
|
||||||
expectEqual(6, maxElement(arr[1..<5]))
|
|
||||||
|
|
||||||
// FIXME: add tests that check that minElement/maxElement return the
|
|
||||||
// first element of the sequence (by reference equailty) that satisfy the
|
|
||||||
// condition.
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("filter/SequenceType") {
|
|
||||||
if true {
|
|
||||||
let s = MinimalSequence<Int>([], underestimatedCount: .Overestimate)
|
|
||||||
var result = filter(s) {
|
|
||||||
(x: Int) -> Bool in
|
|
||||||
expectUnreachable()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
expectType([Int].self, &result)
|
|
||||||
expectEqual([], result)
|
|
||||||
expectEqual([], Array(s))
|
|
||||||
expectEqual(0, result.capacity)
|
|
||||||
}
|
|
||||||
if true {
|
|
||||||
let s = MinimalSequence(
|
|
||||||
[ 0, 30, 10, 90 ], underestimatedCount: .Overestimate)
|
|
||||||
let result = filter(s) { (x: Int) -> Bool in false }
|
|
||||||
expectEqual([], result)
|
|
||||||
expectEqual([], Array(s))
|
|
||||||
expectEqual(0, result.capacity)
|
|
||||||
}
|
|
||||||
if true {
|
|
||||||
let s = MinimalSequence(
|
|
||||||
[ 0, 30, 10, 90 ], underestimatedCount: .Overestimate)
|
|
||||||
let result = filter(s) { (x: Int) -> Bool in true }
|
|
||||||
expectEqual([ 0, 30, 10, 90 ], result)
|
|
||||||
expectEqual([], Array(s))
|
|
||||||
expectGE(2 * result.count, result.capacity)
|
|
||||||
}
|
|
||||||
if true {
|
|
||||||
let s = MinimalSequence(
|
|
||||||
[ 0, 30, 10, 90 ], underestimatedCount: .Value(0))
|
|
||||||
let result = filter(s) { $0 % 3 == 0 }
|
|
||||||
expectEqual([ 0, 30, 90 ], result)
|
|
||||||
expectEqual([], Array(s))
|
|
||||||
expectGE(2 * result.count, result.capacity)
|
|
||||||
}
|
|
||||||
if true {
|
|
||||||
let s = MinimalSequence(
|
|
||||||
[ 0, 30, 10, 90 ], underestimatedCount: .Overestimate)
|
|
||||||
let result = filter(s) { $0 % 3 == 0 }
|
|
||||||
expectEqual([ 0, 30, 90 ], result)
|
|
||||||
expectEqual([], Array(s))
|
|
||||||
expectGE(2 * result.count, result.capacity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("filter/CollectionType") {
|
|
||||||
if true {
|
|
||||||
let c = MinimalForwardCollection<Int>([])
|
|
||||||
var result = filter(c) {
|
|
||||||
(x: Int) -> Bool in
|
|
||||||
expectUnreachable()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
expectEqual([], result)
|
|
||||||
expectType([Int].self, &result)
|
|
||||||
expectEqual(0, result.capacity)
|
|
||||||
}
|
|
||||||
if true {
|
|
||||||
let c = MinimalForwardCollection([ 0, 30, 10, 90 ])
|
|
||||||
let result = filter(c) { (x: Int) -> Bool in false }
|
|
||||||
expectEqual([], result)
|
|
||||||
expectEqual(0, result.capacity)
|
|
||||||
}
|
|
||||||
if true {
|
|
||||||
let c = MinimalForwardCollection([ 0, 30, 10, 90 ])
|
|
||||||
let result = filter(c) { (x: Int) -> Bool in true }
|
|
||||||
expectEqual([ 0, 30, 10, 90 ], result)
|
|
||||||
expectGE(2 * result.count, result.capacity)
|
|
||||||
}
|
|
||||||
if true {
|
|
||||||
let c = MinimalForwardCollection([ 0, 30, 10, 90 ])
|
|
||||||
let result = filter(c) { $0 % 3 == 0 }
|
|
||||||
expectEqual([ 0, 30, 90 ], result)
|
|
||||||
expectGE(2 * result.count, result.capacity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("filter/eager") {
|
|
||||||
// Make sure filter is eager and only calls its predicate once per element.
|
|
||||||
var count = 0
|
|
||||||
let one = filter(0..<10) {
|
|
||||||
(x: Int)->Bool in ++count; return x == 1
|
|
||||||
}
|
|
||||||
for x in one {}
|
|
||||||
expectEqual(10, count)
|
|
||||||
for x in one {}
|
|
||||||
expectEqual(10, count)
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("map/SequenceType") {
|
|
||||||
if true {
|
|
||||||
let s = MinimalSequence<Int>([], underestimatedCount: .Overestimate)
|
|
||||||
var result = map(s) {
|
|
||||||
(x: Int) -> Int16 in
|
|
||||||
expectUnreachable()
|
|
||||||
return 42
|
|
||||||
}
|
|
||||||
expectType([Int16].self, &result)
|
|
||||||
expectEqual([], result)
|
|
||||||
expectEqual([], Array(s))
|
|
||||||
// FIXME: <rdar://problem/19810841> Reserve capacity when running map() over a SequenceType
|
|
||||||
// expectLE(s._underestimatedCount, result.capacity)
|
|
||||||
}
|
|
||||||
if true {
|
|
||||||
let s = MinimalSequence(
|
|
||||||
[ 0, 30, 10, 90 ], underestimatedCount: .Value(0))
|
|
||||||
let result = map(s) { $0 + 1 }
|
|
||||||
expectEqual([ 1, 31, 11, 91 ], result)
|
|
||||||
expectEqual([], Array(s))
|
|
||||||
// FIXME: <rdar://problem/19810841> Reserve capacity when running map() over a SequenceType
|
|
||||||
// expectLE(s._underestimatedCount, result.capacity)
|
|
||||||
}
|
|
||||||
if true {
|
|
||||||
let s = MinimalSequence(
|
|
||||||
[ 0, 30, 10, 90 ], underestimatedCount: .Overestimate)
|
|
||||||
let result = map(s) { $0 + 1 }
|
|
||||||
expectEqual([ 1, 31, 11, 91 ], result)
|
|
||||||
expectEqual([], Array(s))
|
|
||||||
// FIXME: <rdar://problem/19810841> Reserve capacity when running map() over a SequenceType
|
|
||||||
// expectLE(s._underestimatedCount, result.capacity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("map/CollectionType") {
|
|
||||||
if true {
|
|
||||||
let c = MinimalForwardCollection<Int>([])
|
|
||||||
var result = map(c) {
|
|
||||||
(x: Int) -> Int16 in
|
|
||||||
expectUnreachable()
|
|
||||||
return 42
|
|
||||||
}
|
|
||||||
expectType([Int16].self, &result)
|
|
||||||
expectEqual([], result)
|
|
||||||
// FIXME: <rdar://problem/19810841> Reserve capacity when running map() over a SequenceType
|
|
||||||
// expectLE(c._underestimatedCount, result.capacity)
|
|
||||||
}
|
|
||||||
if true {
|
|
||||||
let c = MinimalForwardCollection(
|
|
||||||
[ 0, 30, 10, 90 ], underestimatedCount: .Value(0))
|
|
||||||
let result = map(c) { $0 + 1 }
|
|
||||||
expectEqual([ 1, 31, 11, 91 ], result)
|
|
||||||
// FIXME: <rdar://problem/19810841> Reserve capacity when running map() over a SequenceType
|
|
||||||
// expectLE(c._underestimatedCount, result.capacity)
|
|
||||||
}
|
|
||||||
if true {
|
|
||||||
let c = MinimalForwardCollection(
|
|
||||||
[ 0, 30, 10, 90 ], underestimatedCount: .Overestimate)
|
|
||||||
let result = map(c) { $0 + 1 }
|
|
||||||
expectEqual([ 1, 31, 11, 91 ], result)
|
|
||||||
// FIXME: <rdar://problem/19810841> Reserve capacity when running map() over a SequenceType
|
|
||||||
// expectLE(c._underestimatedCount, result.capacity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("flatMap/SequenceType") {
|
|
||||||
if true {
|
|
||||||
let s = MinimalSequence<Int>([])
|
|
||||||
var result = flatMap(s) {
|
|
||||||
(x: Int) -> [Int16] in
|
|
||||||
expectUnreachable()
|
|
||||||
return [42]
|
|
||||||
}
|
|
||||||
expectType([Int16].self, &result)
|
|
||||||
expectEqual([], result)
|
|
||||||
expectEqual([], Array(s))
|
|
||||||
}
|
|
||||||
if true {
|
|
||||||
let s = MinimalSequence([ 0, 30, 10, 90 ])
|
|
||||||
let result = flatMap(s) { [$0 + 1] }
|
|
||||||
expectEqual([ 1, 31, 11, 91 ], result)
|
|
||||||
expectEqual([], Array(s))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("flatMap/CollectionType") {
|
|
||||||
if true {
|
|
||||||
let c = MinimalForwardCollection<Int>([])
|
|
||||||
var result = flatMap(c) {
|
|
||||||
(x: Int) -> [Int16] in
|
|
||||||
expectUnreachable()
|
|
||||||
return [42]
|
|
||||||
}
|
|
||||||
expectType([Int16].self, &result)
|
|
||||||
expectEqual([], result)
|
|
||||||
}
|
|
||||||
if true {
|
|
||||||
let c = MinimalForwardCollection([ 0, 30, 10, 90 ])
|
|
||||||
let result = flatMap(c) { [$0 + 1] }
|
|
||||||
expectEqual([ 1, 31, 11, 91 ], result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("sorted/strings")
|
|
||||||
.xfail(.LinuxAny(reason: "String comparison: ICU vs. Foundation"))
|
|
||||||
.code {
|
|
||||||
expectEqual(
|
|
||||||
[ "Banana", "apple", "cherry" ],
|
|
||||||
sorted([ "apple", "Banana", "cherry" ]))
|
|
||||||
|
|
||||||
let s = sorted(["apple", "Banana", "cherry"]) {
|
|
||||||
count($0) > count($1)
|
|
||||||
}
|
|
||||||
expectEqual([ "Banana", "cherry", "apple" ], s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// A wrapper around Array<T> that disables any type-specific algorithm
|
|
||||||
// optimizations and forces bounds checking on.
|
|
||||||
struct A<T> : MutableSliceable {
|
|
||||||
init(_ a: Array<T>) {
|
|
||||||
impl = a
|
|
||||||
}
|
|
||||||
|
|
||||||
var startIndex: Int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var endIndex: Int {
|
|
||||||
return impl.count
|
|
||||||
}
|
|
||||||
|
|
||||||
func generate() -> Array<T>.Generator {
|
|
||||||
return impl.generate()
|
|
||||||
}
|
|
||||||
|
|
||||||
subscript(i: Int) -> T {
|
|
||||||
get {
|
|
||||||
expectTrue(i >= 0 && i < impl.count)
|
|
||||||
return impl[i]
|
|
||||||
}
|
|
||||||
set (x) {
|
|
||||||
expectTrue(i >= 0 && i < impl.count)
|
|
||||||
impl[i] = x
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
subscript(r: Range<Int>) -> Array<T>.SubSlice {
|
|
||||||
get {
|
|
||||||
expectTrue(r.startIndex >= 0 && r.startIndex <= impl.count)
|
|
||||||
expectTrue(r.endIndex >= 0 && r.endIndex <= impl.count)
|
|
||||||
return impl[r]
|
|
||||||
}
|
|
||||||
set (x) {
|
|
||||||
expectTrue(r.startIndex >= 0 && r.startIndex <= impl.count)
|
|
||||||
expectTrue(r.endIndex >= 0 && r.endIndex <= impl.count)
|
|
||||||
impl[r] = x
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var impl: Array<T>
|
|
||||||
}
|
|
||||||
|
|
||||||
func withInvalidOrderings(body: ((Int,Int)->Bool)->Void) {
|
|
||||||
// Test some ordering predicates that don't create strict weak orderings
|
|
||||||
body { (_,_) in true }
|
|
||||||
body { (_,_) in false }
|
|
||||||
var i = 0
|
|
||||||
body { (_,_) in i++ % 2 == 0 }
|
|
||||||
body { (_,_) in i++ % 3 == 0 }
|
|
||||||
body { (_,_) in i++ % 5 == 0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
func randomArray() -> A<Int> {
|
|
||||||
let count = Int(rand32(exclusiveUpperBound: 50))
|
|
||||||
return A(randArray(count))
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("invalidOrderings") {
|
|
||||||
withInvalidOrderings {
|
|
||||||
var a = randomArray()
|
|
||||||
sort(&a, $0)
|
|
||||||
}
|
|
||||||
withInvalidOrderings {
|
|
||||||
var a: A<Int>
|
|
||||||
a = randomArray()
|
|
||||||
partition(&a, indices(a), $0)
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
// FIXME: Disabled due to <rdar://problem/17734737> Unimplemented:
|
|
||||||
// abstraction difference in l-value
|
|
||||||
withInvalidOrderings {
|
|
||||||
var a = randomArray()
|
|
||||||
var pred = $0
|
|
||||||
_insertionSort(&a, indices(a), &pred)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
withInvalidOrderings {
|
|
||||||
let predicate: (Int,Int)->Bool = $0
|
|
||||||
let result = lexicographicalCompare(randomArray(), randomArray(), isOrderedBefore: predicate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The routine is based on http://www.cs.dartmouth.edu/~doug/mdmspe.pdf
|
|
||||||
func makeQSortKiller(len: Int) -> [Int] {
|
|
||||||
var candidate: Int = 0
|
|
||||||
var keys = [Int:Int]()
|
|
||||||
func Compare(x: Int, y : Int) -> Bool {
|
|
||||||
if keys[x] == nil && keys[y] == nil {
|
|
||||||
if (x == candidate) {
|
|
||||||
keys[x] = keys.count
|
|
||||||
} else {
|
|
||||||
keys[y] = keys.count
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if keys[x] == nil {
|
|
||||||
candidate = x
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if keys[y] == nil {
|
|
||||||
candidate = y
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return keys[x]! > keys[y]!
|
|
||||||
}
|
|
||||||
|
|
||||||
var ary = [Int](count: len, repeatedValue:0)
|
|
||||||
var ret = [Int](count: len, repeatedValue:0)
|
|
||||||
for i in 0..<len { ary[i] = i }
|
|
||||||
ary = sorted(ary, Compare)
|
|
||||||
for i in 0..<len {
|
|
||||||
ret[ary[i]] = i
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("sorted/complexity") {
|
|
||||||
var ary: [Int] = []
|
|
||||||
|
|
||||||
// Check performance of sort on array of repeating values
|
|
||||||
var comparisons_100 = 0
|
|
||||||
ary = [Int](count: 100, repeatedValue: 0)
|
|
||||||
sort(&ary) { comparisons_100++; return $0 < $1 }
|
|
||||||
var comparisons_1000 = 0
|
|
||||||
ary = [Int](count: 1000, repeatedValue: 0)
|
|
||||||
sort(&ary) { comparisons_1000++; return $0 < $1 }
|
|
||||||
expectTrue(comparisons_1000/comparisons_100 < 20)
|
|
||||||
|
|
||||||
// Try to construct 'bad' case for quicksort, on which the algorithm
|
|
||||||
// goes quadratic.
|
|
||||||
comparisons_100 = 0
|
|
||||||
ary = makeQSortKiller(100)
|
|
||||||
sort(&ary) { comparisons_100++; return $0 < $1 }
|
|
||||||
comparisons_1000 = 0
|
|
||||||
ary = makeQSortKiller(1000)
|
|
||||||
sort(&ary) { comparisons_1000++; return $0 < $1 }
|
|
||||||
expectTrue(comparisons_1000/comparisons_100 < 20)
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm.test("sorted/return type") {
|
|
||||||
let x: Array = sorted([5, 4, 3, 2, 1] as ArraySlice)
|
|
||||||
}
|
|
||||||
runAllTests()
|
|
||||||
|
|
||||||
2024
test/1_stdlib/Algorithm.swift.gyb
Normal file
2024
test/1_stdlib/Algorithm.swift.gyb
Normal file
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,8 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// RUN: %target-run-simple-swift | FileCheck %s
|
// RUN: %target-run-simple-swift | FileCheck %s
|
||||||
|
|
||||||
|
// FIXME(prext): remove this file when protocol extensions land.
|
||||||
|
|
||||||
// CHECK: testing...
|
// CHECK: testing...
|
||||||
println("testing...")
|
println("testing...")
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// RUN: %target-run-simple-swift | FileCheck %s
|
// RUN: %target-run-simple-swift | FileCheck %s
|
||||||
|
|
||||||
|
// FIXME(prext): remove this file when protocol extensions land.
|
||||||
|
|
||||||
var n = [2, 3, 5, 7, 11]
|
var n = [2, 3, 5, 7, 11]
|
||||||
var s = ["two", "three", "five", "seven", "eleven", "thirteen"]
|
var s = ["two", "three", "five", "seven", "eleven", "thirteen"]
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func usesAGenericMethod<U : NeedsAGenericMethod>(x: U) {
|
|||||||
x.method(5)
|
x.method(5)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct L<T>: SequenceType {} // expected-error {{type 'L<T>' does not conform to protocol '_Sequence_Type'}} expected-error {{type 'L<T>' does not conform to protocol 'SequenceType'}}
|
struct L<T>: SequenceType {} // expected-error {{type 'L<T>' does not conform to protocol '_Sequence_Type'}} expected-error {{type 'L<T>' does not conform to protocol 'SequenceType'}} expected-error {{type 'L<T>' does not conform to protocol '_SequenceDefaultsType'}}
|
||||||
|
|
||||||
func z(x: L<Int>) {
|
func z(x: L<Int>) {
|
||||||
for xx in x {} // expected-error{{'L<Int>' does not have a member named 'Generator'}}
|
for xx in x {} // expected-error{{'L<Int>' does not have a member named 'Generator'}}
|
||||||
|
|||||||
@@ -6,10 +6,6 @@
|
|||||||
// RUN: FileCheck %s -check-prefix=PRIVATE_NOMINAL_MEMBERS_1 < %t.members.txt
|
// RUN: FileCheck %s -check-prefix=PRIVATE_NOMINAL_MEMBERS_1 < %t.members.txt
|
||||||
// RUN: FileCheck %s -check-prefix=NO_STDLIB_PRIVATE < %t.members.txt
|
// RUN: FileCheck %s -check-prefix=NO_STDLIB_PRIVATE < %t.members.txt
|
||||||
|
|
||||||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PRIVATE_PROTOCOL_MEMBERS_1 > %t.protocol.members.txt
|
|
||||||
// RUN: FileCheck %s -check-prefix=PRIVATE_PROTOCOL_MEMBERS_1 < %t.protocol.members.txt
|
|
||||||
// RUN: FileCheck %s -check-prefix=NO_STDLIB_PRIVATE < %t.protocol.members.txt
|
|
||||||
|
|
||||||
// NO_STDLIB_PRIVATE: Begin completions
|
// NO_STDLIB_PRIVATE: Begin completions
|
||||||
// NO_STDLIB_PRIVATE-NOT: Decl[{{.*}}]{{[^:]*}}: _
|
// NO_STDLIB_PRIVATE-NOT: Decl[{{.*}}]{{[^:]*}}: _
|
||||||
// NO_STDLIB_PRIVATE: End completions
|
// NO_STDLIB_PRIVATE: End completions
|
||||||
@@ -28,11 +24,3 @@ func privateNominalMembers(a: String) {
|
|||||||
// PRIVATE_NOMINAL_MEMBERS_1-DAG: Decl[InstanceVar]/CurrNominal: startIndex[#String.Index#]{{; name=.+$}}
|
// PRIVATE_NOMINAL_MEMBERS_1-DAG: Decl[InstanceVar]/CurrNominal: startIndex[#String.Index#]{{; name=.+$}}
|
||||||
// PRIVATE_NOMINAL_MEMBERS_1: End completions
|
// PRIVATE_NOMINAL_MEMBERS_1: End completions
|
||||||
|
|
||||||
func privateProtocolMembers(a: CollectionType) {
|
|
||||||
a.#^PRIVATE_PROTOCOL_MEMBERS_1^#
|
|
||||||
}
|
|
||||||
|
|
||||||
// PRIVATE_PROTOCOL_MEMBERS_1: Begin completions
|
|
||||||
// PRIVATE_PROTOCOL_MEMBERS_1-DAG: Decl[InstanceVar]/Super: startIndex[#Self.Index#]
|
|
||||||
|
|
||||||
// PRIVATE_PROTOCOL_MEMBERS_1: End completions
|
|
||||||
|
|||||||
@@ -8,16 +8,16 @@ func bad_containers_1(bc: BadContainer1) {
|
|||||||
for e in bc { } // expected-error{{type 'BadContainer1' does not conform to protocol 'SequenceType'}}
|
for e in bc { } // expected-error{{type 'BadContainer1' does not conform to protocol 'SequenceType'}}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BadContainer2 : SequenceType { // expected-error{{type 'BadContainer2' does not conform to protocol '_Sequence_Type'}} expected-error{{type 'BadContainer2' does not conform to protocol 'SequenceType'}}
|
struct BadContainer2 : SequenceType { // expected-error{{type 'BadContainer2' does not conform to protocol '_Sequence_Type'}} expected-error{{type 'BadContainer2' does not conform to protocol 'SequenceType'}} expected-error{{type 'BadContainer2' does not conform to protocol '_SequenceDefaultsType'}}
|
||||||
var generate : Int // expected-note{{candidate is not a function}} expected-note{{candidate is not a function}}
|
var generate : Int // expected-note 3{{candidate is not a function}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func bad_containers_2(bc: BadContainer2) {
|
func bad_containers_2(bc: BadContainer2) {
|
||||||
for e in bc { } // expected-error{{'BadContainer2' does not have a member named 'Generator'}}
|
for e in bc { } // expected-error{{'BadContainer2' does not have a member named 'Generator'}}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BadContainer3 : SequenceType { // expected-error{{type 'BadContainer3' does not conform to protocol '_Sequence_Type'}} expected-error{{type 'BadContainer3' does not conform to protocol 'SequenceType'}}
|
struct BadContainer3 : SequenceType { // expected-error{{type 'BadContainer3' does not conform to protocol '_Sequence_Type'}} expected-error{{type 'BadContainer3' does not conform to protocol 'SequenceType'}} expected-error{{type 'BadContainer3' does not conform to protocol '_SequenceDefaultsType'}}
|
||||||
func generate() { } // expected-note{{candidate has non-matching type '() -> ()'}} expected-note{{candidate has non-matching type '() -> ()'}}
|
func generate() { } // expected-note 3{{candidate has non-matching type '() -> ()'}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func bad_containers_3(bc: BadContainer3) {
|
func bad_containers_3(bc: BadContainer3) {
|
||||||
@@ -28,8 +28,8 @@ struct BadGeneratorType1 {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BadContainer4 : SequenceType { // expected-error{{type 'BadContainer4' does not conform to protocol '_Sequence_Type'}} expected-error{{type 'BadContainer4' does not conform to protocol 'SequenceType'}}
|
struct BadContainer4 : SequenceType { // expected-error{{type 'BadContainer4' does not conform to protocol '_Sequence_Type'}} expected-error{{type 'BadContainer4' does not conform to protocol 'SequenceType'}} expected-error{{type 'BadContainer4' does not conform to protocol '_SequenceDefaultsType'}}
|
||||||
typealias Generator = BadGeneratorType1 // expected-note{{possibly intended match 'Generator' does not conform to 'GeneratorType'}} expected-note{{possibly intended match 'Generator' does not conform to 'GeneratorType'}}
|
typealias Generator = BadGeneratorType1 // expected-note 3{{possibly intended match 'Generator' does not conform to 'GeneratorType'}}
|
||||||
func generate() -> BadGeneratorType1 { }
|
func generate() -> BadGeneratorType1 { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,13 +32,13 @@ let expected = ContiguousArray(0..<8)
|
|||||||
|
|
||||||
for (expected, source) in samples {
|
for (expected, source) in samples {
|
||||||
ConcatenateTests.test("forward-\(source)") {
|
ConcatenateTests.test("forward-\(source)") {
|
||||||
checkCollection(
|
checkBidirectionalCollection(
|
||||||
expected,
|
expected,
|
||||||
_lazyConcatenate(source),
|
_lazyConcatenate(source),
|
||||||
SourceLocStack().withCurrentLoc())
|
SourceLocStack().withCurrentLoc())
|
||||||
}
|
}
|
||||||
ConcatenateTests.test("reverse-\(source)") {
|
ConcatenateTests.test("reverse-\(source)") {
|
||||||
checkCollection(
|
checkBidirectionalCollection(
|
||||||
ContiguousArray(lazy(expected).reverse()),
|
ContiguousArray(lazy(expected).reverse()),
|
||||||
_lazyConcatenate(source).reverse(),
|
_lazyConcatenate(source).reverse(),
|
||||||
SourceLocStack().withCurrentLoc())
|
SourceLocStack().withCurrentLoc())
|
||||||
|
|||||||
@@ -253,7 +253,8 @@ CoreAudioTestSuite.test("UnsafeMutableAudioBufferListPointer.subscript(_: Int)/t
|
|||||||
}
|
}
|
||||||
|
|
||||||
CoreAudioTestSuite.test("UnsafeMutableAudioBufferListPointer/Collection") {
|
CoreAudioTestSuite.test("UnsafeMutableAudioBufferListPointer/Collection") {
|
||||||
let ablPtrWrapper = AudioBufferList.allocate(maximumBuffers: 16)
|
var ablPtrWrapper = AudioBufferList.allocate(maximumBuffers: 16)
|
||||||
|
expectType(UnsafeMutableAudioBufferListPointer.self, &ablPtrWrapper)
|
||||||
|
|
||||||
var expected: [AudioBuffer] = []
|
var expected: [AudioBuffer] = []
|
||||||
for i in 0..<16 {
|
for i in 0..<16 {
|
||||||
@@ -265,7 +266,9 @@ CoreAudioTestSuite.test("UnsafeMutableAudioBufferListPointer/Collection") {
|
|||||||
expected.append(audioBuffer)
|
expected.append(audioBuffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkCollection(expected, ablPtrWrapper, SourceLocStack().withCurrentLoc())
|
// FIXME: use checkMutableRandomAccessCollection, when we have that function.
|
||||||
|
checkRandomAccessCollection(
|
||||||
|
expected, ablPtrWrapper, SourceLocStack().withCurrentLoc())
|
||||||
free(ablPtrWrapper.unsafeMutablePointer)
|
free(ablPtrWrapper.unsafeMutablePointer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2168,7 +2168,9 @@ class NonContiguousNSString : NSString {
|
|||||||
|
|
||||||
func checkUTF8View(expected: [UInt8], subject: String,
|
func checkUTF8View(expected: [UInt8], subject: String,
|
||||||
stackTrace: SourceLocStack) {
|
stackTrace: SourceLocStack) {
|
||||||
checkCollection(expected, subject.utf8, stackTrace.withCurrentLoc())
|
checkForwardCollection(
|
||||||
|
expected, subject.utf8,
|
||||||
|
stackTrace.withCurrentLoc())
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkUTF16View(expected: [UInt16], subject: String,
|
func checkUTF16View(expected: [UInt16], subject: String,
|
||||||
|
|||||||
Reference in New Issue
Block a user