Add fmtlib::fmt backport of C++20 std::format

Because I'm tired of waiting for std::format.
This commit is contained in:
Jason Rhinelander 2021-08-16 18:44:42 -03:00
parent c81cf6fd3b
commit eefd42f93f
7 changed files with 68 additions and 86 deletions

3
.gitmodules vendored
View File

@ -28,3 +28,6 @@
[submodule "external/ghc-filesystem"] [submodule "external/ghc-filesystem"]
path = external/ghc-filesystem path = external/ghc-filesystem
url = https://github.com/gulrak/filesystem.git url = https://github.com/gulrak/filesystem.git
[submodule "external/fmt"]
path = external/fmt
url = https://github.com/fmtlib/fmt.git

View File

@ -83,6 +83,7 @@ endif()
add_subdirectory(db_drivers) add_subdirectory(db_drivers)
add_subdirectory(easylogging++ easyloggingpp) add_subdirectory(easylogging++ easyloggingpp)
add_subdirectory(randomx EXCLUDE_FROM_ALL) add_subdirectory(randomx EXCLUDE_FROM_ALL)
add_subdirectory(fmt)
# uSockets doesn't really have a proper build system (just a very simple Makefile) so build it # uSockets doesn't really have a proper build system (just a very simple Makefile) so build it
# ourselves. # ourselves.

1
external/fmt vendored Submodule

@ -0,0 +1 @@
Subproject commit d141cdbeb0fb422a3fb7173b285fd38e0d1772dc

View File

@ -28,7 +28,6 @@
#include "db_lmdb.h" #include "db_lmdb.h"
#include <boost/format.hpp>
#include <boost/circular_buffer.hpp> #include <boost/circular_buffer.hpp>
#include <boost/endian/conversion.hpp> #include <boost/endian/conversion.hpp>
#include <memory> #include <memory>
@ -712,7 +711,7 @@ bool BlockchainLMDB::need_resize(uint64_t threshold_size) const
MDEBUG("Space remaining: " << mei.me_mapsize - size_used); MDEBUG("Space remaining: " << mei.me_mapsize - size_used);
MDEBUG("Size threshold: " << threshold_size); MDEBUG("Size threshold: " << threshold_size);
float resize_percent = RESIZE_PERCENT; float resize_percent = RESIZE_PERCENT;
MDEBUG(boost::format("Percent used: %.04f Percent threshold: %.04f") % (100.*size_used/mei.me_mapsize) % (100.*resize_percent)); MDEBUG("Percent used: " << 100.*size_used/mei.me_mapsize << " Percent threshold: " << 100.*resize_percent);
if (threshold_size > 0) if (threshold_size > 0)
{ {

View File

@ -66,6 +66,7 @@ target_link_libraries(common
cncrypto cncrypto
oxenmq::oxenmq oxenmq::oxenmq
filesystem filesystem
fmt::fmt
PRIVATE PRIVATE
libunbound libunbound
OpenSSL::SSL OpenSSL::SSL

View File

@ -40,8 +40,9 @@
#include "cryptonote_core/service_node_rules.h" #include "cryptonote_core/service_node_rules.h"
#include "cryptonote_basic/hardfork.h" #include "cryptonote_basic/hardfork.h"
#include "checkpoints/checkpoints.h" #include "checkpoints/checkpoints.h"
#include <boost/format.hpp> #include <exception>
#include <oxenmq/base32z.h> #include <oxenmq/base32z.h>
#include <fmt/core.h>
#include "common/oxen_integration_test_hooks.h" #include "common/oxen_integration_test_hooks.h"
@ -111,19 +112,6 @@ namespace {
return input_line_result::yes; return input_line_result::yes;
} }
const char *get_address_type_name(epee::net_utils::address_type address_type)
{
switch (address_type)
{
default:
case epee::net_utils::address_type::invalid: return "invalid";
case epee::net_utils::address_type::ipv4: return "IPv4";
case epee::net_utils::address_type::ipv6: return "IPv6";
case epee::net_utils::address_type::i2p: return "I2P";
case epee::net_utils::address_type::tor: return "Tor";
}
}
void print_peer(std::string const & prefix, GET_PEER_LIST::peer const & peer, bool pruned_only, bool publicrpc_only) void print_peer(std::string const & prefix, GET_PEER_LIST::peer const & peer, bool pruned_only, bool publicrpc_only)
{ {
if (pruned_only && peer.pruning_seed == 0) if (pruned_only && peer.pruning_seed == 0)
@ -139,7 +127,7 @@ namespace {
std::string addr_str = peer.host + ":" + std::to_string(peer.port); std::string addr_str = peer.host + ":" + std::to_string(peer.port);
std::string rpc_port = peer.rpc_port ? std::to_string(peer.rpc_port) : "-"; std::string rpc_port = peer.rpc_port ? std::to_string(peer.rpc_port) : "-";
std::string pruning_seed = epee::string_tools::to_string_hex(peer.pruning_seed); std::string pruning_seed = epee::string_tools::to_string_hex(peer.pruning_seed);
tools::msg_writer() << boost::format("%-10s %-25s %-25s %-5s %-4s %s") % prefix % id_str % addr_str % rpc_port % pruning_seed % elapsed; tools::msg_writer() << fmt::format("{:<10} {:<25} {:<25} {:<5} %{:-4} {}", prefix, id_str, addr_str, rpc_port, pruning_seed, elapsed);
} }
void print_block_header(block_header_response const & header) void print_block_header(block_header_response const & header)
@ -174,11 +162,11 @@ namespace {
if (dt < 90s) if (dt < 90s)
s = std::to_string(dt.count()) + (abbreviate ? "sec" : dt == 1s ? " second" : " seconds"); s = std::to_string(dt.count()) + (abbreviate ? "sec" : dt == 1s ? " second" : " seconds");
else if (dt < 90min) else if (dt < 90min)
s = (boost::format(abbreviate ? "%.1fmin" : "%.1f minutes") % ((float)dt.count()/60)).str(); s = fmt::format("{:.1f}{:s}", ((float)dt.count()/60), abbreviate ? "min" : " minutes");
else if (dt < 36h) else if (dt < 36h)
s = (boost::format(abbreviate ? "%.1fhr" : "%.1f hours") % ((float)dt.count()/3600)).str(); s = fmt::format("{:.1f}{:s}", ((float)dt.count()/3600), abbreviate ? "hr" : " hours");
else else
s = (boost::format("%.1f days") % ((float)dt.count()/(86400))).str(); s = fmt::format("{:.1f} days", ((float)dt.count()/86400));
if (abbreviate) { if (abbreviate) {
if (ago < 0s) if (ago < 0s)
return s + " (in fut.)"; return s + " (in fut.)";
@ -407,15 +395,15 @@ bool rpc_command_executor::show_difficulty() {
static std::string get_mining_speed(uint64_t hr) static std::string get_mining_speed(uint64_t hr)
{ {
if (hr>1e9) return (boost::format("%.2f GH/s") % (hr/1e9)).str(); if (hr >= 1e9) return fmt::format("{:.2f} GH/s", hr*1e-9);
if (hr>1e6) return (boost::format("%.2f MH/s") % (hr/1e6)).str(); if (hr >= 1e6) return fmt::format("{:.2f} MH/s", hr*1e-6);
if (hr>1e3) return (boost::format("%.2f kH/s") % (hr/1e3)).str(); if (hr >= 1e3) return fmt::format("{:.2f} kH/s", hr*1e-3);
return (boost::format("%.0f H/s") % hr).str(); return fmt::format("{:d} H/s", hr);
} }
static std::ostream& print_fork_extra_info(std::ostream& o, uint64_t t, uint64_t now, uint64_t block_time) static std::ostream& print_fork_extra_info(std::ostream& o, uint64_t t, uint64_t now, std::chrono::seconds block_time)
{ {
uint64_t blocks_per_day = 86400 / block_time; double blocks_per_day = 24h / block_time;
if (t == now) if (t == now)
return o << " (forking now)"; return o << " (forking now)";
@ -428,8 +416,8 @@ static std::ostream& print_fork_extra_info(std::ostream& o, uint64_t t, uint64_t
if (dblocks <= 30) if (dblocks <= 30)
return o << dblocks << " blocks)"; return o << dblocks << " blocks)";
if (dblocks <= blocks_per_day / 2) if (dblocks <= blocks_per_day / 2)
return o << boost::format("%.1f hours)") % (dblocks / (float)blocks_per_day * 24); return o << fmt::format("{:.1f} hours)", dblocks / blocks_per_day * 24);
return o << boost::format("%.1f days)") % (dblocks / (float)blocks_per_day); return o << fmt::format("{:.1f} days)", dblocks / blocks_per_day);
} }
static float get_sync_percentage(uint64_t height, uint64_t target_height) static float get_sync_percentage(uint64_t height, uint64_t target_height)
@ -440,10 +428,6 @@ static float get_sync_percentage(uint64_t height, uint64_t target_height)
return 99.9f; // to avoid 100% when not fully synced return 99.9f; // to avoid 100% when not fully synced
return pc; return pc;
} }
static float get_sync_percentage(const GET_INFO::response &ires)
{
return get_sync_percentage(ires.height, ires.target_height);
}
bool rpc_command_executor::show_status() { bool rpc_command_executor::show_status() {
GET_INFO::response ires{}; GET_INFO::response ires{};
@ -505,7 +489,7 @@ bool rpc_command_executor::show_status() {
std::ostringstream str; std::ostringstream str;
str << "Height: " << ires.height; str << "Height: " << ires.height;
if (ires.height != net_height) if (ires.height != net_height)
str << "/" << net_height << " (" << boost::format("%.1f") % get_sync_percentage(ires) << "%)"; str << fmt::format("/{} ({:.1f}%)", net_height, get_sync_percentage(ires.height, net_height));
if (ires.testnet) str << " ON TESTNET"; if (ires.testnet) str << " ON TESTNET";
else if (ires.devnet) str << " ON DEVNET"; else if (ires.devnet) str << " ON DEVNET";
@ -516,8 +500,10 @@ bool rpc_command_executor::show_status() {
if (ires.was_bootstrap_ever_used && *ires.was_bootstrap_ever_used && ires.bootstrap_daemon_address) if (ires.was_bootstrap_ever_used && *ires.was_bootstrap_ever_used && ires.bootstrap_daemon_address)
{ {
str << ", bootstrap " << *ires.bootstrap_daemon_address; str << ", bootstrap " << *ires.bootstrap_daemon_address;
if (ires.untrusted) if (ires.untrusted) {
str << boost::format(", local height: %llu (%.1f%%)") % *ires.height_without_bootstrap % get_sync_percentage(*ires.height_without_bootstrap, net_height); auto hwb = *ires.height_without_bootstrap;
str << fmt::format(", local height: {} ({:.1f}%)", hwb, get_sync_percentage(hwb, net_height));
}
else else
str << " was used"; str << " was used";
} }
@ -533,7 +519,7 @@ bool rpc_command_executor::show_status() {
str << ", v" << (ires.version.empty() ? "?.?.?" : ires.version); str << ", v" << (ires.version.empty() ? "?.?.?" : ires.version);
str << "(net v" << +hfres.version << ')'; str << "(net v" << +hfres.version << ')';
if (hfres.earliest_height) if (hfres.earliest_height)
print_fork_extra_info(str, *hfres.earliest_height, net_height, ires.target); print_fork_extra_info(str, *hfres.earliest_height, net_height, 1s * ires.target);
std::time_t now = std::time(nullptr); std::time_t now = std::time(nullptr);
@ -637,42 +623,33 @@ bool rpc_command_executor::print_connections() {
if (!invoke<GET_CONNECTIONS>({}, res, "Failed to retrieve connection info")) if (!invoke<GET_CONNECTIONS>({}, res, "Failed to retrieve connection info"))
return false; return false;
tools::msg_writer() << std::setw(30) << std::left << "Remote Host" constexpr auto hdr_fmt = "{:<30}{:<8}{:<20}{:<30}{:<25}{:<20}{:<12s}{:<14s}{:<10s}{:<13s}"sv;
<< std::setw(8) << "Type" constexpr auto row_fmt = "{:<30}{:<8}{:<20}{:<30}{:<25}{:<20}{:<12.1f}{:<14.1f}{:<10.1f}{:<13.1f}{}{}"sv;
<< std::setw(20) << "Peer id" tools::msg_writer() << fmt::format(hdr_fmt,
<< std::setw(20) << "Support Flags" "Remote Host", "Type", "Peer id", "Recv/Sent (inactive,sec)", "State", "Livetime(sec)",
<< std::setw(30) << "Recv/Sent (inactive,sec)" "Down (kB/sec)", "Down(now)", "Up (kB/s)", "Up(now)");
<< std::setw(25) << "State"
<< std::setw(20) << "Livetime(sec)"
<< std::setw(12) << "Down (kB/s)"
<< std::setw(14) << "Down(now)"
<< std::setw(10) << "Up (kB/s)"
<< std::setw(13) << "Up(now)"
<< std::endl;
for (auto & info : res.connections) for (auto & info : res.connections)
{ {
std::string address = info.incoming ? "INC " : "OUT "; std::string address = info.incoming ? "INC " : "OUT ";
address += info.ip + ":" + info.port; address += info.ip;
//std::string in_out = info.incoming ? "INC " : "OUT "; address += ':';
tools::msg_writer() address += info.port;
//<< std::setw(30) << std::left << in_out tools::msg_writer() << fmt::format(row_fmt,
<< std::setw(30) << std::left << address address,
<< std::setw(8) << (get_address_type_name((epee::net_utils::address_type)info.address_type)) info.address_type,
<< std::setw(20) << info.peer_id info.peer_id,
<< std::setw(20) << info.support_flags fmt::format("{}({}/{})", info.recv_count,
<< std::setw(30) << std::to_string(info.recv_count) + "(" + std::to_string(tools::to_seconds(info.recv_idle_time)) + ")/" + std::to_string(info.send_count) + "(" + std::to_string(tools::to_seconds(info.send_idle_time)) + ")" tools::friendly_duration(info.recv_idle_time),
<< std::setw(25) << info.state tools::friendly_duration(info.send_idle_time)),
<< std::setw(20) << std::to_string(tools::to_seconds(info.live_time)) info.state,
<< std::setw(12) << info.avg_download tools::friendly_duration(info.live_time),
<< std::setw(14) << info.current_download info.avg_upload / 1000.,
<< std::setw(10) << info.avg_upload info.current_download / 1000.,
<< std::setw(13) << info.current_upload info.avg_upload / 1000.,
info.current_upload / 1000.,
<< std::left << (info.localhost ? "[LOCALHOST]" : "") info.localhost ? "[LOCALHOST]" : "",
<< std::left << (info.local_ip ? "[LAN]" : ""); info.local_ip ? "[LAN]" : "");
//tools::msg_writer() << boost::format("%-25s peer_id: %-25s %s") % address % info.peer_id % in_out;
} }
return true; return true;
@ -691,24 +668,24 @@ bool rpc_command_executor::print_net_stats()
uint64_t average = seconds > 0 ? net_stats_res.total_bytes_in / seconds : 0; uint64_t average = seconds > 0 ? net_stats_res.total_bytes_in / seconds : 0;
uint64_t limit = limit_res.limit_down * 1024; // convert to bytes, as limits are always kB/s uint64_t limit = limit_res.limit_down * 1024; // convert to bytes, as limits are always kB/s
double percent = (double)average / (double)limit * 100.0; double percent = (double)average / (double)limit * 100.0;
tools::success_msg_writer() << boost::format("Received %u bytes (%s) in %u packets, average %s/s = %.2f%% of the limit of %s/s") tools::success_msg_writer() << fmt::format("Received {} bytes ({}) in {} packets, average {}/s = {:.2f}% of the limit of {}/s",
% net_stats_res.total_bytes_in net_stats_res.total_bytes_in,
% tools::get_human_readable_bytes(net_stats_res.total_bytes_in) tools::get_human_readable_bytes(net_stats_res.total_bytes_in),
% net_stats_res.total_packets_in net_stats_res.total_packets_in,
% tools::get_human_readable_bytes(average) tools::get_human_readable_bytes(average),
% percent percent,
% tools::get_human_readable_bytes(limit); tools::get_human_readable_bytes(limit));
average = seconds > 0 ? net_stats_res.total_bytes_out / seconds : 0; average = seconds > 0 ? net_stats_res.total_bytes_out / seconds : 0;
limit = limit_res.limit_up * 1024; limit = limit_res.limit_up * 1024;
percent = (double)average / (double)limit * 100.0; percent = (double)average / (double)limit * 100.0;
tools::success_msg_writer() << boost::format("Sent %u bytes (%s) in %u packets, average %s/s = %.2f%% of the limit of %s/s") tools::success_msg_writer() << fmt::format("Sent {} bytes ({}) in {} packets, average {}/s = {:.2f}% of the limit of {}/s",
% net_stats_res.total_bytes_out net_stats_res.total_bytes_out,
% tools::get_human_readable_bytes(net_stats_res.total_bytes_out) tools::get_human_readable_bytes(net_stats_res.total_bytes_out),
% net_stats_res.total_packets_out net_stats_res.total_packets_out,
% tools::get_human_readable_bytes(average) tools::get_human_readable_bytes(average),
% percent percent,
% tools::get_human_readable_bytes(limit); tools::get_human_readable_bytes(limit));
return true; return true;
} }
@ -1043,7 +1020,7 @@ bool rpc_command_executor::print_transaction_pool_stats() {
else else
{ {
uint64_t backlog = (res.pool_stats.bytes_total + full_reward_zone - 1) / full_reward_zone; uint64_t backlog = (res.pool_stats.bytes_total + full_reward_zone - 1) / full_reward_zone;
backlog_message = (boost::format("estimated %u block (%u minutes) backlog") % backlog % (backlog * TARGET_BLOCK_TIME / 1min)).str(); backlog_message = fmt::format("estimated {} block ({} minutes) backlog", backlog, (backlog * TARGET_BLOCK_TIME / 1min));
} }
tools::msg_writer() << n_transactions << " tx(es), " << res.pool_stats.bytes_total << " bytes total (min " << res.pool_stats.bytes_min << ", max " << res.pool_stats.bytes_max << ", avg " << avg_bytes << ", median " << res.pool_stats.bytes_med << ")" << std::endl tools::msg_writer() << n_transactions << " tx(es), " << res.pool_stats.bytes_total << " bytes total (min " << res.pool_stats.bytes_min << ", max " << res.pool_stats.bytes_max << ", avg " << avg_bytes << ", median " << res.pool_stats.bytes_med << ")" << std::endl

View File

@ -38,7 +38,7 @@
#include <sstream> #include <sstream>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/format.hpp> #include <fmt/core.h>
#include "crypto/crypto.h" // for crypto::secret_key definition #include "crypto/crypto.h" // for crypto::secret_key definition
#include "common/i18n.h" #include "common/i18n.h"
#include "common/command_line.h" #include "common/command_line.h"
@ -78,7 +78,7 @@ namespace
static bool generate_multisig(uint32_t threshold, uint32_t total, const fs::path& basename, network_type nettype, bool create_address_file) static bool generate_multisig(uint32_t threshold, uint32_t total, const fs::path& basename, network_type nettype, bool create_address_file)
{ {
tools::msg_writer() << (boost::format(genms::tr("Generating %u %u/%u multisig wallets")) % total % threshold % total).str(); tools::msg_writer() << fmt::format(genms::tr("Generating {:d} {:d}/{:d} multisig wallets"), total, threshold, total);
const auto pwd_container = tools::password_container::prompt(true, "Enter password for new multisig wallets"); const auto pwd_container = tools::password_container::prompt(true, "Enter password for new multisig wallets");
@ -227,7 +227,7 @@ int main(int argc, char* argv[])
} }
if (threshold <= 1 || threshold > total) if (threshold <= 1 || threshold > total)
{ {
tools::fail_msg_writer() << (boost::format(genms::tr("Error: expected N > 1 and N <= M, but got N==%u and M==%d")) % threshold % total).str(); tools::fail_msg_writer() << fmt::format(genms::tr("Error: expected N > 1 and N <= M, but got N=={:d} and M=={:d}"), threshold, total);
return 1; return 1;
} }
fs::path basename; fs::path basename;