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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
// TODO: Probably refactor out of DSLTree
extension DSLTree.CustomCharacterClass {
internal struct AsciiBitset {
let isInverted: Bool
var a: UInt64 = 0
var b: UInt64 = 0
init(isInverted: Bool) {
self.isInverted = isInverted
}
init(_ val: UInt8, _ isInverted: Bool, _ isCaseInsensitive: Bool) {
self.isInverted = isInverted
add(val, isCaseInsensitive)
}
init(low: UInt8, high: UInt8, isInverted: Bool, isCaseInsensitive: Bool) {
self.isInverted = isInverted
for val in low...high {
add(val, isCaseInsensitive)
}
}
internal init(
a: UInt64,
b: UInt64,
isInverted: Bool
) {
self.isInverted = isInverted
self.a = a
self.b = b
}
internal mutating func add(_ val: UInt8, _ isCaseInsensitive: Bool) {
setBit(val)
if isCaseInsensitive {
switch val {
case 64...90: setBit(val + 32)
case 97...122: setBit(val - 32)
default: break
}
}
}
internal mutating func setBit(_ val: UInt8) {
if val < 64 {
a = a | 1 << val
} else {
b = b | 1 << (val - 64)
}
}
private func _matchesWithoutInversionCheck(_ val: UInt8) -> Bool {
if val < 64 {
return (a >> val) & 1 == 1
} else {
return (b >> (val - 64)) & 1 == 1
}
}
internal func matches(_ byte: UInt8) -> Bool {
guard byte < 128 else { return isInverted }
return _matchesWithoutInversionCheck(byte) == !isInverted
}
internal func matches(_ char: Character) -> Bool {
let matched: Bool
if let val = char._singleScalarAsciiValue {
matched = _matchesWithoutInversionCheck(val)
} else {
matched = false
}
if isInverted {
return !matched
}
return matched
}
internal func matches(_ scalar: Unicode.Scalar) -> Bool {
let matched: Bool
if scalar.isASCII {
let val = UInt8(ascii: scalar)
matched = _matchesWithoutInversionCheck(val)
} else {
matched = false
}
if isInverted {
return !matched
}
return matched
}
/// Joins another bitset from a Member of the same CustomCharacterClass
internal func union(_ other: AsciiBitset) -> AsciiBitset {
precondition(self.isInverted == other.isInverted)
return AsciiBitset(
a: self.a | other.a,
b: self.b | other.b,
isInverted: self.isInverted
)
}
}
}
|