11// Copyright © 2018 Christian Tietze. All rights reserved. Distributed under the MIT License.
22
3- public protocol ExpressionSatisfiable {
3+ /// Literal string matching.
4+ public protocol StringExpressionSatisfiable {
45 func contains( phrase: String ) -> Bool
56}
67
7- extension String : ExpressionSatisfiable {
8+ /// The fastest search on earch is `strstr(haystack, needle)` with lowercased string.
9+ /// This provides the needle as UTF-8, lowercased, precomposed string with canonical mapping.
10+ public protocol CStringExpressionSatisfiable {
11+ func matches( needle: ContainsNode . CString ) -> Bool
12+ }
13+
14+ extension String : StringExpressionSatisfiable {
815 public func contains( phrase: String ) -> Bool {
916 return self . contains ( phrase)
1017 }
1118}
1219
1320public protocol Expression {
14- func isSatisfied( by satisfiable: ExpressionSatisfiable ) -> Bool
21+ func isSatisfied( by satisfiable: StringExpressionSatisfiable ) -> Bool
22+ func isSatisfied( by satisfiable: CStringExpressionSatisfiable ) -> Bool
1523}
1624
1725/// Wildcard that is satisfied by any string.
1826public struct AnythingNode : Expression {
19- public func isSatisfied( by satisfiable: ExpressionSatisfiable ) -> Bool {
27+ public func isSatisfied( by satisfiable: StringExpressionSatisfiable ) -> Bool {
28+ return true
29+ }
30+
31+ public func isSatisfied( by satisfiable: CStringExpressionSatisfiable ) -> Bool {
2032 return true
2133 }
2234}
2335
2436public struct ContainsNode : Expression {
37+ public typealias CString = [ CChar ]
2538 public let string : String
39+ public let cString : CString
40+
41+ public static var cStringFactory : ( String ) -> CString = ContainsNode . cString ( string: )
42+
43+ public static func cString( string: String ) -> CString {
44+ return string. precomposedStringWithCanonicalMapping
45+ . lowercased ( )
46+ . cString ( using: . utf8) ?? [ ]
47+ }
2648
2749 public init ( _ string: String ) {
2850 self . string = string
51+ self . cString = ContainsNode . cStringFactory ( string)
2952 }
3053
3154 public init ( token: Token ) {
3255 self . init ( token. string)
3356 }
3457
35- public func isSatisfied( by satisfiable: ExpressionSatisfiable ) -> Bool {
58+ public func isSatisfied( by satisfiable: StringExpressionSatisfiable ) -> Bool {
3659 return satisfiable. contains ( phrase: string)
3760 }
61+
62+ public func isSatisfied( by satisfiable: CStringExpressionSatisfiable ) -> Bool {
63+ return satisfiable. matches ( needle: cString)
64+ }
3865}
3966
4067public struct NotNode : Expression {
@@ -44,7 +71,11 @@ public struct NotNode: Expression {
4471 self . expression = expression
4572 }
4673
47- public func isSatisfied( by satisfiable: ExpressionSatisfiable ) -> Bool {
74+ public func isSatisfied( by satisfiable: StringExpressionSatisfiable ) -> Bool {
75+ return !expression. isSatisfied ( by: satisfiable)
76+ }
77+
78+ public func isSatisfied( by satisfiable: CStringExpressionSatisfiable ) -> Bool {
4879 return !expression. isSatisfied ( by: satisfiable)
4980 }
5081}
@@ -58,7 +89,11 @@ public struct AndNode: Expression {
5889 self . rhs = rhs
5990 }
6091
61- public func isSatisfied( by satisfiable: ExpressionSatisfiable ) -> Bool {
92+ public func isSatisfied( by satisfiable: StringExpressionSatisfiable ) -> Bool {
93+ return lhs. isSatisfied ( by: satisfiable) && rhs. isSatisfied ( by: satisfiable)
94+ }
95+
96+ public func isSatisfied( by satisfiable: CStringExpressionSatisfiable ) -> Bool {
6297 return lhs. isSatisfied ( by: satisfiable) && rhs. isSatisfied ( by: satisfiable)
6398 }
6499}
@@ -72,7 +107,11 @@ public struct OrNode: Expression {
72107 self . rhs = rhs
73108 }
74109
75- public func isSatisfied( by satisfiable: ExpressionSatisfiable ) -> Bool {
110+ public func isSatisfied( by satisfiable: StringExpressionSatisfiable ) -> Bool {
111+ return lhs. isSatisfied ( by: satisfiable) || rhs. isSatisfied ( by: satisfiable)
112+ }
113+
114+ public func isSatisfied( by satisfiable: CStringExpressionSatisfiable ) -> Bool {
76115 return lhs. isSatisfied ( by: satisfiable) || rhs. isSatisfied ( by: satisfiable)
77116 }
78117}
0 commit comments