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
106
107
108
109
110
111
112
113
|
//! Properties module
const Data = struct {
core_s1: []const u16 = undefined,
core_s2: []const u8 = undefined,
props_s1: []const u16 = undefined,
props_s2: []const u8 = undefined,
num_s1: []const u16 = undefined,
num_s2: []const u8 = undefined,
};
const properties = properties: {
const core_props = @import("core_props");
const props_data = @import("props");
const numeric = @import("numeric");
break :properties Data{
.core_s1 = &core_props.s1,
.core_s2 = &core_props.s2,
.props_s1 = &props_data.s1,
.props_s2 = &props_data.s2,
.num_s1 = &numeric.s1,
.num_s2 = &numeric.s2,
};
};
const Properties = @This();
/// True if `cp` is a mathematical symbol.
pub fn isMath(cp: u21) bool {
return properties.core_s2[properties.core_s1[cp >> 8] + (cp & 0xff)] & 1 == 1;
}
/// True if `cp` is an alphabetic character.
pub fn isAlphabetic(cp: u21) bool {
return properties.core_s2[properties.core_s1[cp >> 8] + (cp & 0xff)] & 2 == 2;
}
/// True if `cp` is a valid identifier start character.
pub fn isIdStart(cp: u21) bool {
return properties.core_s2[properties.core_s1[cp >> 8] + (cp & 0xff)] & 4 == 4;
}
/// True if `cp` is a valid identifier continuation character.
pub fn isIdContinue(cp: u21) bool {
return properties.core_s2[properties.core_s1[cp >> 8] + (cp & 0xff)] & 8 == 8;
}
/// True if `cp` is a valid extended identifier start character.
pub fn isXidStart(cp: u21) bool {
return properties.core_s2[properties.core_s1[cp >> 8] + (cp & 0xff)] & 16 == 16;
}
/// True if `cp` is a valid extended identifier continuation character.
pub fn isXidContinue(cp: u21) bool {
return properties.core_s2[properties.core_s1[cp >> 8] + (cp & 0xff)] & 32 == 32;
}
/// True if `cp` is a whitespace character.
pub fn isWhitespace(cp: u21) bool {
return properties.props_s2[properties.props_s1[cp >> 8] + (cp & 0xff)] & 1 == 1;
}
/// True if `cp` is a hexadecimal digit.
pub fn isHexDigit(cp: u21) bool {
return properties.props_s2[properties.props_s1[cp >> 8] + (cp & 0xff)] & 2 == 2;
}
/// True if `cp` is a diacritic mark.
pub fn isDiacritic(cp: u21) bool {
return properties.props_s2[properties.props_s1[cp >> 8] + (cp & 0xff)] & 4 == 4;
}
/// True if `cp` is numeric.
pub fn isNumeric(cp: u21) bool {
return properties.num_s2[properties.num_s1[cp >> 8] + (cp & 0xff)] & 1 == 1;
}
/// True if `cp` is a digit.
pub fn isDigit(cp: u21) bool {
return properties.num_s2[properties.num_s1[cp >> 8] + (cp & 0xff)] & 2 == 2;
}
/// True if `cp` is decimal.
pub fn isDecimal(cp: u21) bool {
return properties.num_s2[properties.num_s1[cp >> 8] + (cp & 0xff)] & 4 == 4;
}
test "Props" {
try testing.expect(Properties.isHexDigit('F'));
try testing.expect(Properties.isHexDigit('a'));
try testing.expect(Properties.isHexDigit('8'));
try testing.expect(!Properties.isHexDigit('z'));
try testing.expect(Properties.isDiacritic('\u{301}'));
try testing.expect(Properties.isAlphabetic('A'));
try testing.expect(!Properties.isAlphabetic('3'));
try testing.expect(Properties.isMath('+'));
try testing.expect(Properties.isNumeric('\u{277f}'));
try testing.expect(Properties.isDigit('\u{2070}'));
try testing.expect(Properties.isDecimal('3'));
try testing.expect(!Properties.isNumeric('1'));
try testing.expect(!Properties.isDigit('2'));
try testing.expect(!Properties.isDecimal('g'));
}
const std = @import("std");
const builtin = @import("builtin");
const compress = std.compress;
const mem = std.mem;
const Allocator = mem.Allocator;
const testing = std.testing;
|