Skip to content

Commit

Permalink
Regex matching
Browse files Browse the repository at this point in the history
  • Loading branch information
trasch committed Sep 5, 2024
1 parent d76833d commit d884b82
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 6 deletions.
24 changes: 24 additions & 0 deletions Sources/MVTTools/Extensions/StringExtensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Foundation

extension String {

public func matches(_ regex: String) -> Bool {
var options: String.CompareOptions = .regularExpression

var regex = regex
if regex.hasPrefix("/") {
regex.removeFirst()

if regex.hasSuffix("/i") {
options.insert(.caseInsensitive)
regex.removeLast(2)
}
else if regex.hasSuffix("/") {
regex.removeLast()
}
}

return self.range(of: regex, options: options) != nil
}

}
30 changes: 24 additions & 6 deletions Sources/MVTTools/QueryParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public struct QueryParser {
case greaterThanOrEqual
case lessThan
case lessThanOrEqual
case regex
}

// Conditions
Expand Down Expand Up @@ -69,6 +70,14 @@ public struct QueryParser {
else { return false }

stack.insert(compare(first: first, second: second, condition: condition), at: 0)

case .regex:
guard stack.count >= 2,
let regex = stack.removeFirst() as? String,
let value = stack.removeFirst() as? String
else { return false }

stack.insert(value.matches(regex), at: 0)
}

case let .condition(condition):
Expand Down Expand Up @@ -178,12 +187,21 @@ public struct QueryParser {

private func compare<T: Comparable>(left: T, right: T, condition: QueryParser.Expression.Comparison) -> Bool {
switch condition {
case .equals: left == right
case .notEquals: left != right
case .greaterThan: left > right
case .greaterThanOrEqual: left >= right
case .lessThan: left < right
case .lessThanOrEqual: left <= right
case .equals:
return left == right
case .notEquals:
return left != right
case .greaterThan:
return left > right
case .greaterThanOrEqual:
return left >= right
case .lessThan:
return left < right
case .lessThanOrEqual:
return left <= right
case .regex:
guard let value = left as? String, let regex = right as? String else { return false }
return value.matches(regex)
}
}

Expand Down
5 changes: 5 additions & 0 deletions Tests/MVTToolsTests/QueryParserTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ final class QueryParserTests: XCTestCase {
"b",
],
"value": 1,
"string": "Some name"
]

private func result(for pipeline: [QueryParser.Expression]) -> Bool {
Expand Down Expand Up @@ -40,6 +41,10 @@ final class QueryParserTests: XCTestCase {
XCTAssertTrue(result(for: [.valueFor(["value"]), .literal(1), .comparison(.lessThanOrEqual)]))
XCTAssertTrue(result(for: [.valueFor(["value"]), .literal(1.5), .comparison(.lessThanOrEqual)]))
XCTAssertFalse(result(for: [.valueFor(["x"]), .literal(1), .comparison(.equals)]))
XCTAssertTrue(result(for: [.valueFor(["string"]), .literal("name$"), .comparison(.regex)]))
XCTAssertTrue(result(for: [.valueFor(["string"]), .literal("/[Ss]ome/"), .comparison(.regex)]))
XCTAssertFalse(result(for: [.valueFor(["string"]), .literal("^some"), .comparison(.regex)]))
XCTAssertTrue(result(for: [.valueFor(["string"]), .literal("/^some/i"), .comparison(.regex)]))
}

func testConditions() throws {
Expand Down

0 comments on commit d884b82

Please sign in to comment.