Files
tech5/source/shared/idlib/text/cmdargs.h
T
2026-08-08 13:54:26 -07:00

119 lines
3.2 KiB
C++

#pragma once
#include <cctype>
#include <cstring>
class idCmdArgs {
public:
idCmdArgs()
: argc(0) {
tokenized[0] = '\0';
}
idCmdArgs(const char* text, const bool keepAsStrings)
: idCmdArgs() {
TokenizeString(text, keepAsStrings);
}
idCmdArgs& operator=(const idCmdArgs& other) {
if (this == &other) {
return *this;
}
Clear();
for (int index = 0; index < other.argc; ++index) {
AppendArg(other.argv[index]);
}
return *this;
}
int Argc() const {
return argc;
}
const char* Argv(const int arg) const {
return arg >= 0 && arg < argc ? argv[arg] : "";
}
void Clear() {
argc = 0;
tokenized[0] = '\0';
}
void AppendArg(const char* text) {
if (argc >= 64) {
return;
}
const char* const source = text == nullptr ? "" : text;
int used = 0;
for (int index = 0; index < argc; ++index) {
used += static_cast<int>(std::strlen(argv[index])) + 1;
}
const int length = static_cast<int>(std::strlen(source));
if (used + length + 1 > 2048) {
return;
}
argv[argc] = tokenized + used;
std::memcpy(argv[argc], source, static_cast<std::size_t>(length + 1));
++argc;
}
void TokenizeString(const char* text, const bool keepAsStrings) {
Clear();
const char* cursor = text == nullptr ? "" : text;
while (*cursor != '\0' && argc < 64) {
while (std::isspace(static_cast<unsigned char>(*cursor)) != 0) {
++cursor;
}
if (*cursor == '\0') {
break;
}
char token[2048];
int tokenLength = 0;
if (*cursor == '"') {
++cursor;
while (*cursor != '\0' && *cursor != '"'
&& tokenLength < 2047) {
token[tokenLength++] = *cursor++;
}
if (*cursor == '"') {
++cursor;
}
} else {
while (*cursor != '\0'
&& std::isspace(static_cast<unsigned char>(*cursor)) == 0
&& tokenLength < 2047) {
if (!keepAsStrings && IsPunctuation(*cursor)
&& tokenLength == 0) {
token[tokenLength++] = *cursor++;
break;
}
if (!keepAsStrings && IsPunctuation(*cursor)) {
break;
}
token[tokenLength++] = *cursor++;
}
}
token[tokenLength] = '\0';
AppendArg(token);
}
}
private:
int argc;
char* argv[64];
char tokenized[2048];
static bool IsPunctuation(const char value) {
switch (value) {
case '{': case '}': case '(': case ')':
case '[': case ']': case ',': case ';':
return true;
default:
return false;
}
}
};
static_assert(sizeof(idCmdArgs) == 2308, "Recovered idCmdArgs ABI changed");