1
0
Fork 0

Codechange: Replace sscanf with StringConsumer.

pull/14161/head
frosch 2025-04-29 13:30:56 +02:00 committed by frosch
parent 8027e31f47
commit e7d758c82a
2 changed files with 45 additions and 39 deletions

View File

@ -1156,70 +1156,72 @@ void NetworkGameLoop()
char buff[4096];
if (fgets(buff, lengthof(buff), *f) == nullptr) break;
char *p = buff;
StringConsumer consumer{std::string_view{buff}};
/* Ignore the "[date time] " part of the message */
if (*p == '[') {
p = strchr(p, ']');
if (p == nullptr) break;
p += 2;
if (consumer.ReadCharIf('[')) {
consumer.SkipUntilChar(']', StringConsumer::SKIP_ONE_SEPARATOR);
consumer.SkipCharIf(' ');
}
if (strncmp(p, "cmd: ", 5) == 0
if (consumer.ReadIf("cmd: ")
#ifdef DEBUG_FAILED_DUMP_COMMANDS
|| strncmp(p, "cmdf: ", 6) == 0
|| consumer.ReadIf("cmdf: ")
#endif
) {
p += 5;
if (*p == ' ') p++;
cp = new CommandPacket();
int company;
uint cmd;
char buffer[256];
uint32_t next_date_raw;
int ret = sscanf(p, "%x; %x; %x; %x; %x; %255s", &next_date_raw, &next_date_fract, &company, &cmd, &cp->err_msg, buffer);
assert(ret == 6);
next_date = TimerGameEconomy::Date((int32_t)next_date_raw);
cp->company = (CompanyID)company;
cp->cmd = (Commands)cmd;
next_date = TimerGameEconomy::Date(consumer.ReadIntegerBase<uint32_t>(16));
bool valid = consumer.ReadIf("; ");
next_date_fract = consumer.ReadIntegerBase<uint32_t>(16);
valid &= consumer.ReadIf("; ");
cp->company = static_cast<CompanyID>(consumer.ReadIntegerBase<uint16_t>(16));
valid &= consumer.ReadIf("; ");
cp->cmd = static_cast<Commands>(consumer.ReadIntegerBase<uint32_t>(16));
valid &= consumer.ReadIf("; ");
cp->err_msg = consumer.ReadIntegerBase<uint32_t>(16);
valid &= consumer.ReadIf("; ");
auto args = consumer.ReadUntilChar(' ', StringConsumer::SKIP_ONE_SEPARATOR);
assert(valid);
/* Parse command data. */
std::vector<uint8_t> args;
size_t arg_len = strlen(buffer);
for (size_t i = 0; i + 1 < arg_len; i += 2) {
cp->data.clear();
for (size_t i = 0; i + 1 < args.size(); i += 2) {
uint8_t e = 0;
std::from_chars(buffer + i, buffer + i + 2, e, 16);
args.emplace_back(e);
cp->data.push_back(e);
}
cp->data = args;
} else if (strncmp(p, "join: ", 6) == 0) {
} else if (consumer.ReadIf("join: ")) {
/* Manually insert a pause when joining; this way the client can join at the exact right time. */
uint32_t next_date_raw;
int ret = sscanf(p + 6, "%x; %x", &next_date_raw, &next_date_fract);
next_date = TimerGameEconomy::Date((int32_t)next_date_raw);
assert(ret == 2);
next_date = TimerGameEconomy::Date(consumer.ReadIntegerBase<uint32_t>(16));
bool valid = consumer.ReadIf("; ");
next_date_fract = consumer.ReadIntegerBase<uint32_t>(16);
assert(valid);
Debug(desync, 0, "Injecting pause for join at {:08x}:{:02x}; please join when paused", next_date, next_date_fract);
cp = new CommandPacket();
cp->company = COMPANY_SPECTATOR;
cp->cmd = CMD_PAUSE;
cp->data = EndianBufferWriter<>::FromValue(CommandTraits<CMD_PAUSE>::Args{ PauseMode::Normal, true });
_ddc_fastforward = false;
} else if (strncmp(p, "sync: ", 6) == 0) {
uint32_t next_date_raw;
int ret = sscanf(p + 6, "%x; %x; %x; %x", &next_date_raw, &next_date_fract, &sync_state[0], &sync_state[1]);
next_date = TimerGameEconomy::Date((int32_t)next_date_raw);
assert(ret == 4);
} else if (consumer.ReadIf("sync: ")) {
next_date = TimerGameEconomy::Date(consumer.ReadIntegerBase<uint32_t>(16));
bool valid = consumer.ReadIf("; ");
next_date_fract = consumer.ReadIntegerBase<uint32_t>(16);
valid &= consumer.ReadIf("; ");
sync_state[0] = consumer.ReadIntegerBase<uint32_t>(16);
valid &= consumer.ReadIf("; ");
sync_state[1] = consumer.ReadIntegerBase<uint32_t>(16);
assert(valid);
check_sync_state = true;
} else if (strncmp(p, "msg: ", 5) == 0 || strncmp(p, "client: ", 8) == 0 ||
strncmp(p, "load: ", 6) == 0 || strncmp(p, "save: ", 6) == 0 ||
strncmp(p, "warning: ", 9) == 0) {
} else if (consumer.ReadIf("msg: ") || consumer.ReadIf("client: ") ||
consumer.ReadIf("load: ") || consumer.ReadIf("save: ") ||
consumer.ReadIf("warning: ")) {
/* A message that is not very important to the log playback, but part of the log. */
#ifndef DEBUG_FAILED_DUMP_COMMANDS
} else if (strncmp(p, "cmdf: ", 6) == 0) {
Debug(desync, 0, "Skipping replay of failed command: {}", p + 6);
} else if (consumer.ReadIf("cmdf: ")) {
Debug(desync, 0, "Skipping replay of failed command: {}", consumer.Read(StringConsumer::npos));
#endif
} else {
/* Can't parse a line; what's wrong here? */
Debug(desync, 0, "Trying to parse: {}", p);
Debug(desync, 0, "Trying to parse: {}", consumer.Read(StringConsumer::npos));
NOT_REACHED();
}
}

View File

@ -47,6 +47,10 @@
/* No clear replacement. */
#define strtok SAFEGUARD_DO_NOT_USE_THIS_METHOD
/* Use StringConsumer instead. */
#define sscanf SAFEGUARD_DO_NOT_USE_THIS_METHOD
#define from_string SAFEGUARD_DO_NOT_USE_THIS_METHOD
/* Use fmt::print instead. */
#define printf SAFEGUARD_DO_NOT_USE_THIS_METHOD
#define fprintf SAFEGUARD_DO_NOT_USE_THIS_METHOD