aboutsummaryrefslogtreecommitdiff
path: root/Sources/NorgKit/Helpers/ASCIIByteSet.swift
diff options
context:
space:
mode:
Diffstat (limited to 'Sources/NorgKit/Helpers/ASCIIByteSet.swift')
-rw-r--r--Sources/NorgKit/Helpers/ASCIIByteSet.swift30
1 files changed, 30 insertions, 0 deletions
diff --git a/Sources/NorgKit/Helpers/ASCIIByteSet.swift b/Sources/NorgKit/Helpers/ASCIIByteSet.swift
new file mode 100644
index 0000000..59efbe7
--- /dev/null
+++ b/Sources/NorgKit/Helpers/ASCIIByteSet.swift
@@ -0,0 +1,30 @@
+/// A membership test over the ASCII range (bytes `0`–`127`)
+/// We use this for performance, since markers are always ASCII, and this this
+/// faster than using Character.
+struct ASCIIByteSet {
+ private let low: UInt64
+ private let high: UInt64
+
+ /// Builds a set from the ASCII values.
+ init(_ characters: String) {
+ var lo: UInt64 = 0
+ var hi: UInt64 = 0
+ for byte in characters.utf8 {
+ if byte < 64 {
+ lo |= 1 << UInt64(byte)
+ } else if byte < 128 {
+ hi |= 1 << UInt64(byte - 64)
+ }
+ }
+ low = lo
+ high = hi
+ }
+
+ /// Whether `byte` is in the set.
+ @inline(__always)
+ func contains(_ byte: UInt8) -> Bool {
+ if byte < 64 { return low & (1 << UInt64(byte)) != 0 }
+ if byte < 128 { return high & (1 << UInt64(byte &- 64)) != 0 }
+ return false
+ }
+}