Files
DevilutionX/Source/utils/str_cat.cpp
T
Gleb MazovetskiyandClaude Fable 5 ac2d7fc731 Replace libfmt with std::format
- `fmt::format` with literal format strings -> `std::format`.
- `fmt::format(fmt::runtime(...))` -> `FormatRuntime` in the new
  `utils/format.hpp`, a std::vformat wrapper that is also safe under the
  P2905 lvalue requirement of `std::make_format_args`.
- `fmt::dynamic_format_arg_store` (Lua logging) -> a small hand-rolled
  per-field formatter over `std::variant`, returning `std::expected`.
- `fmt::format_int` -> `std::to_chars`.
- `fmt::join` -> manual joins at the two call sites.
- SDL_audiolib: new patch that rewrites aulib_log.h to use std::format
  and drops the fmt dependency from its CMakeLists.
- The `-static-libstdc++` guard now keys off
  `DEVILUTIONX_STATIC_SDL_AUDIOLIB` instead of `DEVILUTIONX_STATIC_LIBFMT`.
- libfmt removed from CMake, vcpkg, Brewfile, CI workflows,
  Dockerfiles, packaging scripts, UWP project, and docs.
- macOS bumped to 13.3+, iOS to 16.3+ (required for `<format>`)
- Amiga m68k: provide `__cmpdf2`, which is missing from the hard-float
  libgcc multilib but referenced via libstdc++'s long double paths.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-22 00:00:04 +02:00

79 lines
2.1 KiB
C++

#include "utils/str_cat.hpp"
#include <charconv>
#include <cstdint>
#include <cstring>
namespace devilution {
namespace {
[[nodiscard]] char HexDigit(uint8_t v) { return "0123456789abcdef"[v]; }
[[nodiscard]] char HexDigitUpper(uint8_t v) { return "0123456789ABCDEF"[v]; }
} // namespace
char *BufCopy(char *out, long long value)
{
char buf[MaxNumDigits<long long>];
char *end = std::to_chars(buf, buf + sizeof(buf), value).ptr;
std::memcpy(out, buf, end - buf);
return out + (end - buf);
}
char *BufCopy(char *out, unsigned long long value)
{
char buf[MaxNumDigits<unsigned long long>];
char *end = std::to_chars(buf, buf + sizeof(buf), value).ptr;
std::memcpy(out, buf, end - buf);
return out + (end - buf);
}
char *BufCopy(char *out, AsHexU8Pad2 value)
{
if (value.uppercase) {
*out++ = HexDigitUpper(value.value >> 4);
*out++ = HexDigitUpper(value.value & 0xf);
} else {
*out++ = HexDigit(value.value >> 4);
*out++ = HexDigit(value.value & 0xf);
}
return out;
}
char *BufCopy(char *out, AsHexU16Pad2 value)
{
if (value.value > 0xff) {
if (value.value > 0xfff) {
out = BufCopy(out, AsHexU8Pad2 { static_cast<uint8_t>(value.value >> 8) });
} else {
*out++ = value.uppercase ? HexDigitUpper(value.value >> 8) : HexDigit(value.value >> 8);
}
}
return BufCopy(out, AsHexU8Pad2 { static_cast<uint8_t>(value.value & 0xff) });
}
void StrAppend(std::string &out, long long value)
{
char buf[MaxNumDigits<long long>];
char *end = std::to_chars(buf, buf + sizeof(buf), value).ptr;
out.append(buf, end);
}
void StrAppend(std::string &out, unsigned long long value)
{
char buf[MaxNumDigits<unsigned long long>];
char *end = std::to_chars(buf, buf + sizeof(buf), value).ptr;
out.append(buf, end);
}
void StrAppend(std::string &out, AsHexU8Pad2 value)
{
char hex[2];
BufCopy(hex, value);
out.append(hex, 2);
}
void StrAppend(std::string &out, AsHexU16Pad2 value)
{
char hex[4];
const auto len = static_cast<size_t>(BufCopy(hex, value) - hex);
out.append(hex, len);
}
} // namespace devilution