diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index 375edaa4a..49b3e9caf 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -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) diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index c4b937984..e13a927f9 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -30,7 +30,6 @@ #include "lv2/sys_spu.h" #include #include -#include #ifdef LLVM_AVAILABLE #ifdef _MSC_VER diff --git a/rpcsx/AudioOut.cpp b/rpcsx/AudioOut.cpp index 9a9226bc5..28a27d72c 100644 --- a/rpcsx/AudioOut.cpp +++ b/rpcsx/AudioOut.cpp @@ -1,10 +1,10 @@ #include "AudioOut.hpp" +#include "rx/format.hpp" #include "rx/mem.hpp" #include "rx/watchdog.hpp" #include #include #include -#include #include #include #include @@ -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); diff --git a/rpcsx/core/src/watchdog.cpp b/rpcsx/core/src/watchdog.cpp index 0e2a057e7..499498a02 100644 --- a/rpcsx/core/src/watchdog.cpp +++ b/rpcsx/core/src/watchdog.cpp @@ -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 #include #include @@ -10,8 +12,6 @@ #include #include #include -#include -#include #include #include #include @@ -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(); } diff --git a/rpcsx/gpu/Cache.cpp b/rpcsx/gpu/Cache.cpp index b66349d46..219a26b18 100644 --- a/rpcsx/gpu/Cache.cpp +++ b/rpcsx/gpu/Cache.cpp @@ -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 #include #include -#include #include #include #include @@ -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", diff --git a/rpcsx/gpu/Cache.hpp b/rpcsx/gpu/Cache.hpp index e460e939e..698b8ea98 100644 --- a/rpcsx/gpu/Cache.hpp +++ b/rpcsx/gpu/Cache.hpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff --git a/rpcsx/gpu/Device.cpp b/rpcsx/gpu/Device.cpp index 98f35aa50..0b4db9ec6 100644 --- a/rpcsx/gpu/Device.cpp +++ b/rpcsx/gpu/Device.cpp @@ -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 #include #include -#include -#include #include #include #include @@ -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; diff --git a/rpcsx/gpu/DeviceCtl.cpp b/rpcsx/gpu/DeviceCtl.cpp index 17021a194..59a018a1b 100644 --- a/rpcsx/gpu/DeviceCtl.cpp +++ b/rpcsx/gpu/DeviceCtl.cpp @@ -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 -#include #include 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(""); } diff --git a/rpcsx/gpu/Pipe.cpp b/rpcsx/gpu/Pipe.cpp index 6d713c1db..d07e5c830 100644 --- a/rpcsx/gpu/Pipe.cpp +++ b/rpcsx/gpu/Pipe.cpp @@ -5,11 +5,11 @@ #include "gnm/mmio.hpp" #include "gnm/pm4.hpp" #include "orbis/KernelContext.hpp" +#include "rx/print.hpp" #include "vk.hpp" #include #include #include -#include #include #include #include @@ -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; diff --git a/rpcsx/gpu/Renderer.cpp b/rpcsx/gpu/Renderer.cpp index 0e636471a..484feb866 100644 --- a/rpcsx/gpu/Renderer.cpp +++ b/rpcsx/gpu/Renderer.cpp @@ -1,11 +1,11 @@ #include "Renderer.hpp" #include "Device.hpp" #include "gnm/gnm.hpp" +#include "rx/print.hpp" #include #include #include -#include #include #include #include @@ -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(pipe.context.cbColorControl.mode)); return; } diff --git a/rpcsx/gpu/lib/gcn-shader/src/GcnConverter.cpp b/rpcsx/gpu/lib/gcn-shader/src/GcnConverter.cpp index 498a566ba..faf41b588 100644 --- a/rpcsx/gpu/lib/gcn-shader/src/GcnConverter.cpp +++ b/rpcsx/gpu/lib/gcn-shader/src/GcnConverter.cpp @@ -7,9 +7,9 @@ #include "gcn.hpp" #include "ir.hpp" #include "rx/die.hpp" +#include "rx/print.hpp" #include #include -#include 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 workList; std::set 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()) { for (auto &use : value.getUseList()) { diff --git a/rpcsx/gpu/lib/gcn-shader/src/gcn.cpp b/rpcsx/gpu/lib/gcn-shader/src/gcn.cpp index 152d23568..576beedf0 100644 --- a/rpcsx/gpu/lib/gcn-shader/src/gcn.cpp +++ b/rpcsx/gpu/lib/gcn-shader/src/gcn.cpp @@ -6,10 +6,10 @@ #include "analyze.hpp" #include "dialect.hpp" #include "ir.hpp" +#include "rx/print.hpp" #include "spv.hpp" #include "transform.hpp" -#include #include #include @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -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); diff --git a/rpcsx/iodev/dce.cpp b/rpcsx/iodev/dce.cpp index 05cc2c54a..bcfe89269 100644 --- a/rpcsx/iodev/dce.cpp +++ b/rpcsx/iodev/dce.cpp @@ -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 #include #include -#include #include 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); diff --git a/rpcsx/iodev/dmem.cpp b/rpcsx/iodev/dmem.cpp index 2800f4536..710224919 100644 --- a/rpcsx/iodev/dmem.cpp +++ b/rpcsx/iodev/dmem.cpp @@ -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 #include -#include #include #include #include @@ -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) { diff --git a/rpcsx/iodev/gc.cpp b/rpcsx/iodev/gc.cpp index 61a7b69dd..d59157051 100644 --- a/rpcsx/iodev/gc.cpp +++ b/rpcsx/iodev/gc.cpp @@ -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 #include -#include #include 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; } diff --git a/rpcsx/ipmi.cpp b/rpcsx/ipmi.cpp index e9a199fd4..5a92b8dd4 100644 --- a/rpcsx/ipmi.cpp +++ b/rpcsx/ipmi.cpp @@ -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 #include #include -#include -#include #include #include @@ -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"); diff --git a/rpcsx/main.cpp b/rpcsx/main.cpp index 480f34580..c95b98047 100644 --- a/rpcsx/main.cpp +++ b/rpcsx/main.cpp @@ -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 #include -#include #include #include #include @@ -46,7 +46,6 @@ #include #include #include -#include 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(); } diff --git a/rpcsx/thread.cpp b/rpcsx/thread.cpp index ce222c819..f0511a168 100644 --- a/rpcsx/thread.cpp +++ b/rpcsx/thread.cpp @@ -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 #include #include #include #include -#include #include #include #include @@ -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); diff --git a/rpcsx/vm.cpp b/rpcsx/vm.cpp index ed1cd0f48..2eb7d8fed 100644 --- a/rpcsx/vm.cpp +++ b/rpcsx/vm.cpp @@ -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 #include #include #include #include -#include #include -#include #include #include #include @@ -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 } diff --git a/rx/CMakeLists.txt b/rx/CMakeLists.txt index f5d4a8f90..246fb2490 100644 --- a/rx/CMakeLists.txt +++ b/rx/CMakeLists.txt @@ -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) diff --git a/rx/include/rx/format-base.hpp b/rx/include/rx/format-base.hpp new file mode 100644 index 000000000..4baa2c96d --- /dev/null +++ b/rx/include/rx/format-base.hpp @@ -0,0 +1,59 @@ +#pragma once + +#ifndef __has_include +#define __has_include(x) 0 +#endif + +#if __has_include() +#include + +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 +#include + +namespace rx { +using fmt::format; +using fmt::format_args; +using fmt::format_context; +using fmt::format_parse_context; + +namespace detail { +template +struct format_string_impl : fmt::format_string { + using fmt::format_string::format_string; + + constexpr std::string_view get() const noexcept { + return std::string_view(this->str); + } +}; +} // namespace detail + +template +using format_string = std::type_identity_t>; + +template +auto make_format_args(const Args &...args) + -> decltype(fmt::make_format_args(const_cast(args)...)) { + return fmt::make_format_args(const_cast(args)...); +} + +using fmt::format_to; +using fmt::format_to_n; +using fmt::formatter; +using fmt::vformat; +using fmt::vformat_to; +} // namespace rx +#endif diff --git a/rx/include/rx/format.hpp b/rx/include/rx/format.hpp index d48fe72df..c5449aade 100644 --- a/rx/include/rx/format.hpp +++ b/rx/include/rx/format.hpp @@ -1,8 +1,8 @@ #pragma once +#include "format-base.hpp" #include "refl.hpp" #include -#include -#include +#include #include #include #include @@ -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 constexpr operator T() { info.size = sizeof(T); info.align = alignof(T); - if constexpr (std::is_default_constructible_v>) { - info.format = - [](void *object, - std::format_context &ctx) -> std::format_context::iterator { - std::formatter formatter; + if constexpr (std::is_default_constructible_v>) { + info.format = [](void *object, + format_context &ctx) -> format_context::iterator { + formatter formatter; return formatter.format(*static_cast(object), ctx); }; } @@ -132,51 +130,66 @@ template void registerVariable() { auto &storage = detail::getVariableStorage(); storage.infos[&Variable] = rx::getNameOf(); } + +namespace detail { +template +struct format_string_with_location_impl : format_string { + std::source_location location; + + template + constexpr format_string_with_location_impl( + T message, + std::source_location location = std::source_location::current()) + : format_string(message), location(location) {} +}; +} // namespace detail +template +using format_string_with_location = + std::type_identity_t>; } // namespace rx template requires(std::is_standard_layout_v && std::is_class_v && rx::fieldCount > 0) && (!requires(T value) { std::begin(value) != std::end(value); }) -struct std::formatter { - constexpr std::format_parse_context::iterator - parse(std::format_parse_context &ctx) { +struct rx::formatter { + 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()); - std::format_to(ctx.out(), "{{"); + format_context::iterator format(T &s, rx::format_context &ctx) const { + format_to(ctx.out(), "{}", rx::getNameOf()); + format_to(ctx.out(), "{{"); auto structInfo = rx::detail::getStructInfo(); auto bytes = reinterpret_cast(&s); for (std::size_t i = 0; i < rx::fieldCount; ++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 requires(std::is_enum_v && rx::fieldCount > 0) -struct std::formatter { - constexpr std::format_parse_context::iterator - parse(std::format_parse_context &ctx) { +struct rx::formatter { + 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::underlying_type_t value, std::index_sequence) -> std::string { @@ -188,7 +201,7 @@ struct std::formatter { return std::string(result); } - return std::format("{}", value); + return rx::format("{}", value); }; auto queryUnknownField = @@ -208,16 +221,19 @@ struct std::formatter { }; if (value < 0) { - (queryIndex(std::integral_constant{}, value), ...); + (queryIndex(std::integral_constant{}, + value), + ...); } else { - (queryIndex(std::integral_constant{}, value), ...); + (queryIndex(std::integral_constant{}, 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 { } if (fieldName[0] >= '0' && fieldName[0] <= '9') { - std::format_to(ctx.out(), "({}){}", rx::getNameOf(), fieldName); + rx::format_to(ctx.out(), "({}){}", rx::getNameOf(), fieldName); } else { - std::format_to(ctx.out(), "{}::{}", rx::getNameOf(), fieldName); + rx::format_to(ctx.out(), "{}::{}", rx::getNameOf(), fieldName); } return ctx.out(); @@ -251,26 +267,26 @@ struct std::formatter { template requires requires(T value) { std::begin(value) != std::end(value); } -struct std::formatter { - constexpr std::format_parse_context::iterator - parse(std::format_parse_context &ctx) { +struct rx::formatter { + 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 !std::is_same_v, char8_t> && !std::is_same_v, char16_t> && !std::is_same_v, char32_t> && - std::is_default_constructible_v>) -struct std::formatter { - constexpr std::format_parse_context::iterator - parse(std::format_parse_context &ctx) { + std::is_default_constructible_v>) +struct rx::formatter { + 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(ptr), *ptr); + rx::format_to(ctx.out(), "{}:{}", static_cast(ptr), *ptr); } return ctx.out(); } diff --git a/rx/include/rx/print.hpp b/rx/include/rx/print.hpp new file mode 100644 index 000000000..cef51c831 --- /dev/null +++ b/rx/include/rx/print.hpp @@ -0,0 +1,32 @@ +#pragma once + +#ifndef __has_include +#define __has_include(x) 0 +#endif + +#if __has_include() +#include +namespace rx { +using std::print; +using std::println; +using std::vprint_nonunicode; +using std::vprint_unicode; +} // namespace rx +#else +#include + +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 diff --git a/rx/src/debug.cpp b/rx/src/debug.cpp index d8a2d9d32..1727b2c7a 100644 --- a/rx/src/debug.cpp +++ b/rx/src/debug.cpp @@ -1,7 +1,7 @@ #include "debug.hpp" +#include "print.hpp" #include #include -#include #include #include @@ -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(); } diff --git a/rx/src/hexdump.cpp b/rx/src/hexdump.cpp index 1f570cb39..7ad4dd1e4 100644 --- a/rx/src/hexdump.cpp +++ b/rx/src/hexdump.cpp @@ -1,8 +1,8 @@ #include "hexdump.hpp" #include "FileLock.hpp" +#include "print.hpp" #include #include -#include #include void rx::hexdump(std::span bytes) { @@ -18,13 +18,13 @@ void rx::hexdump(std::span 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 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 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 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, ""); } diff --git a/rx/src/mem.cpp b/rx/src/mem.cpp index c3e225fa7..59baf5fd2 100644 --- a/rx/src/mem.cpp +++ b/rx/src/mem.cpp @@ -1,9 +1,9 @@ #include "mem.hpp" +#include "print.hpp" #ifdef __linux__ #include -#include #include #include @@ -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);