refactor: Use std::format instead of boost::format where it fits (#7996)

Co-authored-by: Timur Yalymov <36795566+tyalymov@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com>
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
This commit is contained in:
Mayukha Vadari
2026-08-14 13:49:08 +00:00
committed by GitHub
parent a0074f83d3
commit d34aa37b3c
21 changed files with 286 additions and 182 deletions

View File

@@ -18,12 +18,11 @@
#include <xrpl/protocol/Serializer.h>
#include <xrpl/protocol/jss.h>
#include <boost/format/free_funcs.hpp>
#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdint>
#include <format>
#include <stdexcept>
#include <string>
#include <utility>
@@ -111,7 +110,7 @@ STLedgerEntry::getSType() const
std::string
STLedgerEntry::getText() const
{
return str(boost::format("{ %s, %s }") % to_string(key_) % STObject::getText());
return std::format("{{ {}, {} }}", to_string(key_), STObject::getText());
}
json::Value

View File

@@ -33,13 +33,13 @@
#include <xrpl/protocol/jss.h>
#include <boost/container/flat_set.hpp>
#include <boost/format/free_funcs.hpp>
#include <array>
#include <cstddef>
#include <cstdint>
#include <exception>
#include <expected>
#include <format>
#include <functional>
#include <memory>
#include <optional>
@@ -399,16 +399,21 @@ STTx::getMetaSQL(
TxnSql status,
std::string const& escapedMetaData) const
{
static boost::format const kBfTrans("('%s', '%s', '%s', '%d', '%d', '%c', %s, %s)");
std::string rTxn = sqlBlobLiteral(rawTxn.peekData());
auto format = TxFormats::getInstance().findByType(txType_);
XRPL_ASSERT(format, "xrpl::STTx::getMetaSQL : non-null type format");
return str(
boost::format(kBfTrans) % to_string(getTransactionID()) % format->getName() %
toBase58(getAccountID(sfAccount)) % getFieldU32(sfSequence) % inLedger %
safeCast<char>(status) % rTxn % escapedMetaData);
return std::format(
"('{}', '{}', '{}', '{}', '{}', '{}', {}, {})",
to_string(getTransactionID()),
format->getName(),
toBase58(getAccountID(sfAccount)),
getFieldU32(sfSequence),
inLedger,
safeCast<char>(status),
rTxn,
escapedMetaData);
}
static std::expected<void, std::string>

View File

@@ -11,9 +11,8 @@
#include <xrpl/protocol/Serializer.h>
#include <xrpl/protocol/jss.h>
#include <boost/format/free_funcs.hpp>
#include <cstddef>
#include <format>
#include <memory>
#include <stdexcept>
#include <string>
@@ -141,10 +140,15 @@ STXChainBridge::getJson(JsonOptions jo) const
std::string
STXChainBridge::getText() const
{
return str(
boost::format("{ %s = %s, %s = %s, %s = %s, %s = %s }") % sfLockingChainDoor.getName() %
lockingChainDoor_.getText() % sfLockingChainIssue.getName() % lockingChainIssue_.getText() %
sfIssuingChainDoor.getName() % issuingChainDoor_.getText() % sfIssuingChainIssue.getName() %
return std::format(
"{{ {} = {}, {} = {}, {} = {}, {} = {} }}",
sfLockingChainDoor.getName(),
lockingChainDoor_.getText(),
sfLockingChainIssue.getName(),
lockingChainIssue_.getText(),
sfIssuingChainDoor.getName(),
issuingChainDoor_.getText(),
sfIssuingChainIssue.getName(),
issuingChainIssue_.getText());
}

View File

@@ -5,8 +5,6 @@
#include <xrpl/rdb/DBInit.h>
#include <xrpl/rdb/DatabaseCon.h>
#include <boost/format.hpp> // IWYU pragma: keep
#include <soci/into.h>
#include <cstdint>
@@ -40,7 +38,7 @@ doVacuumDB(DatabaseCon::Setup const& setup, beast::Journal j)
// Only the most trivial databases will fit in memory on typical
// (recommended) hardware. Force temp files to be written to disk
// regardless of the config settings.
session << boost::format(kCommonDbPragmaTemp) % "file";
session << commonDbPragmaTemp("file");
session << "PRAGMA page_size;", soci::into(pageSize);
std::cout << "VACUUM beginning. page_size: " << pageSize << std::endl;

View File

@@ -16,7 +16,6 @@
#include <xrpl/rdb/SociDB.h>
#include <xrpl/server/Manifest.h>
#include <boost/format/free_funcs.hpp>
#include <boost/optional/optional.hpp> // IWYU pragma: keep
#include <soci/blob-exchange.h> // IWYU pragma: keep
@@ -30,6 +29,7 @@
#include <array>
#include <cstddef>
#include <format>
#include <functional>
#include <memory>
#include <string>
@@ -172,11 +172,10 @@ getNodeIdentity(soci::session& session)
// If a valid identity wasn't found, we randomly generate a new one:
auto [newpublicKey, newsecretKey] = randomKeyPair(KeyType::Secp256k1);
session << str(
boost::format(
"INSERT INTO NodeIdentity (PublicKey,PrivateKey) "
"VALUES ('%s','%s');") %
toBase58(TokenType::NodePublic, newpublicKey) %
session << std::format(
"INSERT INTO NodeIdentity (PublicKey,PrivateKey) "
"VALUES ('{}','{}');",
toBase58(TokenType::NodePublic, newpublicKey),
toBase58(TokenType::NodePrivate, newsecretKey));
return {newpublicKey, newsecretKey};

View File

@@ -20,6 +20,7 @@
#include <cstdint>
#include <exception>
#include <format>
#include <iostream>
#include <map>
#include <optional>
@@ -188,8 +189,7 @@ class AMMCalc_test : public beast::unit_test::Suite
static std::string
toString(STAmount const& a)
{
return (boost::format("%s/%s") % a.getText() % ::xrpl::to_string(a.get<Issue>().currency))
.str();
return std::format("{}/{}", a.getText(), ::xrpl::to_string(a.get<Issue>().currency));
}
static STAmount

View File

@@ -10,8 +10,6 @@
#include <xrpl/protocol/SystemParameters.h> // IWYU pragma: keep
#include <xrpl/server/Port.h>
#include <boost/format.hpp> // IWYU pragma: keep
#include <boost/format/free_funcs.hpp>
#include <boost/lexical_cast/bad_lexical_cast.hpp>
#include <array>
@@ -20,6 +18,7 @@
#include <cstdlib>
#include <exception>
#include <filesystem>
#include <format>
#include <fstream>
#include <optional>
#include <ostream>
@@ -36,7 +35,7 @@ namespace detail {
std::string
configContents(std::string const& dbPath, std::string const& validatorsFile)
{
static boost::format kConfigContentsTemplate(R"xrpldConfig(
static constexpr char const* kConfigContentsTemplate = R"xrpldConfig(
[server]
port_rpc
port_peer
@@ -83,9 +82,9 @@ cache_mb=256
file_size_mb=8
file_size_mult=2
%1%
{}
%2%
{}
# This needs to be an absolute directory reference, not a relative one.
# Modify this value as required.
@@ -106,7 +105,7 @@ r.ripple.com 51235
# Turn down default logging to save disk space in the long run.
# Valid values here are trace, debug, info, warning, error, and fatal
[rpc_startup]
{ "command": "log_level", "severity": "warning" }
{{ "command": "log_level", "severity": "warning" }}
# Defaults to 1 ("yes") so that certificates will be validated. To allow the use
# of self-signed certificates for development or internal use, set to 0 ("no").
@@ -115,12 +114,12 @@ r.ripple.com 51235
[sqdb]
backend=sqlite
)xrpldConfig");
)xrpldConfig";
std::string dbPathSection = dbPath.empty() ? "" : "[database_path]\n" + dbPath;
std::string valFileSection =
validatorsFile.empty() ? "" : "[validators_file]\n" + validatorsFile;
return boost::str(kConfigContentsTemplate % dbPathSection % valFileSection);
return std::format(kConfigContentsTemplate, dbPathSection, valFileSection);
}
/**
@@ -427,7 +426,7 @@ port_wss_admin
using namespace std::filesystem;
{
boost::format cc("[database_path]\n%1%\n");
constexpr char const* cc = "[database_path]\n{}\n";
auto const cwd = current_path();
path const dataDirRel("test_data_dir");
@@ -435,13 +434,13 @@ port_wss_admin
{
// Dummy test - do we get back what we put in
Config c;
c.loadFromString(boost::str(cc % dataDirAbs.string()));
c.loadFromString(std::format(cc, dataDirAbs.string()));
BEAST_EXPECT(c.legacy(Sections::kDatabasePath) == dataDirAbs.string());
}
{
// Rel paths should convert to abs paths
Config c;
c.loadFromString(boost::str(cc % dataDirRel.string()));
c.loadFromString(std::format(cc, dataDirRel.string()));
BEAST_EXPECT(c.legacy(Sections::kDatabasePath) == dataDirAbs.string());
}
{
@@ -508,20 +507,20 @@ port_wss_admin
{
Config c;
static boost::format kConfigTemplate(R"xrpldConfig(
static constexpr char const* kConfigTemplate = R"xrpldConfig(
[validation_seed]
%1%
{}
[validator_token]
%2%
)xrpldConfig");
{}
)xrpldConfig";
std::string error;
auto const expectedError =
"Cannot have both [validation_seed] "
"and [validator_token] config sections";
try
{
c.loadFromString(boost::str(kConfigTemplate % validationSeed % token));
c.loadFromString(std::format(kConfigTemplate, validationSeed, token));
}
catch (std::runtime_error const& e)
{
@@ -604,7 +603,7 @@ main
using namespace std::filesystem;
{
// load should throw for missing specified validators file
boost::format cc("[validators_file]\n%1%\n");
constexpr char const* cc = "[validators_file]\n{}\n";
std::string error;
std::string const missingPath = "/no/way/this/path/exists";
auto const expectedError =
@@ -612,7 +611,7 @@ main
try
{
Config c;
c.loadFromString(boost::str(cc % missingPath));
c.loadFromString(std::format(cc, missingPath));
}
catch (std::runtime_error const& e)
{
@@ -624,14 +623,14 @@ main
// load should throw for invalid [validators_file]
detail::ValidatorsTxtGuard const vtg(*this, "test_cfg", "validators.cfg");
path const invalidFile = current_path() / vtg.subdir();
boost::format cc("[validators_file]\n%1%\n");
constexpr char const* cc = "[validators_file]\n{}\n";
std::string error;
auto const expectedError =
"Invalid file specified in [validators_file]: " + invalidFile.string();
try
{
Config c;
c.loadFromString(boost::str(cc % invalidFile.string()));
c.loadFromString(std::format(cc, invalidFile.string()));
}
catch (std::runtime_error const& e)
{
@@ -829,8 +828,8 @@ trust-these-validators.gov
detail::ValidatorsTxtGuard const vtg(*this, "test_cfg", "validators.cfg");
BEAST_EXPECT(vtg.validatorsFileExists());
Config c;
boost::format cc("[validators_file]\n%1%\n");
c.loadFromString(boost::str(cc % vtg.validatorsFile()));
constexpr char const* cc = "[validators_file]\n{}\n";
c.loadFromString(std::format(cc, vtg.validatorsFile()));
BEAST_EXPECT(c.legacy(Sections::kValidatorsFile) == vtg.validatorsFile());
BEAST_EXPECT(c.section(Sections::kValidators).values().size() == 8);
BEAST_EXPECT(c.section(Sections::kValidatorListSites).values().size() == 2);
@@ -909,9 +908,9 @@ trust-these-validators.gov
{
// load validators from both config and validators file
boost::format cc(R"xrpldConfig(
constexpr char const* cc = R"xrpldConfig(
[validators_file]
%1%
{}
[validators]
n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7
@@ -930,11 +929,11 @@ trust-these-validators.gov
[validator_list_keys]
021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
)xrpldConfig");
)xrpldConfig";
detail::ValidatorsTxtGuard const vtg(*this, "test_cfg", "validators.cfg");
BEAST_EXPECT(vtg.validatorsFileExists());
Config c;
c.loadFromString(boost::str(cc % vtg.validatorsFile()));
c.loadFromString(std::format(cc, vtg.validatorsFile()));
BEAST_EXPECT(c.legacy(Sections::kValidatorsFile) == vtg.validatorsFile());
BEAST_EXPECT(c.section(Sections::kValidators).values().size() == 15);
BEAST_EXPECT(c.section(Sections::kValidatorListSites).values().size() == 4);
@@ -945,13 +944,13 @@ trust-these-validators.gov
{
// load should throw if [validator_list_threshold] is present both
// in xrpld.cfg and validators file
boost::format cc(R"xrpldConfig(
constexpr char const* cc = R"xrpldConfig(
[validators_file]
%1%
{}
[validator_list_threshold]
1
)xrpldConfig");
)xrpldConfig";
std::string error;
detail::ValidatorsTxtGuard const vtg(*this, "test_cfg", "validators.cfg");
BEAST_EXPECT(vtg.validatorsFileExists());
@@ -961,7 +960,7 @@ trust-these-validators.gov
try
{
Config c;
c.loadFromString(boost::str(cc % vtg.validatorsFile()));
c.loadFromString(std::format(cc, vtg.validatorsFile()));
fail();
}
catch (std::runtime_error const& e)
@@ -975,7 +974,7 @@ trust-these-validators.gov
// [validator_list_keys] are missing from xrpld.cfg and
// validators file
Config const c;
boost::format cc("[validators_file]\n%1%\n");
constexpr char const* cc = "[validators_file]\n{}\n";
std::string error;
detail::ValidatorsTxtGuard const vtg(*this, "test_cfg", "validators.cfg");
BEAST_EXPECT(vtg.validatorsFileExists());
@@ -988,7 +987,7 @@ trust-these-validators.gov
try
{
Config c2;
c2.loadFromString(boost::str(cc % vtg.validatorsFile()));
c2.loadFromString(std::format(cc, vtg.validatorsFile()));
}
catch (std::runtime_error const& e)
{

View File

@@ -9,8 +9,7 @@
#include <xrpl/protocol/jss.h>
#include <xrpl/server/NetworkOPs.h>
#include <boost/format/free_funcs.hpp>
#include <format>
#include <memory>
namespace xrpl::test {
@@ -36,12 +35,13 @@ public:
makeValidatorConfig()
{
auto p = std::make_unique<Config>();
boost::format toLoad(R"xrpldConfig(
auto const toLoad = std::format(
R"xrpldConfig(
[validator_token]
%1%
{}
[validators]
%2%
{}
[port_grpc]
ip = 0.0.0.0
@@ -52,9 +52,11 @@ ip = 0.0.0.0
port = 50052
protocol = wss2
admin = 127.0.0.1
)xrpldConfig");
)xrpldConfig",
validator_data::kToken,
validator_data::kPublicKey);
p->loadFromString(boost::str(toLoad % validator_data::kToken % validator_data::kPublicKey));
p->loadFromString(toLoad);
setupConfigForUnitTests(*p);

View File

@@ -0,0 +1,60 @@
#include <xrpl/protocol/STXChainBridge.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Issue.h>
#include <xrpl/protocol/UintTypes.h>
#include <gtest/gtest.h>
#include <string>
#include <string_view>
using namespace xrpl;
namespace {
// Built from raw bytes rather than base58 so the test does not depend on
// hand-computed checksums.
AccountID
account(std::string_view hex)
{
AccountID id;
EXPECT_TRUE(id.parseHex(hex));
return id;
}
} // namespace
// getText() builds its string from eight substitutions of the same type, so a
// transposed pair would still compile and still type check. Pin the output so
// the field/value pairing is actually verified.
TEST(STXChainBridge, getTextPairsEachFieldWithItsValue)
{
auto const lockingDoor = account("0102030405060708090A0B0C0D0E0F1011121314");
auto const issuingDoor = account("14131211100F0E0D0C0B0A090807060504030201");
auto const lockingIssue = xrpIssue();
Issue const issuingIssue{toCurrency("USD"), issuingDoor};
STXChainBridge const bridge{lockingDoor, lockingIssue, issuingDoor, issuingIssue};
std::string const expected = "{ LockingChainDoor = " + toBase58(lockingDoor) +
", LockingChainIssue = " + lockingIssue.getText() +
", IssuingChainDoor = " + toBase58(issuingDoor) +
", IssuingChainIssue = " + issuingIssue.getText() + " }";
EXPECT_EQ(bridge.getText(), expected);
}
TEST(STXChainBridge, getTextOnADefaultBridge)
{
STXChainBridge const bridge;
auto const text = bridge.getText();
// The outer braces are literal, and the four field names appear in
// declaration order regardless of the values.
EXPECT_TRUE(text.starts_with("{ LockingChainDoor = "));
EXPECT_TRUE(text.ends_with(" }"));
EXPECT_LT(text.find("LockingChainIssue"), text.find("IssuingChainDoor"));
EXPECT_LT(text.find("IssuingChainDoor"), text.find("IssuingChainIssue"));
}

View File

@@ -15,6 +15,10 @@
#include <xrpl/protocol/TxSearched.h>
#include <xrpl/protocol/XRPAmount.h>
// boost::optional (not std::optional) appears in the declarations below,
// because SOCI's into()/use() bindings only support boost::optional.
#include <boost/optional/optional.hpp>
#include <cstdint>
#include <memory>
#include <optional>

View File

@@ -10,8 +10,8 @@
#include <boost/asio/io_context.hpp>
#include <boost/asio/ssl/context.hpp>
#include <boost/asio/ssl/stream_base.hpp>
#include <boost/format/free_funcs.hpp>
#include <format>
#include <stdexcept>
#include <string>
@@ -38,7 +38,7 @@ WorkSSL::WorkSSL(
{
auto ec = context_.preConnectVerify(stream_, host_);
if (ec)
Throw<std::runtime_error>(boost::str(boost::format("preConnectVerify: %s") % ec.message()));
Throw<std::runtime_error>(std::format("preConnectVerify: {}", ec.message()));
}
void

View File

@@ -7,7 +7,6 @@
#include <xrpl/net/HTTPClientSSLContext.h>
#include <boost/asio/ssl.hpp>
#include <boost/format.hpp>
#include <memory>
#include <string>

View File

@@ -40,7 +40,6 @@
#include <xrpl/rdb/RelationalDatabase.h>
#include <xrpl/rdb/SociDB.h>
#include <boost/format/free_funcs.hpp>
#include <boost/optional/optional.hpp> // IWYU pragma: keep
#include <boost/system/detail/error_code.hpp>
@@ -58,6 +57,7 @@
#include <cstdint>
#include <exception>
#include <filesystem>
#include <format>
#include <functional>
#include <limits>
#include <map>
@@ -109,18 +109,16 @@ makeLedgerDBs(
// ledger database
auto lgr{std::make_unique<DatabaseCon>(
setup, kLgrDbName, setup.lgrPragma, kLgrDbInit, checkpointerSetup, j)};
lgr->getSession() << boost::str(
boost::format("PRAGMA cache_size=-%d;") %
kilobytes(config.getValueFor(SizedItem::LgrDbCache)));
lgr->getSession() << std::format(
"PRAGMA cache_size=-{};", kilobytes(config.getValueFor(SizedItem::LgrDbCache)));
if (config.useTxTables())
{
// transaction database
auto tx{std::make_unique<DatabaseCon>(
setup, kTxDbName, setup.txPragma, kTxDbInit, checkpointerSetup, j)};
tx->getSession() << boost::str(
boost::format("PRAGMA cache_size=-%d;") %
kilobytes(config.getValueFor(SizedItem::TxnDbCache)));
tx->getSession() << std::format(
"PRAGMA cache_size=-{};", kilobytes(config.getValueFor(SizedItem::TxnDbCache)));
if (!setup.standAlone || setup.startUp == StartUpType::Load ||
setup.startUp == StartUpType::LoadFile || setup.startUp == StartUpType::Replay)
@@ -280,15 +278,17 @@ saveValidatedLedger(
}
{
static boost::format kDeleteLedger("DELETE FROM Ledgers WHERE LedgerSeq = %u;");
static boost::format kDeleteTranS1("DELETE FROM Transactions WHERE LedgerSeq = %u;");
static boost::format kDeleteTranS2("DELETE FROM AccountTransactions WHERE LedgerSeq = %u;");
static boost::format kDeleteAcctTrans(
"DELETE FROM AccountTransactions WHERE TransID = '%s';");
static constexpr char const* kDeleteLedger = "DELETE FROM Ledgers WHERE LedgerSeq = {};";
static constexpr char const* kDeleteTranS1 =
"DELETE FROM Transactions WHERE LedgerSeq = {};";
static constexpr char const* kDeleteTranS2 =
"DELETE FROM AccountTransactions WHERE LedgerSeq = {};";
static constexpr char const* kDeleteAcctTrans =
"DELETE FROM AccountTransactions WHERE TransID = '{}';";
{
auto db = ldgDB.checkoutDb();
*db << boost::str(kDeleteLedger % seq);
*db << std::format(kDeleteLedger, seq);
}
if (app.config().useTxTables())
@@ -305,19 +305,19 @@ saveValidatedLedger(
soci::transaction tr(*db);
*db << boost::str(kDeleteTranS1 % seq);
*db << boost::str(kDeleteTranS2 % seq);
*db << std::format(kDeleteTranS1, seq);
*db << std::format(kDeleteTranS2, seq);
std::string const ledgerSeq(std::to_string(seq));
for (auto const& acceptedLedgerTx : *aLedger)
{
uint256 transactionID = acceptedLedgerTx->getTransactionID();
uint256 const transactionID = acceptedLedgerTx->getTransactionID();
std::string const txnId(to_string(transactionID));
std::string const txnSeq(std::to_string(acceptedLedgerTx->getTxnSeq()));
*db << boost::str(kDeleteAcctTrans % transactionID);
*db << std::format(kDeleteAcctTrans, txnId);
auto const& accts = acceptedLedgerTx->getAffected();
@@ -629,11 +629,11 @@ getHashesByIndex(soci::session& session, LedgerIndex minSeq, LedgerIndex maxSeq,
std::pair<std::vector<std::shared_ptr<Transaction>>, int>
getTxHistory(soci::session& session, Application& app, LedgerIndex startIndex, int quantity)
{
std::string const sql = boost::str(
boost::format(
"SELECT LedgerSeq, Status, RawTxn "
"FROM Transactions ORDER BY LedgerSeq DESC LIMIT %u,%u;") %
startIndex % quantity);
std::string const sql = std::format(
"SELECT LedgerSeq, Status, RawTxn "
"FROM Transactions ORDER BY LedgerSeq DESC LIMIT {},{};",
startIndex,
quantity);
std::vector<std::shared_ptr<Transaction>> txs;
int total = 0;
@@ -730,41 +730,50 @@ transactionsSQL(
if (options.ledgerRange.max != 0u)
{
maxClause = boost::str(
boost::format("AND AccountTransactions.LedgerSeq <= '%u'") % options.ledgerRange.max);
maxClause =
std::format("AND AccountTransactions.LedgerSeq <= '{}'", options.ledgerRange.max);
}
if (options.ledgerRange.min != 0u)
{
minClause = boost::str(
boost::format("AND AccountTransactions.LedgerSeq >= '%u'") % options.ledgerRange.min);
minClause =
std::format("AND AccountTransactions.LedgerSeq >= '{}'", options.ledgerRange.min);
}
std::string sql;
if (count)
{
sql = boost::str(
boost::format(
"SELECT %s FROM AccountTransactions "
"WHERE Account = '%s' %s %s LIMIT %u, %u;") %
selection % toBase58(options.account) % maxClause % minClause % options.offset %
sql = std::format(
"SELECT {} FROM AccountTransactions "
"WHERE Account = '{}' {} {} LIMIT {}, {};",
selection,
toBase58(options.account),
maxClause,
minClause,
options.offset,
numberOfResults);
}
else
{
sql = boost::str(
boost::format(
"SELECT %s FROM "
"AccountTransactions INNER JOIN Transactions "
"ON Transactions.TransID = AccountTransactions.TransID "
"WHERE Account = '%s' %s %s "
"ORDER BY AccountTransactions.LedgerSeq %s, "
"AccountTransactions.TxnSeq %s, AccountTransactions.TransID %s "
"LIMIT %u, %u;") %
selection % toBase58(options.account) % maxClause % minClause %
(descending ? "DESC" : "ASC") % (descending ? "DESC" : "ASC") %
(descending ? "DESC" : "ASC") % options.offset % numberOfResults);
char const* const order = descending ? "DESC" : "ASC";
sql = std::format(
"SELECT {} FROM "
"AccountTransactions INNER JOIN Transactions "
"ON Transactions.TransID = AccountTransactions.TransID "
"WHERE Account = '{}' {} {} "
"ORDER BY AccountTransactions.LedgerSeq {}, "
"AccountTransactions.TxnSeq {}, AccountTransactions.TransID {} "
"LIMIT {}, {};",
selection,
toBase58(options.account),
maxClause,
minClause,
order,
order,
order,
options.offset,
numberOfResults);
}
JLOG(j.trace()) << "txSQL query: " << sql;
return sql;
@@ -1105,14 +1114,6 @@ accountTxPage(
std::optional<RelationalDatabase::AccountTxMarker> newmarker;
static std::string const kPrefix(
R"(SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq,
Status,RawTxn,TxnMeta
FROM AccountTransactions INNER JOIN Transactions
ON Transactions.TransID = AccountTransactions.TransID
AND AccountTransactions.Account = '%s' WHERE
)");
std::string sql;
// SQL's BETWEEN uses a closed interval ([a,b])
@@ -1121,13 +1122,22 @@ accountTxPage(
if (findLedger == 0)
{
sql = boost::str(
boost::format(kPrefix + R"(AccountTransactions.LedgerSeq BETWEEN %u AND %u
ORDER BY AccountTransactions.LedgerSeq %s,
AccountTransactions.TxnSeq %s
LIMIT %u;)") %
toBase58(options.account) % options.ledgerRange.min % options.ledgerRange.max % order %
order % queryLimit);
sql = std::format(
R"(SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq,
Status,RawTxn,TxnMeta
FROM AccountTransactions INNER JOIN Transactions
ON Transactions.TransID = AccountTransactions.TransID
AND AccountTransactions.Account = '{}' WHERE
AccountTransactions.LedgerSeq BETWEEN {} AND {}
ORDER BY AccountTransactions.LedgerSeq {},
AccountTransactions.TxnSeq {}
LIMIT {};)",
toBase58(options.account),
options.ledgerRange.min,
options.ledgerRange.max,
order,
order,
queryLimit);
}
else
{
@@ -1136,27 +1146,34 @@ accountTxPage(
std::uint32_t const maxLedger = forward ? options.ledgerRange.max : findLedger - 1;
auto b58acct = toBase58(options.account);
sql = boost::str(
boost::format(
R"(SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq,
sql = std::format(
R"(SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq,
Status,RawTxn,TxnMeta
FROM AccountTransactions, Transactions WHERE
(AccountTransactions.TransID = Transactions.TransID AND
AccountTransactions.Account = '%s' AND
AccountTransactions.LedgerSeq BETWEEN %u AND %u)
AccountTransactions.Account = '{}' AND
AccountTransactions.LedgerSeq BETWEEN {} AND {})
UNION
SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq,Status,RawTxn,TxnMeta
FROM AccountTransactions, Transactions WHERE
(AccountTransactions.TransID = Transactions.TransID AND
AccountTransactions.Account = '%s' AND
AccountTransactions.LedgerSeq = %u AND
AccountTransactions.TxnSeq %s %u)
ORDER BY AccountTransactions.LedgerSeq %s,
AccountTransactions.TxnSeq %s
LIMIT %u;
)") %
b58acct % minLedger % maxLedger % b58acct % findLedger % compare % findSeq % order %
order % queryLimit);
AccountTransactions.Account = '{}' AND
AccountTransactions.LedgerSeq = {} AND
AccountTransactions.TxnSeq {} {})
ORDER BY AccountTransactions.LedgerSeq {},
AccountTransactions.TxnSeq {}
LIMIT {};
)",
b58acct,
minLedger,
maxLedger,
b58acct,
findLedger,
compare,
findSeq,
order,
order,
queryLimit);
}
{

View File

@@ -21,7 +21,6 @@
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/format/free_funcs.hpp>
#include <boost/multiprecision/detail/endian.hpp>
#include <boost/predef.h>
#include <boost/regex.hpp> // IWYU pragma: keep
@@ -34,6 +33,7 @@
#include <cstdint>
#include <cstdlib>
#include <filesystem>
#include <format>
#include <iostream>
#include <iterator>
#include <limits>
@@ -400,7 +400,7 @@ Config::setup(std::string const& strConf, bool bQuiet, bool bSilent, bool bStand
std::filesystem::create_directories(dataDir, ec);
if (ec)
Throw<std::runtime_error>(boost::str(boost::format("Can not create %s") % dataDir));
Throw<std::runtime_error>(std::format("Can not create {}", dataDir.string()));
legacy(Sections::kDatabasePath, std::filesystem::absolute(dataDir).string());
}
@@ -1315,8 +1315,7 @@ setupDatabaseCon(Config const& c, std::optional<beast::Journal> j)
boost::iequals(journalMode, "truncate") || boost::iequals(journalMode, "persist") ||
boost::iequals(journalMode, "wal"))
{
result->emplace_back(
boost::str(boost::format(kCommonDbPragmaJournal) % journalMode));
result->emplace_back(commonDbPragmaJournal(journalMode));
}
else
{
@@ -1337,7 +1336,7 @@ setupDatabaseCon(Config const& c, std::optional<beast::Journal> j)
if (higherRisk || boost::iequals(synchronous, "normal") ||
boost::iequals(synchronous, "full") || boost::iequals(synchronous, "extra"))
{
result->emplace_back(boost::str(boost::format(kCommonDbPragmaSync) % synchronous));
result->emplace_back(commonDbPragmaSync(synchronous));
}
else
{
@@ -1358,7 +1357,7 @@ setupDatabaseCon(Config const& c, std::optional<beast::Journal> j)
if (higherRisk || boost::iequals(tempStore, "default") ||
boost::iequals(tempStore, "file"))
{
result->emplace_back(boost::str(boost::format(kCommonDbPragmaTemp) % tempStore));
result->emplace_back(commonDbPragmaTemp(tempStore));
}
else
{

View File

@@ -37,6 +37,7 @@
#include <array>
#include <cstdint>
#include <cstring>
#include <format>
#include <functional>
#include <optional>
#include <tuple>
@@ -424,7 +425,7 @@ parseSubUnsubJson(
if (jv.isMember(jss::mpt_issuance_id) &&
(jv.isMember(jss::currency) || jv.isMember(jss::issuer)))
{
JLOG(j.info()) << boost::format("Bad %s currency or MPT.") % name.cStr();
JLOG(j.info()) << std::format("Bad {} currency or MPT.", name.cStr());
return RpcInvalidParams;
}
@@ -435,7 +436,7 @@ parseSubUnsubJson(
if (!jv.isMember(jss::currency) ||
!toCurrency(issue.currency, jv[jss::currency].asString()))
{
JLOG(j.info()) << boost::format("Bad %s currency.") % name.cStr();
JLOG(j.info()) << std::format("Bad {} currency.", name.cStr());
return assetError;
}
@@ -445,7 +446,7 @@ parseSubUnsubJson(
// Don't allow illegal issuers.
|| (!issue.currency != !issue.account) || noAccount() == issue.account)
{
JLOG(j.info()) << boost::format("Bad %s issuer.") % name.cStr();
JLOG(j.info()) << std::format("Bad {} issuer.", name.cStr());
return issuerError;
}
asset = issue;
@@ -459,7 +460,7 @@ parseSubUnsubJson(
}
else
{
JLOG(j.info()) << boost::format("Neither %s currency or MPT is present.") % name.cStr();
JLOG(j.info()) << std::format("Neither {} currency or MPT is present.", name.cStr());
return assetError;
}

View File

@@ -23,10 +23,9 @@
#include <xrpl/protocol/XRPAmount.h>
#include <xrpl/protocol/jss.h>
#include <boost/format/free_funcs.hpp>
#include <array>
#include <cstdint>
#include <format>
#include <memory>
#include <optional>
#include <string>
@@ -60,7 +59,7 @@ injectSLE(json::Value& jv, SLE const& sle)
md5 = toLower(md5);
// VFALCO TODO Give a name to this constant and move it
// to a more visible location.
jv[jss::urlgravatar] = str(boost::format("https://www.gravatar.com/avatar/%s") % md5);
jv[jss::urlgravatar] = std::format("https://www.gravatar.com/avatar/{}", md5);
}
}

View File

@@ -22,6 +22,7 @@
#include <xrpl/resource/Fees.h>
#include <xrpl/server/NetworkOPs.h>
#include <format>
#include <memory>
#include <optional>
@@ -32,7 +33,7 @@ validateTakerJSON(json::Value const& taker, json::StaticString const& name)
{
if (!taker.isMember(jss::currency) && !taker.isMember(jss::mpt_issuance_id))
{
return rpc::missingFieldError((boost::format("%s.currency") % name.cStr()).str());
return rpc::missingFieldError(std::format("{}.currency", name.cStr()));
}
if (taker.isMember(jss::mpt_issuance_id) &&
@@ -44,8 +45,7 @@ validateTakerJSON(json::Value const& taker, json::StaticString const& name)
if ((taker.isMember(jss::currency) && !taker[jss::currency].isString()) ||
(taker.isMember(jss::mpt_issuance_id) && !taker[jss::mpt_issuance_id].isString()))
{
return rpc::expectedFieldError(
(boost::format("%s.currency") % name.cStr()).str(), "string");
return rpc::expectedFieldError(std::format("{}.currency", name.cStr()), "string");
}
return std::nullopt;
@@ -70,10 +70,9 @@ parseTakerAssetJSON(
if (!toCurrency(issue.currency, taker[jss::currency].asString()))
{
JLOG(j.info()) << boost::format("Bad %s currency.") % name.cStr();
JLOG(j.info()) << std::format("Bad {} currency.", name.cStr());
return rpc::makeError(
assetError,
(boost::format("Invalid field '%s.currency', bad currency.") % name.cStr()).str());
assetError, std::format("Invalid field '{}.currency', bad currency.", name.cStr()));
}
asset = issue;
}
@@ -83,8 +82,7 @@ parseTakerAssetJSON(
if (!mptid.parseHex(taker[jss::mpt_issuance_id].asString()))
{
return rpc::makeError(
assetError,
(boost::format("Invalid field '%s.mpt_issuance_id'") % name.cStr()).str());
assetError, std::format("Invalid field '{}.mpt_issuance_id'", name.cStr()));
}
asset = mptid;
}
@@ -113,24 +111,21 @@ parseTakerIssuerJSON(
{
if (!taker[jss::issuer].isString())
{
return rpc::expectedFieldError(
(boost::format("%s.issuer") % name.cStr()).str(), "string");
return rpc::expectedFieldError(std::format("{}.issuer", name.cStr()), "string");
}
if (!toIssuer(issue.account, taker[jss::issuer].asString()))
{
return rpc::makeError(
issuerError,
(boost::format("Invalid field '%s.issuer', bad issuer.") % name.cStr()).str());
std::format("Invalid field '{}.issuer', bad issuer.", name.cStr()));
}
if (issue.account == noAccount())
{
return rpc::makeError(
issuerError,
(boost::format("Invalid field '%s.issuer', bad issuer account one.") %
name.cStr())
.str());
std::format("Invalid field '{}.issuer', bad issuer account one.", name.cStr()));
}
}
else
@@ -142,19 +137,17 @@ parseTakerIssuerJSON(
{
return rpc::makeError(
issuerError,
(boost::format(
"Unneeded field '%s.issuer' for XRP currency "
"specification.") %
name.cStr())
.str());
std::format(
"Unneeded field '{}.issuer' for XRP currency "
"specification.",
name.cStr()));
}
if (!isXRP(issue.currency) && isXRP(issue.account))
{
return rpc::makeError(
issuerError,
(boost::format("Invalid field '%s.issuer', expected non-XRP issuer.") % name.cStr())
.str());
std::format("Invalid field '{}.issuer', expected non-XRP issuer.", name.cStr()));
}
}