Skip to content

Commit 0000114

Browse files
committed
Initial commit
0 parents  commit 0000114

7 files changed

Lines changed: 237 additions & 0 deletions

File tree

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
/*.xcodeproj
5+
xcuserdata/
6+
DerivedData/
7+
.swiftpm/config/registries.json
8+
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
9+
.netrc

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

Package.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// swift-tools-version: 5.7
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "StringContainsOperators",
8+
products: [
9+
// Products define the executables and libraries a package produces, and make them visible to other packages.
10+
.library(
11+
name: "StringContainsOperators",
12+
targets: ["StringContainsOperators"]),
13+
],
14+
dependencies: [
15+
// Dependencies declare other packages that this package depends on.
16+
// .package(url: /* package url */, from: "1.0.0"),
17+
],
18+
targets: [
19+
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
20+
// Targets can depend on other targets in this package, and on products in packages this package depends on.
21+
.target(
22+
name: "StringContainsOperators",
23+
dependencies: []),
24+
.testTarget(
25+
name: "StringContainsOperatorsTests",
26+
dependencies: ["StringContainsOperators"]),
27+
]
28+
)

README.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# StringContainsOperators
2+
3+
StringContainsOperators is a Swift library for creating and evaluating complex string predicates using custom operators. This library provides an easy-to-use and flexible solution for matching strings against complex patterns.
4+
5+
## How to Use
6+
7+
The library provides three main components: custom operators, an enum type, and an extension to the String class.
8+
9+
## Custom Operators
10+
11+
StringContainsOperators provides two custom operators: || and &&. These operators are used to create OR and AND predicates, respectively, between two strings or between a string and another predicate.
12+
13+
For example, you can create an OR predicate between two strings as follows:
14+
15+
```swift
16+
let predicate = "hello" || "world"
17+
```
18+
This creates a predicate that matches any string that contains either "hello" or "world". Similarly, you can create an AND predicate between two strings like this:
19+
20+
```swift
21+
let predicate = "hello" && "world"
22+
```
23+
This creates a predicate that matches any string that contains both "hello" and "world".
24+
25+
## Enum Type
26+
27+
The resulting predicate is represented by an enum type called StringPredicate. This enum type can be either a base predicate, an OR predicate, or an AND predicate.
28+
29+
## Extension to String
30+
31+
The contains() function, which is an extension of the String class, is used to evaluate whether a given string satisfies a particular predicate. The function takes a StringPredicate as input and returns a boolean value indicating whether the predicate is true or false.
32+
33+
```swift
34+
let result = "hello world".contains("hello" || "world")
35+
print(result) // true
36+
```
37+
38+
## How to Install
39+
40+
### SPM
41+
42+
You can install StringContainsOperators using Swift Package Manager (SPM). Simply add the following line to your dependencies in your Package.swift file:
43+
44+
```swift
45+
.package(url: "https://github.com/Tavernari/StringContainsOperators.git", from: "1.0.0")
46+
```
47+
48+
### Cocoapods
49+
50+
You can also install StringContainsOperators using CocoaPods. Simply add the following line to your Podfile:
51+
52+
```ruby
53+
pod 'StringContainsOperators', '~> 1.0'
54+
```
55+
56+
## Contributions
57+
58+
Contributions to StringContainsOperators are welcome! Before making a pull request, please open an issue to discuss your proposed changes. We follow the GitHub Flow for our development process.
59+
60+
Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import Foundation
2+
3+
infix operator || : LogicalDisjunctionPrecedence
4+
infix operator && : LogicalConjunctionPrecedence
5+
6+
public indirect enum StringPredicate {
7+
case base(StringPredicate)
8+
case or([String])
9+
case orPredicates(String, StringPredicate)
10+
case and([String])
11+
case andPredicates(String, StringPredicate)
12+
}
13+
14+
public func || (lhs: String, rhs: String) -> StringPredicate {
15+
16+
return .base(.or([lhs, rhs]))
17+
}
18+
19+
public func || (lhs: String, rhs: StringPredicate) -> StringPredicate {
20+
21+
return .orPredicates(lhs, rhs)
22+
}
23+
24+
public func || (lhs: StringPredicate, rhs: String) -> StringPredicate {
25+
26+
return .orPredicates(rhs, lhs)
27+
}
28+
29+
public func && (lhs: String, rhs: String) -> StringPredicate {
30+
31+
return .base(.and([lhs, rhs]))
32+
}
33+
34+
public func && (lhs: String, rhs: StringPredicate) -> StringPredicate {
35+
36+
return .andPredicates(lhs, rhs)
37+
}
38+
39+
public func && (lhs: StringPredicate, rhs: String) -> StringPredicate {
40+
41+
return .andPredicates(rhs, lhs)
42+
}
43+
44+
public extension String {
45+
func contains(_ predicate: StringPredicate) -> Bool {
46+
47+
switch predicate {
48+
49+
case let .base(predicate):
50+
return self.contains(predicate)
51+
52+
case let .or(strings):
53+
return strings.contains(where: self.contains)
54+
55+
case let .orPredicates(value, predicate):
56+
return self.contains(predicate) || self.contains(.or([value]))
57+
58+
case let .and(strings):
59+
return strings.allSatisfy(self.contains)
60+
61+
case let .andPredicates(value, predicate):
62+
return self.contains(predicate) && self.contains(.and([value]))
63+
}
64+
}
65+
}
66+
67+

StringContainsOperators.podspec

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Pod::Spec.new do |s|
2+
s.name = "StringContainsOperators"
3+
s.version = "1.0.0"
4+
s.summary = "A Swift library for creating and evaluating complex string predicates using custom operators."
5+
s.description = "StringContainsOperators provides custom operators and an enum type to create complex string predicates, which can be evaluated using the contains() function. This library is designed to be easy to use and flexible, allowing developers to create powerful string matching logic with minimal code."
6+
s.homepage = "https://github.com/Tavernari/StringContainsOperators"
7+
s.license = "MIT"
8+
s.author = { "Victor Carvalho Tavernari" => "victortavernari@gmail.com" }
9+
s.source = { :git => "https://github.com/Tavernari/StringContainsOperators.git", :tag => "#{s.version}" }
10+
s.source_files = "Sources/**/*.swift"
11+
s.ios.deployment_target = '11.0'
12+
s.osx.deployment_target = '10.13'
13+
end
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import XCTest
2+
@testable import StringContainsOperators
3+
4+
final class StringContainsOperatorsTests: XCTestCase {
5+
6+
func testBaseStringPredicate() {
7+
let predicate = "Hello" || "World"
8+
XCTAssertTrue("Hello".contains(predicate))
9+
XCTAssertTrue("World".contains(predicate))
10+
XCTAssertFalse("Goodbye".contains(predicate))
11+
}
12+
13+
func testOrStringPredicate() {
14+
let predicate = "Hello" || "World" || "Goodbye"
15+
XCTAssertTrue("Hello".contains(predicate))
16+
XCTAssertTrue("World".contains(predicate))
17+
XCTAssertTrue("Goodbye".contains(predicate))
18+
XCTAssertFalse("Goodnight".contains(predicate))
19+
}
20+
21+
func testOrPredicates() {
22+
let predicate = "Hello" || ("W" && "o" && "r" && "l" && "d")
23+
XCTAssertTrue("Hello".contains(predicate))
24+
XCTAssertTrue("World".contains(predicate))
25+
XCTAssertFalse("Goodbye".contains(predicate))
26+
XCTAssertFalse("Hey".contains(predicate))
27+
}
28+
29+
func testAndStringPredicate() {
30+
let predicate = "Hello" && "World"
31+
XCTAssertTrue("HelloWorld".contains(predicate))
32+
XCTAssertFalse("Hello".contains(predicate))
33+
XCTAssertFalse("World".contains(predicate))
34+
XCTAssertFalse("Goodbye".contains(predicate))
35+
}
36+
37+
func testAndPredicates() {
38+
let predicate = "H" && ("e" || "i") && "llo"
39+
XCTAssertTrue("Hello".contains(predicate))
40+
XCTAssertTrue("Hillo".contains(predicate))
41+
XCTAssertFalse("Hallo".contains(predicate))
42+
XCTAssertFalse("Hiyo".contains(predicate))
43+
}
44+
45+
func testIndirectStringPredicate() {
46+
let predicate = ("Hello" || "World") && "!"
47+
XCTAssertTrue("Hello!".contains(predicate))
48+
XCTAssertTrue("World!".contains(predicate))
49+
XCTAssertFalse("Hello".contains(predicate))
50+
}
51+
52+
func testNestedStringPredicate() {
53+
let predicate = "Hello" || ("W" && ("o" || "i") && "r" && "l" && "d")
54+
XCTAssertTrue("Hello".contains(predicate))
55+
XCTAssertTrue("World".contains(predicate))
56+
XCTAssertTrue("Wirld".contains(predicate))
57+
XCTAssertFalse("Goodbye".contains(predicate))
58+
}
59+
}

0 commit comments

Comments
 (0)