-
Notifications
You must be signed in to change notification settings - Fork 16
/
StringExtensions.swift
82 lines (66 loc) · 2.54 KB
/
StringExtensions.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import Foundation
public extension String {
init(apnDeviceToken: Data) {
/// Convert `Data` to `String` for APN device token.
/// [Reference](https://nshipster.com/apns-device-tokens/)
self = apnDeviceToken.map { String(format: "%02x", $0) }.joined()
}
var data: Data! {
data(using: .utf8)
}
var url: URL? {
URL(string: self)
}
static var abcLetters: String {
"abcdefghijklmnopqrstuvwxyz"
}
func getFirstNCharacters(_ numberOfCharacters: Int) -> String {
self[0 ..< numberOfCharacters]
}
static var random: String {
String.random()
}
static func random(length: Int = 10) -> String {
String((0 ..< length).map { _ in abcLetters.randomElement()! })
}
/**
Checks if the string matches the regex pattern.
Will only return true if the *full string* is matched, not a substring.
*/
func matches(regex: String) -> Bool {
// Force try because we are assuming that all regex patterns are hard-coded into
// the source code and therefore can be tested with an automated test.
// swiftlint:disable:next force_try
let regex = try! NSRegularExpression(pattern: regex, options: [])
let range = NSRange(location: 0, length: utf16.count)
let match = regex.firstMatch(in: self, options: [], range: range)
// By checking the ranges equal, we are asserting that the regex didn't just match
// a subset of the string meaning it may not match the whole string.
return match != nil && match?.range == range
}
/// Given: "foo" and input ".jpg", return "foo.jpg"
/// Given: "foo.jpg" and input ".jpg", return "foo.jpg" (unmodified)
func setLastCharacters(_ characters: String) -> String {
if hasSuffix(characters) { return self }
return self + characters
}
func isBlankOrEmpty() -> Bool {
trimmingCharacters(in: .whitespaces).isEmpty
}
/// Substrings
/// let s = "hello"
/// s[0..<3] // "hel"
/// s[3...] // "lo"
subscript(_ range: CountableRange<Int>) -> String {
let start = index(startIndex, offsetBy: max(0, range.lowerBound))
let end = index(start, offsetBy: min(
count - range.lowerBound,
range.upperBound - range.lowerBound
))
return String(self[start ..< end])
}
subscript(_ range: CountablePartialRangeFrom<Int>) -> String {
let start = index(startIndex, offsetBy: max(0, range.lowerBound))
return String(self[start...])
}
}