mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 10:53:44 +00:00
feat(common): read the memory text the client sends at login
The login request's memoryStats is a run of short parts with no separators (process working set and private bytes, memory load, physical memory, commit limit, the 32-bit client's own address space, peaks). ParseMemoryStats splits it into numbers; a text cut short keeps the parts before the cut. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
61
dCommon/ClientSysInfo.cpp
Normal file
61
dCommon/ClientSysInfo.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "ClientSysInfo.h"
|
||||
|
||||
#include <array>
|
||||
#include <cctype>
|
||||
#include <charconv>
|
||||
|
||||
namespace {
|
||||
struct Reader {
|
||||
std::string_view text;
|
||||
size_t pos{};
|
||||
|
||||
void SkipSpace() {
|
||||
while (pos < text.size() && std::isspace(static_cast<unsigned char>(text[pos]))) pos++;
|
||||
}
|
||||
|
||||
bool Literal(std::string_view literal) {
|
||||
SkipSpace();
|
||||
if (text.substr(pos, literal.size()) != literal) return false;
|
||||
pos += literal.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<int64_t> Number() {
|
||||
SkipSpace();
|
||||
int64_t value{};
|
||||
const auto* begin = text.data() + pos;
|
||||
const auto [end, error] = std::from_chars(begin, text.data() + text.size(), value);
|
||||
if (error != std::errc{} || end == begin) return std::nullopt;
|
||||
pos += static_cast<size_t>(end - begin);
|
||||
return value;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ClientSysInfo::MemoryStats ClientSysInfo::ParseMemoryStats(const std::string_view text) {
|
||||
MemoryStats stats;
|
||||
// Each part: text before the number, text after it, and where the number goes
|
||||
struct Part { std::string_view prefix; std::string_view suffix; std::optional<int64_t> MemoryStats::* field; };
|
||||
const std::array<Part, 11> parts{ {
|
||||
{ "", "p,", &MemoryStats::workingSetBytes },
|
||||
{ "", "vbytes.", &MemoryStats::pagefileUsageBytes },
|
||||
{ "", "n-use.", &MemoryStats::memoryLoadPercent },
|
||||
{ "", "TKb-pmem.", &MemoryStats::totalPhysKb },
|
||||
{ "", "FKb pmem.", &MemoryStats::availPhysKb },
|
||||
{ "", "TKb pfile.", &MemoryStats::totalPageFileKb },
|
||||
{ "", "FKb pfile.", &MemoryStats::availPageFileKb },
|
||||
{ "", "TKbytes vmem.", &MemoryStats::totalVirtualKb },
|
||||
{ "", "FKb vmem.", &MemoryStats::availVirtualKb },
|
||||
{ "P", "p,", &MemoryStats::peakWorkingSetBytes },
|
||||
{ "", "v.", &MemoryStats::peakPagefileUsageBytes },
|
||||
} };
|
||||
Reader reader{ text };
|
||||
for (const auto& part : parts) {
|
||||
if (!part.prefix.empty() && !reader.Literal(part.prefix)) return stats;
|
||||
const auto value = reader.Number();
|
||||
if (!value || !reader.Literal(part.suffix)) return stats;
|
||||
stats.*part.field = *value;
|
||||
}
|
||||
stats.complete = true;
|
||||
return stats;
|
||||
}
|
||||
Reference in New Issue
Block a user