Making the tests & the API nicer.
Signed-off-by: Adam Rocska <adam.rocska@adams.solutions>
This commit is contained in:
parent
028b7ae23d
commit
e06afd3d7a
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.id="." external.linked.project.path="$MODULE_DIR$/." external.root.project.path="$MODULE_DIR$" external.system.id="SPM" type="CPP_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
|
@ -4,6 +4,7 @@
|
|||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/../../.idea/..iml" filepath="$PROJECT_DIR$/../../.idea/..iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/GeoIP2-swift.iml" filepath="$PROJECT_DIR$/.idea/GeoIP2-swift.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/../.idea/GeoIP2-swift...iml" filepath="$PROJECT_DIR$/../.idea/GeoIP2-swift...iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -1,22 +1,25 @@
|
|||
import Foundation
|
||||
|
||||
extension Data {
|
||||
func index(of data: Data) -> Index? {
|
||||
|
||||
fileprivate func boyerMoore(data: Data, from: Index) -> Index? {
|
||||
let patternLength = data.count
|
||||
precondition(patternLength > 0)
|
||||
precondition(self.count >= patternLength)
|
||||
precondition(patternLength > 0, "Pattern can't be empty.")
|
||||
precondition(self.count >= patternLength, "Pattern can't be >= than the Data to search in.")
|
||||
precondition(data.indices.contains(from), "Index from which to start the lookup must be contained in the Data.")
|
||||
|
||||
var skipTable = [UInt8: Int]()
|
||||
for (i, byte) in data.enumerated() {
|
||||
skipTable[byte] = patternLength - i - 1
|
||||
}
|
||||
|
||||
let lastByteIndexOfData = data.index(before: data.endIndex)
|
||||
let lastByteOfData = data.last
|
||||
var i = self.index(self.startIndex, offsetBy: patternLength - 1)
|
||||
let lastIndexOfSelf = self.endIndex
|
||||
let lastIndexOfData = data.index(before: data.endIndex)
|
||||
let lastByteOfData = data.last
|
||||
var i = self.index(from, offsetBy: patternLength - 1, limitedBy: lastIndexOfSelf) ?? lastIndexOfSelf
|
||||
|
||||
func reverseMatch() -> Index? {
|
||||
var dataIndex = lastByteIndexOfData
|
||||
var dataIndex = lastIndexOfData
|
||||
var selfIndex = i
|
||||
while dataIndex > data.startIndex {
|
||||
selfIndex = self.index(before: selfIndex)
|
||||
|
@ -38,10 +41,19 @@ extension Data {
|
|||
i = self.index(
|
||||
i,
|
||||
offsetBy: skipTable[byte] ?? patternLength,
|
||||
limitedBy: self.endIndex
|
||||
) ?? self.endIndex
|
||||
limitedBy: lastIndexOfSelf
|
||||
) ?? lastIndexOfSelf
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func index(of data: Data) -> Index? {
|
||||
return boyerMoore(data: data, from: self.startIndex)
|
||||
}
|
||||
|
||||
func index(of data: Data, from: Index) -> Index? {
|
||||
return boyerMoore(data: data, from: from)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,37 +2,32 @@ import Foundation
|
|||
import XCTest
|
||||
@testable import MaxMindDBReader
|
||||
|
||||
fileprivate extension String {
|
||||
var asciiData: Data { get { return self.data(using: .ascii) ?? Data() } }
|
||||
}
|
||||
|
||||
class IndexOfData: XCTestCase {
|
||||
private typealias TestDefinition = (sequence: Data, subsequence: Data, expectedIndex: Data.Index?)
|
||||
|
||||
private func testDefinition(sequence: String, subsequence: String, expectedIndex: Int?) -> TestDefinition? {
|
||||
guard let dataSequence = sequence.data(using: .ascii) else {
|
||||
XCTFail("Could not represent sequence String as Data using ASCII encoding.")
|
||||
return nil
|
||||
}
|
||||
guard let dataSubsequence = subsequence.data(using: .ascii) else {
|
||||
XCTFail("Could not represent subsequence String as Data using ASCII encoding.")
|
||||
return nil
|
||||
}
|
||||
return (
|
||||
sequence: dataSequence,
|
||||
subsequence: dataSubsequence,
|
||||
sequence: sequence.asciiData,
|
||||
subsequence: subsequence.asciiData,
|
||||
expectedIndex: expectedIndex
|
||||
)
|
||||
}
|
||||
|
||||
func testIndexOfData() {
|
||||
func testIndex_ofData() {
|
||||
let testDefinitions = [
|
||||
testDefinition(sequence: "Hello World", subsequence: "World", expectedIndex: 6),
|
||||
testDefinition(sequence: "Hello world", subsequence: "World", expectedIndex: nil),
|
||||
testDefinition(sequence: "Hello World SOME World", subsequence: "World", expectedIndex: 6),
|
||||
testDefinition(sequence: "Hello world SOME World", subsequence: "World", expectedIndex: 17),
|
||||
|
||||
testDefinition(sequence: "Hello World", subsequence: "Hello", expectedIndex: 0),
|
||||
testDefinition(sequence: "hello World", subsequence: "hello", expectedIndex: 0),
|
||||
testDefinition(sequence: "hello world", subsequence: "Hello", expectedIndex: nil),
|
||||
testDefinition(sequence: "hello World SOME World", subsequence: "Hello", expectedIndex: nil),
|
||||
testDefinition(sequence: "hello world SOME World", subsequence: "Hello", expectedIndex: nil)
|
||||
(sequence: "Hello World".asciiData, subsequence: "World".asciiData, expectedIndex: 6),
|
||||
(sequence: "Hello world".asciiData, subsequence: "World".asciiData, expectedIndex: nil),
|
||||
(sequence: "Hello World SOME World".asciiData, subsequence: "World".asciiData, expectedIndex: 6),
|
||||
(sequence: "Hello world SOME World".asciiData, subsequence: "World".asciiData, expectedIndex: 17),
|
||||
(sequence: "Hello World".asciiData, subsequence: "Hello".asciiData, expectedIndex: 0),
|
||||
(sequence: "hello World".asciiData, subsequence: "hello".asciiData, expectedIndex: 0),
|
||||
(sequence: "hello world".asciiData, subsequence: "Hello".asciiData, expectedIndex: nil),
|
||||
(sequence: "hello World SOME World".asciiData, subsequence: "Hello".asciiData, expectedIndex: nil),
|
||||
(sequence: "hello world SOME World".asciiData, subsequence: "Hello".asciiData, expectedIndex: nil)
|
||||
]
|
||||
|
||||
for testDefinition in testDefinitions.compactMap({ $0 }) {
|
||||
|
@ -42,4 +37,8 @@ class IndexOfData: XCTestCase {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
func testIndex_ofData_fromIndex() {
|
||||
XCTAssertEqual(12, "Hello World Hello World".asciiData.index(of: "Hello World".asciiData, from: 3))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue