temporary make std::print and std::format optional

This commit is contained in:
DH 2025-10-04 14:06:47 +03:00
parent d2b9b7c1f6
commit 5904079a87
26 changed files with 231 additions and 130 deletions

View file

@ -399,6 +399,7 @@ add_subdirectory(opencv EXCLUDE_FROM_ALL)
# FUSION
add_subdirectory(fusion EXCLUDE_FROM_ALL)
add_subdirectory(fmtlib)
# add nice ALIAS targets for ease of use
if(USE_SYSTEM_LIBUSB)

View file

@ -30,7 +30,6 @@
#include "lv2/sys_spu.h"
#include <cstddef>
#include <rx/format.hpp>
#include <format>
#ifdef LLVM_AVAILABLE
#ifdef _MSC_VER

View file

@ -1,10 +1,10 @@
#include "AudioOut.hpp"
#include "rx/format.hpp"
#include "rx/mem.hpp"
#include "rx/watchdog.hpp"
#include <atomic>
#include <chrono>
#include <fcntl.h>
#include <format>
#include <mutex>
#include <orbis/evf.hpp>
#include <orbis/utils/Logs.hpp>
@ -41,10 +41,10 @@ void AudioOut::channelEntry(AudioOutChannelInfo info) {
std::format_to(
control_shm_name, "{}",
rx::getShmGuestPath(std::format("shm_{}_C", info.idControl)).string());
rx::getShmGuestPath(rx::format("shm_{}_C", info.idControl)).string());
std::format_to(
audio_shm_name, "{}",
rx::getShmGuestPath(std::format("shm_{}_{}_A", info.channel, info.port))
rx::getShmGuestPath(rx::format("shm_{}_{}_A", info.channel, info.port))
.string());
int controlFd = ::open(control_shm_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);

View file

@ -2,6 +2,8 @@
#include "gpu/DeviceCtl.hpp"
#include "orbis/KernelContext.hpp"
#include "rx/Config.hpp"
#include "rx/format.hpp"
#include "rx/print.hpp"
#include <bit>
#include <chrono>
#include <csignal>
@ -10,8 +12,6 @@
#include <cstdlib>
#include <fcntl.h>
#include <filesystem>
#include <format>
#include <print>
#include <string_view>
#include <sys/mman.h>
#include <sys/socket.h>
@ -108,7 +108,7 @@ static void sendMessage(MessageId id, std::uint32_t data) {
const char *rx::getShmPath() { return g_shmPath; }
std::filesystem::path rx::getShmGuestPath(std::string_view path) {
return std::format("{}/guest/{}", getShmPath(), path);
return rx::format("{}/guest/{}", getShmPath(), path);
}
void rx::createGpuDevice() {
@ -158,7 +158,7 @@ void rx::startWatchdog() {
std::exit(-1);
}
if (!std::filesystem::create_directory(std::format("{}/guest", g_shmPath))) {
if (!std::filesystem::create_directory(rx::format("{}/guest", g_shmPath))) {
perror("failed to create guest shared memory directory");
std::exit(-1);
}
@ -231,7 +231,7 @@ void rx::startWatchdog() {
}
if (g_runGpuRequested) {
std::println("watchdog: gpu start requested");
rx::println("watchdog: gpu start requested");
g_runGpuRequested = false;
runGPU();
}

View file

@ -5,6 +5,7 @@
#include "rx/Config.hpp"
#include "rx/hexdump.hpp"
#include "rx/mem.hpp"
#include "rx/print.hpp"
#include "shader/Evaluator.hpp"
#include "shader/GcnConverter.hpp"
#include "shader/dialect.hpp"
@ -14,7 +15,6 @@
#include <cstddef>
#include <cstring>
#include <memory>
#include <print>
#include <rx/AddressRange.hpp>
#include <rx/MemoryTable.hpp>
#include <rx/die.hpp>
@ -1354,7 +1354,7 @@ Cache::Shader Cache::Tag::getShader(const ShaderKey &key,
return {};
}
std::print(stderr, "{}", shader::glsl::decompile(converted->spv));
rx::print(stderr, "{}", shader::glsl::decompile(converted->spv));
// if (auto opt = shader::spv::optimize(converted->spv)) {
// converted->spv = std::move(*opt);
// std::fprintf(stderr, "opt: %s",

View file

@ -10,7 +10,6 @@
#include <algorithm>
#include <map>
#include <memory>
#include <print>
#include <rx/ConcurrentBitPool.hpp>
#include <rx/MemoryTable.hpp>
#include <shader/gcn.hpp>

View file

@ -11,7 +11,9 @@
#include "rx/Config.hpp"
#include "rx/bits.hpp"
#include "rx/die.hpp"
#include "rx/format.hpp"
#include "rx/mem.hpp"
#include "rx/print.hpp"
#include "rx/watchdog.hpp"
#include "shader/spv.hpp"
#include "shaders/rdna-semantic-spirv.hpp"
@ -20,8 +22,6 @@
#include <chrono>
#include <cstdio>
#include <fcntl.h>
#include <format>
#include <print>
#include <stop_token>
#include <sys/mman.h>
#include <thread>
@ -34,7 +34,7 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debugUtilsMessageCallback(
const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
void *pUserData) {
if (pCallbackData->pMessage) {
std::println("{}", pCallbackData->pMessage);
rx::println("{}", pCallbackData->pMessage);
}
if (messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
@ -324,7 +324,7 @@ void Device::start() {
continue;
}
auto path = std::format("{}/dmem-{}", rx::getShmPath(), i);
auto path = rx::format("{}/dmem-{}", rx::getShmPath(), i);
if (!std::filesystem::exists(path)) {
std::println("Waiting for dmem {}", i);
@ -382,7 +382,7 @@ void Device::start() {
if (gpIndex > GLFW_JOYSTICK_LAST) {
for (int i = 0; i <= GLFW_JOYSTICK_LAST; ++i) {
if (glfwJoystickIsGamepad(i) == GLFW_TRUE) {
std::print("Gamepad \"{}\" activated", glfwGetGamepadName(i));
rx::print("Gamepad \"{}\" activated", glfwGetGamepadName(i));
gpIndex = i;
break;
}
@ -571,7 +571,7 @@ void Device::mapProcess(std::uint32_t pid, int vmId) {
auto memory = amdgpu::RemoteMemory{vmId};
std::string pidVmName = std::format("{}/memory-{}", rx::getShmPath(), pid);
std::string pidVmName = rx::format("{}/memory-{}", rx::getShmPath(), pid);
int memoryFd = ::open(pidVmName.c_str(), O_RDWR, S_IRUSR | S_IWUSR);
process.vmFd = memoryFd;

View file

@ -5,9 +5,8 @@
#include "rx/bits.hpp"
#include "rx/die.hpp"
#include "rx/format.hpp"
#include "rx/print.hpp"
#include "shader/dialect.hpp"
#include <cstdio>
#include <print>
#include <vector>
using namespace amdgpu;
@ -40,7 +39,7 @@ void DeviceCtl::submitGfxCommand(int gfxPipe, int vmId,
if ((op != gnm::IT_INDIRECT_BUFFER && op != gnm::IT_INDIRECT_BUFFER_CNST &&
op != gnm::IT_CONTEXT_CONTROL) ||
type != 3 || command.size() != len) {
std::println(stderr, "unexpected gfx command for main ring: {}, {}, {}",
rx::println(stderr, "unexpected gfx command for main ring: {}, {}, {}",
gnm::Pm4Opcode(op), type, len);
rx::die("");
}

View file

@ -5,11 +5,11 @@
#include "gnm/mmio.hpp"
#include "gnm/pm4.hpp"
#include "orbis/KernelContext.hpp"
#include "rx/print.hpp"
#include "vk.hpp"
#include <bit>
#include <cstdio>
#include <mutex>
#include <print>
#include <rx/bits.hpp>
#include <rx/die.hpp>
#include <rx/format.hpp>
@ -193,7 +193,7 @@ void ComputePipe::setIndirectRing(int queueId, int indirectLevel, Ring ring) {
}
ring.indirectLevel = indirectLevel;
std::println(stderr, "mapQueue: {}, {}, {}", (void *)ring.base,
rx::println(stderr, "mapQueue: {}, {}, {}", (void *)ring.base,
(void *)ring.wptr, ring.size);
queues[1 - ring.indirectLevel][queueId] = ring;

View file

@ -1,11 +1,11 @@
#include "Renderer.hpp"
#include "Device.hpp"
#include "gnm/gnm.hpp"
#include "rx/print.hpp"
#include <amdgpu/tiler.hpp>
#include <gnm/constants.hpp>
#include <gnm/vulkan.hpp>
#include <print>
#include <rx/format.hpp>
#include <shader/Evaluator.hpp>
#include <shader/dialect.hpp>
@ -161,7 +161,7 @@ void amdgpu::draw(GraphicsPipe &pipe, int vmId, std::uint32_t firstVertex,
if (pipe.context.cbColorControl.mode != gnm::CbMode::Normal &&
pipe.context.cbColorControl.mode != gnm::CbMode::EliminateFastClear) {
std::println("unimplemented context.cbColorControl.mode = {}",
rx::println("unimplemented context.cbColorControl.mode = {}",
static_cast<gnm::CbMode>(pipe.context.cbColorControl.mode));
return;
}

View file

@ -7,9 +7,9 @@
#include "gcn.hpp"
#include "ir.hpp"
#include "rx/die.hpp"
#include "rx/print.hpp"
#include <iostream>
#include <limits>
#include <print>
using namespace shader;
@ -1111,7 +1111,7 @@ static void expToSpv(GcnConverter &converter, gcn::Stage stage,
return result;
};
std::println(stderr, "exp target {}.{}", targetToString(target),
rx::println(stderr, "exp target {}.{}", targetToString(target),
swizzleToString(swizzle));
std::abort();
}
@ -1184,9 +1184,9 @@ static void instructionsToSpv(GcnConverter &converter, gcn::Import &importer,
if (inst.getKind() != ir::Kind::Spv && inst.getKind() != ir::Kind::AmdGpu &&
semanticModuleInfo.findSemanticOf(inst.getInstId()) == nullptr) {
std::println(std::cerr, "unimplemented semantic: ");
std::println(stderr, "unimplemented semantic: ");
inst.print(std::cerr, context.ns);
std::println(std::cerr, "\n");
std::println(stderr, "\n");
std::vector<ir::Instruction> workList;
std::set<ir::Instruction> removed;
@ -1201,9 +1201,9 @@ static void instructionsToSpv(GcnConverter &converter, gcn::Import &importer,
continue;
}
std::println(std::cerr, "removing ");
rx::println(stderr, "removing ");
inst.print(std::cerr, context.ns);
std::println(std::cerr, "\n");
std::println(stderr, "\n");
if (auto value = inst.cast<ir::Value>()) {
for (auto &use : value.getUseList()) {

View file

@ -6,10 +6,10 @@
#include "analyze.hpp"
#include "dialect.hpp"
#include "ir.hpp"
#include "rx/print.hpp"
#include "spv.hpp"
#include "transform.hpp"
#include <print>
#include <rx/die.hpp>
#include <SPIRV/GlslangToSpv.h>
@ -22,7 +22,6 @@
#include <iostream>
#include <map>
#include <optional>
#include <print>
#include <type_traits>
#include <unordered_map>
#include <vector>
@ -1933,7 +1932,7 @@ gcn::deserialize(gcn::Context &context, const gcn::Environment &environment,
exitLabel.replaceAllUsesWith(newLabel);
}
std::print("\n\n{}\n\n", buildCFG(context.entryPoint).genTest());
rx::print("\n\n{}\n\n", buildCFG(context.entryPoint).genTest());
structurizeCfg(context, context.body);

View file

@ -9,6 +9,7 @@
#include "orbis/thread/Process.hpp"
#include "orbis/thread/Thread.hpp"
#include "orbis/utils/Logs.hpp"
#include "rx/die.hpp"
#include "rx/mem.hpp"
#include "rx/watchdog.hpp"
#include "vm.hpp"
@ -16,7 +17,6 @@
#include <cstdio>
#include <cstring>
#include <mutex>
#include <print>
#include <sys/mman.h>
static constexpr auto kDceControlMemoryOffset = 0;
@ -229,8 +229,7 @@ int DceDevice::allocateVmId() {
int id = std::countr_zero(freeVmIds);
if (id >= kVmIdCount) {
std::println(stderr, "out of vm slots");
std::abort();
rx::die("out of vm slots");
}
freeVmIds &= ~(1 << id);

View file

@ -8,11 +8,11 @@
#include "orbis/thread/Thread.hpp"
#include "orbis/utils/Logs.hpp"
#include "rx/align.hpp"
#include "rx/format.hpp"
#include "rx/watchdog.hpp"
#include "vm.hpp"
#include <fcntl.h>
#include <filesystem>
#include <format>
#include <mutex>
#include <sys/mman.h>
#include <unistd.h>
@ -36,7 +36,7 @@ DmemDevice::~DmemDevice() {
close(shmFd);
}
std::filesystem::remove(std::format("{}/dmem-{}", rx::getShmPath(), index));
std::filesystem::remove(rx::format("{}/dmem-{}", rx::getShmPath(), index));
}
orbis::ErrorCode DmemDevice::mmap(void **address, std::uint64_t len,
@ -400,7 +400,7 @@ IoDevice *createDmemCharacterDevice(int index) {
newDevice->index = index;
newDevice->dmemTotalSize = dmemSize;
auto path = std::format("{}/dmem-{}", rx::getShmPath(), index);
auto path = rx::format("{}/dmem-{}", rx::getShmPath(), index);
auto shmFd = ::open(path.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (ftruncate(shmFd, dmemSize) < 0) {

View file

@ -10,10 +10,10 @@
#include "orbis/utils/Logs.hpp"
#include "orbis/utils/SharedMutex.hpp"
#include "rx/die.hpp"
#include "rx/print.hpp"
#include "vm.hpp"
#include <cstdio>
#include <mutex>
#include <print>
#include <sys/mman.h>
struct ComputeQueue {
@ -405,7 +405,7 @@ static orbis::ErrorCode gc_ioctl(orbis::File *file, std::uint64_t request,
case 0x802450c9: {
// used during Net initialization
std::println(stderr, "***WARNING*** Unknown gc ioctl_{:x}(0x{:x})", request,
rx::println(stderr, "***WARNING*** Unknown gc ioctl_{:x}(0x{:x})", request,
(unsigned long)*(std::uint32_t *)argp);
break;
}

View file

@ -5,16 +5,16 @@
#include "orbis/KernelContext.hpp"
#include "orbis/osem.hpp"
#include "orbis/utils/Logs.hpp"
#include "rx/format.hpp"
#include "rx/hexdump.hpp"
#include "rx/mem.hpp"
#include "rx/print.hpp"
#include "rx/watchdog.hpp"
#include "vfs.hpp"
#include "vm.hpp"
#include <cstdint>
#include <fcntl.h>
#include <filesystem>
#include <format>
#include <print>
#include <sys/mman.h>
#include <sys/stat.h>
@ -209,9 +209,9 @@ ipmi::IpmiServer::handle(orbis::IpmiSession *session,
result = handler(*session, response.errorCode, outData, inData);
} else {
std::println(stderr, "Unimplemented async method {}::{:x}(inBufCount={})",
session->server->name, unsigned(message->methodId),
unsigned(message->numInData));
rx::println(stderr, "Unimplemented async method {}::{:x}(inBufCount={})",
session->server->name, unsigned(message->methodId),
unsigned(message->numInData));
for (auto in : inData) {
std::println(stderr, "in {}", in.size());
@ -562,9 +562,9 @@ void ipmi::createGnmCompositorObjects(orbis::Process *) {
void ipmi::createShellCoreObjects(orbis::Process *process) {
auto fmtHex = [](auto value, bool upperCase = false) {
if (upperCase) {
return std::format("{:08X}", value);
return rx::format("{:08X}", value);
}
return std::format("{:08x}", value);
return rx::format("{:08x}", value);
};
createIpmiServer(process, "SceSystemLoggerService");

View file

@ -12,6 +12,7 @@
#include "orbis/utils/Logs.hpp"
#include "rx/Config.hpp"
#include "rx/mem.hpp"
#include "rx/print.hpp"
#include "rx/watchdog.hpp"
#include "thread.hpp"
#include "vfs.hpp"
@ -19,7 +20,6 @@
#include "xbyak/xbyak.h"
#include <optional>
#include <orbis/utils/Rc.hpp>
#include <print>
#include <rx/Version.hpp>
#include <rx/align.hpp>
#include <rx/hexdump.hpp>
@ -46,7 +46,6 @@
#include <cstddef>
#include <cstdint>
#include <filesystem>
#include <print>
static int g_gpuPid;
extern bool allowMonoDebug;
@ -709,7 +708,7 @@ ExecEnv guestCreateExecEnv(orbis::Thread *mainThread,
mainThread);
if (libkernel == nullptr) {
std::println(stderr, "libkernel not found");
rx::println(stderr, "libkernel not found");
std::abort();
}

View file

@ -4,14 +4,13 @@
#include "orbis/thread/Process.hpp"
#include "orbis/thread/Thread.hpp"
#include "orbis/utils/Logs.hpp"
#include "rx/debug.hpp"
#include "rx/mem.hpp"
#include "rx/print.hpp"
#include <asm/prctl.h>
#include <csignal>
#include <immintrin.h>
#include <link.h>
#include <linux/prctl.h>
#include <print>
#include <rx/align.hpp>
#include <sys/prctl.h>
#include <ucontext.h>
@ -363,7 +362,7 @@ void *rx::thread::setupSignalStack(void *address) {
void *rx::thread::setupSignalStack() {
auto data = malloc(getSigAltStackSize());
if (data == nullptr) {
std::println(stderr, "malloc produces null, {:x}", getSigAltStackSize());
rx::println(stderr, "malloc produces null, {:x}", getSigAltStackSize());
std::exit(EXIT_FAILURE);
}
return setupSignalStack(data);

View file

@ -8,15 +8,15 @@
#include "orbis/thread/Thread.hpp"
#include "orbis/utils/Logs.hpp"
#include "orbis/utils/Rc.hpp"
#include "rx/format.hpp"
#include "rx/print.hpp"
#include "rx/watchdog.hpp"
#include <bit>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <fcntl.h>
#include <format>
#include <mutex>
#include <print>
#include <rx/MemoryTable.hpp>
#include <rx/align.hpp>
#include <rx/mem.hpp>
@ -674,7 +674,7 @@ static void reserve(std::uint64_t startAddress, std::uint64_t endAddress) {
}
void vm::fork(std::uint64_t pid) {
auto shmPath = std::format("{}/memory-{}", rx::getShmPath(), pid);
auto shmPath = rx::format("{}/memory-{}", rx::getShmPath(), pid);
gMemoryShm =
::open(shmPath.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
@ -682,7 +682,7 @@ void vm::fork(std::uint64_t pid) {
g_mtx.unlock(); // release mutex
if (gMemoryShm == -1) {
std::println(stderr, "Memory: failed to open {}", shmPath);
rx::println(stderr, "Memory: failed to open {}", shmPath);
std::abort();
}
@ -739,7 +739,7 @@ void vm::reset() {
void vm::initialize(std::uint64_t pid) {
std::println("Memory: initialization");
auto shmPath = std::format("{}/memory-{}", rx::getShmPath(), pid);
auto shmPath = rx::format("{}/memory-{}", rx::getShmPath(), pid);
gMemoryShm =
::open(shmPath.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
@ -1185,8 +1185,8 @@ bool vm::virtualQuery(const void *addr, std::int32_t flags,
}
memoryType = dmemIt->memoryType;
blockFlags = kBlockFlagDirectMemory;
std::print(stderr, "virtual query {}", addr);
std::println(stderr, "memory type: {}", memoryType);
rx::print(stderr, "virtual query {}", addr);
rx::println(stderr, "memory type: {}", memoryType);
}
// TODO
}

View file

@ -2,7 +2,6 @@ project(rx)
find_package(Git)
add_library(${PROJECT_NAME} OBJECT
src/debug.cpp
src/die.cpp
@ -20,6 +19,8 @@ PRIVATE
include/${PROJECT_NAME}
)
target_link_libraries(${PROJECT_NAME} PUBLIC fmt::fmt)
if (Git_FOUND)
execute_process(COMMAND ${GIT_EXECUTABLE} log --date=format:%Y%m%d --pretty=format:'%cd' -n 1 WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" OUTPUT_VARIABLE GIT_DATE)

View file

@ -0,0 +1,59 @@
#pragma once
#ifndef __has_include
#define __has_include(x) 0
#endif
#if __has_include(<print>)
#include <format>
namespace rx {
using std::format;
using std::format_args;
using std::format_context;
using std::format_parse_context;
using std::format_string;
using std::format_to;
using std::format_to_n;
using std::formatter;
using std::make_format_args;
using std::vformat;
using std::vformat_to;
} // namespace rx
#else
#include <fmt/format.h>
#include <type_traits>
namespace rx {
using fmt::format;
using fmt::format_args;
using fmt::format_context;
using fmt::format_parse_context;
namespace detail {
template <typename... Args>
struct format_string_impl : fmt::format_string<Args...> {
using fmt::format_string<Args...>::format_string;
constexpr std::string_view get() const noexcept {
return std::string_view(this->str);
}
};
} // namespace detail
template <typename... Args>
using format_string = std::type_identity_t<detail::format_string_impl<Args...>>;
template <typename... Args>
auto make_format_args(const Args &...args)
-> decltype(fmt::make_format_args(const_cast<Args &>(args)...)) {
return fmt::make_format_args(const_cast<Args &>(args)...);
}
using fmt::format_to;
using fmt::format_to_n;
using fmt::formatter;
using fmt::vformat;
using fmt::vformat_to;
} // namespace rx
#endif

View file

@ -1,8 +1,8 @@
#pragma once
#include "format-base.hpp"
#include "refl.hpp"
#include <array>
#include <format>
#include <optional>
#include <source_location>
#include <string_view>
#include <type_traits>
#include <unordered_map>
@ -14,8 +14,7 @@ struct StructFieldInfo {
std::size_t size = 0;
std::size_t align = 0;
std::size_t offset = 0;
std::format_context::iterator (*format)(void *,
std::format_context &ctx) = nullptr;
format_context::iterator (*format)(void *, format_context &ctx) = nullptr;
std::string_view name;
};
@ -25,11 +24,10 @@ struct StructFieldQuery {
template <typename T> constexpr operator T() {
info.size = sizeof(T);
info.align = alignof(T);
if constexpr (std::is_default_constructible_v<std::formatter<T>>) {
info.format =
[](void *object,
std::format_context &ctx) -> std::format_context::iterator {
std::formatter<T> formatter;
if constexpr (std::is_default_constructible_v<formatter<T>>) {
info.format = [](void *object,
format_context &ctx) -> format_context::iterator {
formatter<T> formatter;
return formatter.format(*static_cast<T *>(object), ctx);
};
}
@ -132,51 +130,66 @@ template <auto &&Variable> void registerVariable() {
auto &storage = detail::getVariableStorage();
storage.infos[&Variable] = rx::getNameOf<Variable>();
}
namespace detail {
template <typename... Args>
struct format_string_with_location_impl : format_string<Args...> {
std::source_location location;
template <typename T>
constexpr format_string_with_location_impl(
T message,
std::source_location location = std::source_location::current())
: format_string<Args...>(message), location(location) {}
};
} // namespace detail
template <typename... Args>
using format_string_with_location =
std::type_identity_t<detail::format_string_with_location_impl<Args...>>;
} // namespace rx
template <typename T>
requires(std::is_standard_layout_v<T> && std::is_class_v<T> &&
rx::fieldCount<T> > 0) &&
(!requires(T value) { std::begin(value) != std::end(value); })
struct std::formatter<T> {
constexpr std::format_parse_context::iterator
parse(std::format_parse_context &ctx) {
struct rx::formatter<T> {
constexpr rx::format_parse_context::iterator
parse(rx::format_parse_context &ctx) {
return ctx.begin();
}
std::format_context::iterator format(T &s, std::format_context &ctx) const {
std::format_to(ctx.out(), "{}", rx::getNameOf<T>());
std::format_to(ctx.out(), "{{");
format_context::iterator format(T &s, rx::format_context &ctx) const {
format_to(ctx.out(), "{}", rx::getNameOf<T>());
format_to(ctx.out(), "{{");
auto structInfo = rx::detail::getStructInfo<T>();
auto bytes = reinterpret_cast<std::byte *>(&s);
for (std::size_t i = 0; i < rx::fieldCount<T>; ++i) {
if (i != 0) {
std::format_to(ctx.out(), ", ");
format_to(ctx.out(), ", ");
}
if (!structInfo[i].name.empty()) {
std::format_to(ctx.out(), ".{} = ", structInfo[i].name);
format_to(ctx.out(), ".{} = ", structInfo[i].name);
}
structInfo[i].format(bytes + structInfo[i].offset, ctx);
}
std::format_to(ctx.out(), "}}");
format_to(ctx.out(), "}}");
return ctx.out();
}
};
template <typename T>
requires(std::is_enum_v<T> && rx::fieldCount<T> > 0)
struct std::formatter<T> {
constexpr std::format_parse_context::iterator
parse(std::format_parse_context &ctx) {
struct rx::formatter<T> {
constexpr rx::format_parse_context::iterator
parse(rx::format_parse_context &ctx) {
return ctx.begin();
}
std::format_context::iterator format(T value,
std::format_context &ctx) const {
rx::format_context::iterator format(T value, format_context &ctx) const {
auto getFieldName =
[]<std::size_t... I>(std::underlying_type_t<T> value,
std::index_sequence<I...>) -> std::string {
@ -188,7 +201,7 @@ struct std::formatter<T> {
return std::string(result);
}
return std::format("{}", value);
return rx::format("{}", value);
};
auto queryUnknownField =
@ -208,16 +221,19 @@ struct std::formatter<T> {
};
if (value < 0) {
(queryIndex(std::integral_constant<std::int64_t, -(I + Offset)>{}, value), ...);
(queryIndex(std::integral_constant<std::int64_t, -(I + Offset)>{},
value),
...);
} else {
(queryIndex(std::integral_constant<std::int64_t, I + Offset>{}, value), ...);
(queryIndex(std::integral_constant<std::int64_t, I + Offset>{}, value),
...);
}
if (!result.empty()) {
return std::string(result);
}
return std::format("{}", value);
return rx::format("{}", value);
};
std::string fieldName;
@ -240,9 +256,9 @@ struct std::formatter<T> {
}
if (fieldName[0] >= '0' && fieldName[0] <= '9') {
std::format_to(ctx.out(), "({}){}", rx::getNameOf<T>(), fieldName);
rx::format_to(ctx.out(), "({}){}", rx::getNameOf<T>(), fieldName);
} else {
std::format_to(ctx.out(), "{}::{}", rx::getNameOf<T>(), fieldName);
rx::format_to(ctx.out(), "{}::{}", rx::getNameOf<T>(), fieldName);
}
return ctx.out();
@ -251,26 +267,26 @@ struct std::formatter<T> {
template <typename T>
requires requires(T value) { std::begin(value) != std::end(value); }
struct std::formatter<T> {
constexpr std::format_parse_context::iterator
parse(std::format_parse_context &ctx) {
struct rx::formatter<T> {
constexpr rx::format_parse_context::iterator
parse(rx::format_parse_context &ctx) {
return ctx.begin();
}
std::format_context::iterator format(T &s, std::format_context &ctx) const {
std::format_to(ctx.out(), "[");
rx::format_context::iterator format(T &s, rx::format_context &ctx) const {
rx::format_to(ctx.out(), "[");
for (bool first = true; auto &elem : s) {
if (first) {
first = false;
} else {
std::format_to(ctx.out(), ", ");
rx::format_to(ctx.out(), ", ");
}
std::format_to(ctx.out(), "{}", elem);
rx::format_to(ctx.out(), "{}", elem);
}
std::format_to(ctx.out(), "]");
rx::format_to(ctx.out(), "]");
return ctx.out();
}
};
@ -281,25 +297,25 @@ template <typename T>
!std::is_same_v<std::remove_cv_t<T>, char8_t> &&
!std::is_same_v<std::remove_cv_t<T>, char16_t> &&
!std::is_same_v<std::remove_cv_t<T>, char32_t> &&
std::is_default_constructible_v<std::formatter<T>>)
struct std::formatter<T *> {
constexpr std::format_parse_context::iterator
parse(std::format_parse_context &ctx) {
std::is_default_constructible_v<rx::formatter<T>>)
struct rx::formatter<T *> {
constexpr rx::format_parse_context::iterator
parse(rx::format_parse_context &ctx) {
return ctx.begin();
}
std::format_context::iterator format(T *ptr, std::format_context &ctx) const {
rx::format_context::iterator format(T *ptr, rx::format_context &ctx) const {
auto name = rx::detail::getVariableStorage().getVariableName(ptr);
if (!name.empty()) {
std::format_to(ctx.out(), "*{} = ", name);
rx::format_to(ctx.out(), "*{} = ", name);
} else {
std::format_to(ctx.out(), "*");
rx::format_to(ctx.out(), "*");
}
if (ptr == nullptr) {
std::format_to(ctx.out(), "nullptr");
rx::format_to(ctx.out(), "nullptr");
} else {
std::format_to(ctx.out(), "{}:{}", static_cast<void *>(ptr), *ptr);
rx::format_to(ctx.out(), "{}:{}", static_cast<void *>(ptr), *ptr);
}
return ctx.out();
}

32
rx/include/rx/print.hpp Normal file
View file

@ -0,0 +1,32 @@
#pragma once
#ifndef __has_include
#define __has_include(x) 0
#endif
#if __has_include(<print>)
#include <print>
namespace rx {
using std::print;
using std::println;
using std::vprint_nonunicode;
using std::vprint_unicode;
} // namespace rx
#else
#include <fmt/format.h>
namespace rx {
using fmt::print;
using fmt::println;
inline void vprint_nonunicode(FILE *stream, std::string_view fmt,
fmt::format_args args) {
fmt::vprint(stream, fmt, args);
}
inline void vprint_unicode(FILE *stream, std::string_view fmt,
fmt::format_args args) {
fmt::vprint(stream, fmt, args);
}
} // namespace rx
#endif

View file

@ -1,7 +1,7 @@
#include "debug.hpp"
#include "print.hpp"
#include <fstream>
#include <list>
#include <print>
#include <thread>
#include <vector>
@ -73,13 +73,13 @@ void rx::waitForDebugger() {
return;
}
std::println(stderr, "waiting for debugger, pid {}", ::getpid());
rx::println(stderr, "waiting for debugger, pid {}", ::getpid());
while (!isDebuggerPresent()) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::println(stderr, "debugger was attached");
rx::println(stderr, "debugger was attached");
std::this_thread::sleep_for(std::chrono::seconds(3));
breakpoint();
}

View file

@ -1,8 +1,8 @@
#include "hexdump.hpp"
#include "FileLock.hpp"
#include "print.hpp"
#include <cstdio>
#include <cstring>
#include <print>
#include <string>
void rx::hexdump(std::span<const std::byte> bytes) {
@ -18,13 +18,13 @@ void rx::hexdump(std::span<const std::byte> bytes) {
}
rx::ScopedFileLock stderrLock(stderr);
std::print(stderr, "{} ", std::string(sizeWidth, ' '));
rx::print(stderr, "{} ", std::string(sizeWidth, ' '));
for (unsigned i = 0; i < 16; ++i) {
std::print(stderr, " {:02x}", i);
rx::print(stderr, " {:02x}", i);
}
std::print(stderr, "\n{} ", std::string(sizeWidth, ' '));
rx::print(stderr, "\n{} ", std::string(sizeWidth, ' '));
for (unsigned i = 0; i < 16; ++i) {
std::print(stderr, " --");
rx::print(stderr, " --");
}
std::byte zeros[16]{};
@ -38,7 +38,7 @@ void rx::hexdump(std::span<const std::byte> bytes) {
if (std::memcmp(bytes.data() + i, zeros, 16) == 0) {
if (!dotsPrinted) {
dotsPrinted = true;
std::print(stderr, "\n...");
rx::print(stderr, "\n...");
}
i += 15;
continue;
@ -46,22 +46,21 @@ void rx::hexdump(std::span<const std::byte> bytes) {
}
if (!dotsPrinted) {
std::print(stderr, " | ");
rx::print(stderr, " | ");
for (std::size_t j = i - 16; j < i; ++j) {
auto c = unsigned(bytes[j]);
std::print(stderr, "{:c}",
(std::isprint(c) && c != '\n') ? c : '.');
rx::print(stderr, "{:c}", (std::isprint(c) && c != '\n') ? c : '.');
}
}
}
std::println(stderr, "");
std::print(stderr, "{:0{}x} ", i, sizeWidth);
rx::println(stderr, "");
rx::print(stderr, "{:0{}x} ", i, sizeWidth);
wasAllZeros = true;
dotsPrinted = false;
}
std::print(stderr, " {:02x}", unsigned(bytes[i]));
rx::print(stderr, " {:02x}", unsigned(bytes[i]));
if (bytes[i] != std::byte{0}) {
wasAllZeros = false;
@ -70,17 +69,17 @@ void rx::hexdump(std::span<const std::byte> bytes) {
if (!bytes.empty()) {
for (std::size_t i = 0; i < (16 - (bytes.size() % 16)) % 16; ++i) {
std::print(stderr, " ");
rx::print(stderr, " ");
}
std::print(stderr, " | ");
rx::print(stderr, " | ");
for (std::size_t j = bytes.size() -
std::min(bytes.size(),
(bytes.size() % 16 ? bytes.size() % 16 : 16));
j < bytes.size(); ++j) {
auto c = unsigned(bytes[j]);
std::print(stderr, "{:c}", (std::isprint(c) && c != '\n') ? c : '.');
rx::print(stderr, "{:c}", (std::isprint(c) && c != '\n') ? c : '.');
}
}
std::println(stderr, "");
rx::println(stderr, "");
}

View file

@ -1,9 +1,9 @@
#include "mem.hpp"
#include "print.hpp"
#ifdef __linux__
#include <cstdio>
#include <print>
#include <sys/mman.h>
#include <unistd.h>
@ -41,7 +41,7 @@ void rx::mem::printStats() {
char *line = nullptr;
std::size_t size = 0;
while (getline(&line, &size, maps) > 0) {
std::print("{}", line);
rx::print("{}", line);
}
free(line);