SourcePP
Several modern C++20 libraries for sanely parsing Valve's formats.
Toggle main menu visibility
Loading...
Searching...
No Matches
CmdSeq.cpp
Go to the documentation of this file.
1
// ReSharper disable CppRedundantQualifier
2
3
#include <
toolpp/CmdSeq.h
>
4
5
#include <cstring>
6
#include <format>
7
8
#include <FileStream.h>
9
#include <
kvpp/kvpp.h
>
10
#include <
sourcepp/String.h
>
11
12
using namespace
kvpp
;
13
using namespace
sourcepp
;
14
using namespace
toolpp
;
15
16
namespace
{
17
18
CmdSeq::Command::Special
specialCmdFromString(std::string_view specialCmd) {
19
using
enum
CmdSeq::Command::Special
;
20
if
(
string::iequals
(specialCmd,
"change_dir"
)) {
21
return
CHANGE_DIRECTORY;
22
}
23
if
(
string::iequals
(specialCmd,
"copy_file"
)) {
24
return
COPY_FILE;
25
}
26
if
(
string::iequals
(specialCmd,
"delete_file"
)) {
27
return
DELETE_FILE;
28
}
29
if
(
string::iequals
(specialCmd,
"rename_file"
)) {
30
return
RENAME_FILE;
31
}
32
if
(
string::iequals
(specialCmd,
"copy_file_if_exists"
)) {
33
return
COPY_FILE_IF_EXISTS;
34
}
35
return
NONE
;
36
}
37
38
}
// namespace
39
40
std::string
CmdSeq::Command::getSpecialDisplayNameFor
(
Special
special
) {
41
switch
(
special
) {
42
case
Special::NONE
:
43
break
;
44
case
Special::CHANGE_DIRECTORY
:
45
return
"Change Directory"
;
46
case
Special::COPY_FILE
:
47
return
"Copy File"
;
48
case
Special::DELETE_FILE
:
49
return
"Delete File"
;
50
case
Special::RENAME_FILE
:
51
return
"Rename File"
;
52
case
Special::COPY_FILE_IF_EXISTS
:
53
return
"Copy File If It Exists"
;
54
}
55
return
"None"
;
56
}
57
58
std::string
CmdSeq::Command::getExecutableDisplayName
()
const
{
59
if
(this->
special
!=
Command::Special::NONE
) {
60
return
getSpecialDisplayNameFor
(this->
special
);
61
}
62
return
this->
executable
;
63
}
64
65
CmdSeq::CmdSeq
(
Type
type_)
66
:
type
(type_)
67
,
version
(0.2f) {}
68
69
CmdSeq::CmdSeq
(
const
std::filesystem::path& cmdSeqPath)
70
:
type
(
Type
::INVALID)
71
,
version
(0.2f) {
72
{
73
FileStream reader{cmdSeqPath};
74
if
(!reader) {
75
return
;
76
}
77
if
(
const
auto
binStr = reader.seek_in(0).read_string(10); binStr ==
"Worldcraft"
) {
78
this->
type
=
Type::BINARY
;
79
}
else
{
80
auto
kvStr = reader.seek_in(0).read_string(19);
81
string::toLower
(kvStr);
82
if
(kvStr ==
"\"command sequences\""
) {
83
this->
type
= cmdSeqPath.extension() ==
".cfg"
?
Type::KEYVALUES_HPP
:
Type::KEYVALUES_STRATA
;
84
}
else
{
85
return
;
86
}
87
}
88
}
89
switch
(this->
type
) {
90
using
enum
Type
;
91
case
INVALID:
92
break
;
93
case
BINARY:
94
this->
parseBinary
(cmdSeqPath);
95
break
;
96
case
KEYVALUES_HPP:
97
this->
parseKeyValuesHPP
(cmdSeqPath);
98
break
;
99
case
KEYVALUES_STRATA:
100
this->
parseKeyValuesStrata
(cmdSeqPath);
101
break
;
102
}
103
}
104
105
CmdSeq::operator bool()
const
{
106
return
this->
type
!=
Type::INVALID
;
107
}
108
109
CmdSeq::Type
CmdSeq::getType
()
const
{
110
return
this->
type
;
111
}
112
113
void
CmdSeq::setType
(
Type
type_) {
114
this->
type
= type_;
115
}
116
117
float
CmdSeq::getBinaryVersion
()
const
{
118
return
this->
version
;
119
}
120
121
void
CmdSeq::setBinaryVersion
(
bool
isV02) {
122
if
(isV02) {
123
this->
version
= 0.2f;
124
}
else
{
125
this->
version
= 0.1f;
126
}
127
}
128
129
void
CmdSeq::parseBinary
(
const
std::filesystem::path& path) {
130
FileStream reader{path};
131
if
(!reader) {
132
return
;
133
}
134
135
reader.seek_in(31).read(this->
version
);
136
137
const
auto
sequenceCount = reader.read<uint32_t>();
138
for
(uint32_t s = 0; s < sequenceCount; s++) {
139
auto
& [seqName, seqCommands] = this->
sequences
.emplace_back();
140
seqName = reader.read_string(128);
141
142
const
auto
commandCount = reader.read<uint32_t>();
143
for
(uint32_t c = 0; c < commandCount; c++) {
144
auto
& [enabled, special, executable, arguments, ensureFileExists, pathToTheoreticallyExistingFile, useProcessWindow, waitForKeypress] = seqCommands.emplace_back();
145
enabled = reader.read<int32_t>() & 0xFF;
146
special = reader.read<
Command::Special
>();
147
if
(special ==
static_cast<
Command::Special
>
(
Command::SPECIAL_COPY_FILE_IF_EXISTS_ALIAS
)) {
148
special =
Command::Special::COPY_FILE_IF_EXISTS
;
149
}
150
executable = reader.read_string(260);
151
arguments = reader.read_string(260);
152
reader.skip_in<int32_t>();
153
ensureFileExists = reader.read<int32_t>();
154
pathToTheoreticallyExistingFile = reader.read_string(260);
155
useProcessWindow = reader.read<int32_t>();
156
if
(
version
> 0.15f) {
157
waitForKeypress = reader.read<int32_t>();
158
}
159
}
160
}
161
}
162
163
void
CmdSeq::parseKeyValuesHPP
(
const
std::filesystem::path& path) {
164
this->
version
= 0.2f;
165
166
const
KV1
cmdSeq{
fs::readFileText
(path)};
167
for
(
const
auto
& kvSequence : cmdSeq[
"Command Sequences"
].getChildren()) {
168
auto
& [seqName, seqCommands] = this->
sequences
.emplace_back();
169
seqName = kvSequence.getKey();
170
171
for
(
const
auto
& kvCommand : kvSequence.getChildren()) {
172
auto
& [enabled, special, executable, arguments, ensureFileExists, pathToTheoreticallyExistingFile, useProcessWindow, waitForKeypress] = seqCommands.emplace_back();
173
string::toBool
(kvCommand[
"enable"
].getValue(), enabled);
174
if
(
175
const
auto
specialCmd = kvCommand[
"specialcmd"
].getValue();
176
string::toInt
(specialCmd,
reinterpret_cast<
std::underlying_type_t<Command::Special>&
>
(special))
177
) {
178
if
(special ==
Command::SPECIAL_COPY_FILE_IF_EXISTS_ALIAS
) {
179
special =
Command::Special::COPY_FILE_IF_EXISTS
;
180
}
181
}
else
{
182
special = ::specialCmdFromString(specialCmd);
183
}
184
executable = kvCommand[
"run"
].getValue();
185
arguments = kvCommand[
"parms"
].getValue();
186
}
187
}
188
}
189
190
void
CmdSeq::parseKeyValuesStrata
(
const
std::filesystem::path& path) {
191
this->
version
= 0.2f;
192
193
const
KV1
cmdSeq{
fs::readFileText
(path)};
194
for
(
const
auto
& kvSequence : cmdSeq[
"Command Sequences"
].getChildren()) {
195
auto
& [seqName, seqCommands] = this->
sequences
.emplace_back();
196
seqName = kvSequence.getKey();
197
198
for
(
const
auto
& kvCommand : kvSequence.getChildren()) {
199
auto
& [enabled, special, executable, arguments, ensureFileExists, pathToTheoreticallyExistingFile, useProcessWindow, waitForKeypress] = seqCommands.emplace_back();
200
string::toBool
(kvCommand[
"enabled"
].getValue(), enabled);
201
if
(
202
const
auto
specialCmd = kvCommand[
"special_cmd"
].getValue();
203
string::toInt
(specialCmd,
reinterpret_cast<
std::underlying_type_t<Command::Special>&
>
(special))
204
) {
205
if
(special ==
Command::SPECIAL_COPY_FILE_IF_EXISTS_ALIAS
) {
206
special =
Command::Special::COPY_FILE_IF_EXISTS
;
207
}
208
}
else
{
209
special = ::specialCmdFromString(specialCmd);
210
}
211
executable = kvCommand[
"run"
].getValue();
212
arguments = kvCommand[
"params"
].getValue();
213
string::toBool
(kvCommand[
"ensure_check"
].getValue(), ensureFileExists);
214
pathToTheoreticallyExistingFile = kvCommand[
"ensure_fn"
].getValue();
215
string::toBool
(kvCommand[
"use_process_wnd"
].getValue(), useProcessWindow);
216
string::toBool
(kvCommand[
"no_wait"
].getValue(), waitForKeypress);
217
}
218
}
219
}
220
221
std::vector<CmdSeq::Sequence>&
CmdSeq::getSequences
() {
222
return
this->
sequences
;
223
}
224
225
const
std::vector<CmdSeq::Sequence>&
CmdSeq::getSequences
()
const
{
226
return
this->
sequences
;
227
}
228
229
std::vector<std::byte>
CmdSeq::bakeBinary
()
const
{
230
std::vector<std::byte> out;
231
BufferStream writer{out};
232
233
writer
234
.write(
"Worldcraft Command Sequences\r\n\x1a"
, 31)
235
.write<
float
>(this->
getBinaryVersion
())
236
.write<uint32_t>(this->
getSequences
().size());
237
238
for
(
const
auto
& [seqName, seqCommands] : this->
getSequences
()) {
239
writer
240
.write(seqName,
true
, 128)
241
.write<uint32_t>(seqCommands.size());
242
243
for
(
const
auto
& [enabled, special, executable, arguments, ensureFileExists, pathToTheoreticallyExistingFile, useProcessWindow, waitForKeypress] : seqCommands) {
244
writer
245
.write<uint32_t>(enabled)
246
.write(special)
247
.write(executable,
true
, 260)
248
.write(arguments,
true
, 260)
249
.write<uint32_t>(
true
)
250
.write<uint32_t>(ensureFileExists)
251
.write(pathToTheoreticallyExistingFile,
true
, 260)
252
.write<uint32_t>(useProcessWindow);
253
254
if
(this->
getBinaryVersion
() > 0.15f) {
255
writer.write<uint32_t>(waitForKeypress);
256
}
257
}
258
}
259
260
out.resize(writer.size());
261
return
out;
262
}
263
264
std::vector<std::byte>
CmdSeq::bakeKeyValuesHPP
()
const
{
265
KV1Writer
kv;
266
auto
& kvFile = kv.
addChild
(
"Command Sequences"
);
267
for
(
const
auto
& [seqName, seqCommands] : this->
getSequences
()) {
268
auto
& kvSequence = kvFile.addChild(seqName);
269
for
(
int
i = 1; i <= seqCommands.size(); i++) {
270
const
auto
& [enabled, special, executable, arguments, ensureFileExists, pathToTheoreticallyExistingFile, useProcessWindow, waitForKeypress] = seqCommands[i - 1];
271
auto
& kvCommand = kvSequence.addChild(std::format(
"{}"
, i));
272
kvCommand[
"enable"
] = enabled;
273
kvCommand[
"specialcmd"
] =
static_cast<
int
>
(special);
274
kvCommand[
"run"
] = executable;
275
kvCommand[
"parms"
] = arguments;
276
}
277
}
278
279
const
auto
kvStr = kv.
bake
();
280
std::vector<std::byte> out;
281
out.resize(kvStr.length());
282
std::memcpy(out.data(), kvStr.data(), kvStr.length());
283
return
out;
284
}
285
286
std::vector<std::byte>
CmdSeq::bakeKeyValuesStrata
()
const
{
287
KV1Writer
kv;
288
auto
& kvFile = kv.
addChild
(
"Command Sequences"
);
289
for
(
const
auto
& [seqName, seqCommands] : this->
getSequences
()) {
290
auto
& kvSequence = kvFile.addChild(seqName);
291
for
(
int
i = 1; i <= seqCommands.size(); i++) {
292
const
auto
& [enabled, special, executable, arguments, ensureFileExists, pathToTheoreticallyExistingFile, useProcessWindow, waitForKeypress] = seqCommands[i - 1];
293
auto
& kvCommand = kvSequence.addChild(std::format(
"{}"
, i));
294
kvCommand[
"enabled"
] = enabled;
295
kvCommand[
"special_cmd"
] =
static_cast<
int
>
(special);
296
kvCommand[
"run"
] = executable;
297
kvCommand[
"params"
] = arguments;
298
kvCommand[
"ensure_check"
] = ensureFileExists;
299
kvCommand[
"ensure_fn"
] = pathToTheoreticallyExistingFile;
300
kvCommand[
"use_process_wnd"
] = useProcessWindow;
301
kvCommand[
"no_wait"
] = waitForKeypress;
302
}
303
}
304
305
const
auto
kvStr = kv.
bake
();
306
std::vector<std::byte> out;
307
out.resize(kvStr.length());
308
std::memcpy(out.data(), kvStr.data(), kvStr.length());
309
return
out;
310
}
311
312
std::vector<std::byte>
CmdSeq::bake
()
const
{
313
switch
(this->
type
) {
314
using
enum
Type
;
315
case
INVALID:
316
return
{};
317
case
BINARY:
318
return
this->
bakeBinary
();
319
case
KEYVALUES_HPP:
320
return
this->
bakeKeyValuesHPP
();
321
case
KEYVALUES_STRATA:
322
return
this->
bakeKeyValuesStrata
();
323
}
324
return
{};
325
}
326
327
bool
CmdSeq::bake
(
const
std::filesystem::path& path)
const
{
328
FileStream writer{path};
329
if
(!writer) {
330
return
false
;
331
}
332
writer.seek_out(0).write(this->
bake
());
333
return
true
;
334
}
CmdSeq.h
String.h
kvpp::KV1ElementWritable::addChild
KV1ElementWritable & addChild(std::string_view key_, V value_={}, std::string_view conditional_="")
Definition
KV1Writer.h:89
kvpp::KV1Writer
Definition
KV1Writer.h:347
kvpp::KV1Writer::bake
std::string bake() const
Definition
KV1Writer.h:365
kvpp::KV1
Definition
KV1.h:216
toolpp::CmdSeq::parseKeyValuesHPP
void parseKeyValuesHPP(const std::filesystem::path &path)
Definition
CmdSeq.cpp:163
toolpp::CmdSeq::bake
std::vector< std::byte > bake() const
Definition
CmdSeq.cpp:312
toolpp::CmdSeq::getBinaryVersion
float getBinaryVersion() const
Definition
CmdSeq.cpp:117
toolpp::CmdSeq::setBinaryVersion
void setBinaryVersion(bool isV02)
Definition
CmdSeq.cpp:121
toolpp::CmdSeq::getType
Type getType() const
Definition
CmdSeq.cpp:109
toolpp::CmdSeq::parseKeyValuesStrata
void parseKeyValuesStrata(const std::filesystem::path &path)
Definition
CmdSeq.cpp:190
toolpp::CmdSeq::CmdSeq
CmdSeq(Type type_)
Definition
CmdSeq.cpp:65
toolpp::CmdSeq::Type
Type
Definition
CmdSeq.h:48
toolpp::CmdSeq::Type::KEYVALUES_HPP
@ KEYVALUES_HPP
Definition
CmdSeq.h:51
toolpp::CmdSeq::Type::KEYVALUES_STRATA
@ KEYVALUES_STRATA
Definition
CmdSeq.h:52
toolpp::CmdSeq::Type::BINARY
@ BINARY
Definition
CmdSeq.h:50
toolpp::CmdSeq::Type::INVALID
@ INVALID
Definition
CmdSeq.h:49
toolpp::CmdSeq::setType
void setType(Type type_)
Definition
CmdSeq.cpp:113
toolpp::CmdSeq::bakeKeyValuesStrata
std::vector< std::byte > bakeKeyValuesStrata() const
Definition
CmdSeq.cpp:286
toolpp::CmdSeq::getSequences
std::vector< Sequence > & getSequences()
Definition
CmdSeq.cpp:221
toolpp::CmdSeq::parseBinary
void parseBinary(const std::filesystem::path &path)
Definition
CmdSeq.cpp:129
toolpp::CmdSeq::type
Type type
Definition
CmdSeq.h:90
toolpp::CmdSeq::sequences
std::vector< Sequence > sequences
Definition
CmdSeq.h:92
toolpp::CmdSeq::bakeKeyValuesHPP
std::vector< std::byte > bakeKeyValuesHPP() const
Definition
CmdSeq.cpp:264
toolpp::CmdSeq::version
float version
Definition
CmdSeq.h:91
toolpp::CmdSeq::bakeBinary
std::vector< std::byte > bakeBinary() const
Definition
CmdSeq.cpp:229
kvpp.h
kvpp
Definition
DMX.h:13
sourcepp::fs::readFileText
std::string readFileText(const std::filesystem::path &filepath, std::size_t startOffset=0)
Definition
FS.cpp:22
sourcepp::string::toBool
bool toBool(std::string_view number, bool &out, int base=10)
Definition
String.cpp:280
sourcepp::string::toInt
bool toInt(std::string_view number, std::integral auto &out, int base=10)
Definition
String.h:141
sourcepp::string::iequals
bool iequals(std::string_view s1, std::string_view s2)
Definition
String.cpp:96
sourcepp::string::toLower
void toLower(std::string &input)
Definition
String.cpp:200
sourcepp
Definition
LZMA.h:11
toolpp
Definition
CmdSeq.h:9
vpkpp::Attribute::NONE
@ NONE
Definition
Attribute.h:8
toolpp::CmdSeq::Command::executable
std::string executable
Definition
CmdSeq.h:28
toolpp::CmdSeq::Command::getExecutableDisplayName
std::string getExecutableDisplayName() const
Definition
CmdSeq.cpp:58
toolpp::CmdSeq::Command::special
enum toolpp::CmdSeq::Command::Special special
toolpp::CmdSeq::Command::SPECIAL_COPY_FILE_IF_EXISTS_ALIAS
static constexpr auto SPECIAL_COPY_FILE_IF_EXISTS_ALIAS
Definition
CmdSeq.h:26
toolpp::CmdSeq::Command::Special
Special
Definition
CmdSeq.h:16
toolpp::CmdSeq::Command::Special::DELETE_FILE
@ DELETE_FILE
Definition
CmdSeq.h:20
toolpp::CmdSeq::Command::Special::COPY_FILE
@ COPY_FILE
Definition
CmdSeq.h:19
toolpp::CmdSeq::Command::Special::COPY_FILE_IF_EXISTS
@ COPY_FILE_IF_EXISTS
Definition
CmdSeq.h:24
toolpp::CmdSeq::Command::Special::NONE
@ NONE
Definition
CmdSeq.h:17
toolpp::CmdSeq::Command::Special::CHANGE_DIRECTORY
@ CHANGE_DIRECTORY
Definition
CmdSeq.h:18
toolpp::CmdSeq::Command::Special::RENAME_FILE
@ RENAME_FILE
Definition
CmdSeq.h:21
toolpp::CmdSeq::Command::getSpecialDisplayNameFor
static std::string getSpecialDisplayNameFor(Special special)
Definition
CmdSeq.cpp:40
src
toolpp
CmdSeq.cpp
Generated on
for SourcePP by
1.18.0