-
Notifications
You must be signed in to change notification settings - Fork 10
/
steno_key_state.cc
120 lines (103 loc) · 3.36 KB
/
steno_key_state.cc
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
114
115
116
117
118
119
120
//---------------------------------------------------------------------------
#include "steno_key_state.h"
#include <assert.h>
//---------------------------------------------------------------------------
#define USE_CTZLL 1
//---------------------------------------------------------------------------
int8_t StenoKeyState::STROKE_BIT_INDEX_LOOKUP[] = {
StrokeBitIndex::SL, // S1
StrokeBitIndex::SL, // S2
StrokeBitIndex::TL, // TL
StrokeBitIndex::KL, // KL
StrokeBitIndex::PL, // PL
StrokeBitIndex::WL, // WL
StrokeBitIndex::HL, // HL
StrokeBitIndex::RL, // RL
StrokeBitIndex::A, // A
StrokeBitIndex::O, // O
StrokeBitIndex::STAR, // STAR1
StrokeBitIndex::STAR, // STAR2
StrokeBitIndex::STAR, // STAR3
StrokeBitIndex::STAR, // STAR4
StrokeBitIndex::E, // E
StrokeBitIndex::U, // U
StrokeBitIndex::FR, // FR
StrokeBitIndex::RR, // RR
StrokeBitIndex::PR, // PR
StrokeBitIndex::BR, // BR
StrokeBitIndex::LR, // LR
StrokeBitIndex::GR, // GR
StrokeBitIndex::TR, // TR
StrokeBitIndex::SR, // SR
StrokeBitIndex::DR, // DR
StrokeBitIndex::ZR, // ZR
StrokeBitIndex::NUM, // NUM1
StrokeBitIndex::NUM, // NUM2
StrokeBitIndex::NUM, // NUM3
StrokeBitIndex::NUM, // NUM4
StrokeBitIndex::NUM, // NUM5
StrokeBitIndex::NUM, // NUM6
StrokeBitIndex::NUM, // NUM7
StrokeBitIndex::NUM, // NUM8
StrokeBitIndex::NUM, // NUM9
StrokeBitIndex::NUM, // NUM10
StrokeBitIndex::NUM, // NUM11
StrokeBitIndex::NUM, // NUM12
StrokeBitIndex::NONE, // FUNCTION
StrokeBitIndex::NONE, // POWER
StrokeBitIndex::NONE, // RES1
StrokeBitIndex::NONE, // RES2
};
static_assert(sizeof(StenoKeyState::STROKE_BIT_INDEX_LOOKUP) ==
(int)StenoKey::COUNT,
"StrokeBitIndex table must be complete");
//---------------------------------------------------------------------------
void StenoKeyState::Process(StenoKey key, bool isPress) {
if (isPress) {
keyState |= 1ULL << (int)key;
} else {
keyState &= ~(1ULL << (int)key);
}
}
StenoStroke StenoKeyState::ToStroke() const {
uint32_t strokeKeyState = 0;
#if USE_CTZLL
uint64_t localKeyState = keyState;
while (localKeyState) {
const int index = __builtin_ctzll(localKeyState);
const int shift = STROKE_BIT_INDEX_LOOKUP[index];
if (shift != -1) {
strokeKeyState |= 1UL << shift;
}
// Zero the lowest bit.
localKeyState &= localKeyState - 1;
}
#else
for (size_t i = 0; i < sizeof(STROKE_BIT_INDEX_LOOKUP); ++i) {
if (keyState & (1ULL << i)) {
int shift = STROKE_BIT_INDEX_LOOKUP[i];
if (shift != -1) {
strokeKeyState |= 1UL << shift;
}
}
}
#endif
return StenoStroke(strokeKeyState);
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include "unit_test.h"
#include <string.h>
TEST_BEGIN("StenoKeyState tests") {
char buffer[StenoStroke::MAX_STRING_LENGTH];
StenoKeyState state;
state.Process(StenoKey::HL, true);
state.Process(StenoKey::LR, true);
{
const StenoStroke stroke = state.ToStroke();
stroke.ToString(buffer);
assert(strcmp(buffer, "H-L") == 0);
}
}
TEST_END
//---------------------------------------------------------------------------