-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathctrl_stream_writer.cpp
More file actions
157 lines (128 loc) · 4.68 KB
/
Copy pathctrl_stream_writer.cpp
File metadata and controls
157 lines (128 loc) · 4.68 KB
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ctrl_stream_writer.cpp
#include "misc.h"
#include "ctrl_stream_writer.h"
//=============================================================================
// CtrlStreamWriter - primitive helpers
//=============================================================================
CtrlStreamWriter::CtrlStreamWriter(std::ostream &out) : m_out(out) {}
void CtrlStreamWriter::writeU8(uint8_t v)
{
if (m_buf)
m_buf->push_back(static_cast<char>(v));
else
m_out.put(static_cast<char>(v));
}
void CtrlStreamWriter::writeU16(uint16_t v)
{
writeU8(static_cast<uint8_t>(v & 0xFF));
writeU8(static_cast<uint8_t>((v >> 8) & 0xFF));
}
void CtrlStreamWriter::writeU32(uint32_t v)
{
writeU8(static_cast<uint8_t>(v & 0xFF));
writeU8(static_cast<uint8_t>((v >> 8) & 0xFF));
writeU8(static_cast<uint8_t>((v >> 16) & 0xFF));
writeU8(static_cast<uint8_t>((v >> 24) & 0xFF));
}
void CtrlStreamWriter::writeI32(int32_t v)
{
writeU32(static_cast<uint32_t>(v));
}
void CtrlStreamWriter::writeU64(uint64_t v)
{
writeU32(static_cast<uint32_t>(v & 0xFFFFFFFF));
writeU32(static_cast<uint32_t>((v >> 32) & 0xFFFFFFFF));
}
void CtrlStreamWriter::writeString(const wstringi &s)
{
uint16_t len = static_cast<uint16_t>(s.size());
writeU16(len);
for (size_t i = 0; i < len; ++i) {
wchar_t ch = s[i];
writeU8(static_cast<uint8_t>(ch & 0xFF));
writeU8(static_cast<uint8_t>((ch >> 8) & 0xFF));
}
}
//=============================================================================
// CtrlStreamWriter - command writers
//=============================================================================
void CtrlStreamWriter::writeStart(const wstringi &configName,
const wstringi &configPath,
const Symbols &syms,
LogLevel logLevel)
{
writeU8(static_cast<uint8_t>(CtrlId::Start));
writeString(configName);
writeString(configPath);
writeU16(static_cast<uint16_t>(syms.size()));
for (const auto &sym : syms)
writeString(sym);
writeU8(static_cast<uint8_t>(logLevel));
m_out.flush();
}
void CtrlStreamWriter::writeSetLogLevel(LogLevel logLevel)
{
writeU8(static_cast<uint8_t>(CtrlId::SetLogLevel));
writeU8(static_cast<uint8_t>(logLevel));
m_out.flush();
}
void CtrlStreamWriter::writeQuit()
{
writeU8(static_cast<uint8_t>(CtrlId::Quit));
m_out.flush();
}
// Same tags and layout as CmdStreamWriter::writeArgument(), so an argument
// means the same thing whichever way it travels. The visit deliberately has
// no catch-all: a FuncArg alternative that is not handled here has to fail to
// compile rather than be dropped from the stream.
void CtrlStreamWriter::writeFuncArg(const FuncArg &arg)
{
std::visit(overloaded{
[&](const FuncArgString& a) { writeU8(FuncArgTag_String); writeString(a); },
[&](const FuncArgNumber& a) { writeU8(FuncArgTag_Number); writeI32(a); },
[&](const FuncArgRegexp& a) { writeU8(FuncArgTag_Regexp); writeString(a.str()); },
[&](const FuncArgKeySeqIdx& a) { writeU8(FuncArgTag_KeySeqIdx); writeU32(a); },
[&](const FuncArgModifierSpec& a) {
writeU8(FuncArgTag_ModifierSpec);
writeU64(a.modifiers);
writeU64(a.dontcares);
},
[&](const FuncArgTokenSeq& a) {
writeU8(FuncArgTag_TokenSeq);
writeU16(static_cast<uint16_t>(a.size()));
for (const auto &t : a)
writeString(t);
},
[&](const FuncArgDollarName& a) {
// funcExecUserFunc() resolves these before they reach us, because
// only the engine knows what $Clipboard stands for. Should one
// arrive anyway, send the name rather than lose the argument.
writeU8(FuncArgTag_String);
writeString(a.m_name);
},
}, arg);
}
void CtrlStreamWriter::writeExecUserFunc(const wstringi &funcName,
const std::vector<FuncArg> &args,
const TriggerInfo &ctx)
{
// Serialize the arguments before the count that describes them reaches the
// stream. The reader cannot recover if the two disagree: it would read the
// bytes that follow as an argument and then block waiting for the rest of a
// string that is never coming, taking every later request down with it.
std::string payload;
m_buf = &payload;
for (const auto &arg : args)
writeFuncArg(arg);
m_buf = nullptr;
writeU8(static_cast<uint8_t>(CtrlId::ExecUserFunc));
writeString(funcName);
writeU16(static_cast<uint16_t>(args.size()));
m_out.write(payload.data(), static_cast<std::streamsize>(payload.size()));
writeU8(ctx.scanCode);
writeU8(ctx.extended ? 1 : 0);
writeString(wstringi(ctx.windowClass));
writeString(wstringi(ctx.windowTitle));
m_out.flush();
}