Skip to content

Commit fe39acf

Browse files
ryanofskyMarcoFalke
andcommitted
tinyformat: Add compile-time checking for literal format strings
Co-authored-by: MarcoFalke <*~=`'#}+{/-|&$^[email protected]>
1 parent 184f34f commit fe39acf

File tree

2 files changed

+17
-22
lines changed

2 files changed

+17
-22
lines changed

src/tinyformat.h

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ namespace tfm = tinyformat;
145145
#include <iostream>
146146
#include <sstream>
147147
#include <stdexcept> // Added for Bitcoin Core
148+
#include <util/string.h> // Added for Bitcoin Core
148149

149150
#ifndef TINYFORMAT_ASSERT
150151
# include <cassert>
@@ -178,6 +179,18 @@ namespace tfm = tinyformat;
178179

179180
namespace tinyformat {
180181

182+
// Added for Bitcoin Core. Wrapper for checking format strings at compile time.
183+
// Unlike ConstevalFormatString this supports std::string for runtime string
184+
// formatting without compile time checks.
185+
template <unsigned num_params>
186+
struct FormatStringCheck {
187+
consteval FormatStringCheck(const char* str) : fmt{util::ConstevalFormatString<num_params>{str}.fmt} {}
188+
FormatStringCheck(const std::string& str) : fmt{str.c_str()} {}
189+
FormatStringCheck(util::ConstevalFormatString<num_params> str) : fmt{str.fmt} {}
190+
operator const char*() { return fmt; }
191+
const char* fmt;
192+
};
193+
181194
// Added for Bitcoin Core
182195
class format_error: public std::runtime_error
183196
{
@@ -1056,15 +1069,15 @@ inline void vformat(std::ostream& out, const char* fmt, FormatListRef list)
10561069

10571070
/// Format list of arguments to the stream according to given format string.
10581071
template<typename... Args>
1059-
void format(std::ostream& out, const char* fmt, const Args&... args)
1072+
void format(std::ostream& out, FormatStringCheck<sizeof...(Args)> fmt, const Args&... args)
10601073
{
10611074
vformat(out, fmt, makeFormatList(args...));
10621075
}
10631076

10641077
/// Format list of arguments according to the given format string and return
10651078
/// the result as a string.
10661079
template<typename... Args>
1067-
std::string format(const char* fmt, const Args&... args)
1080+
std::string format(FormatStringCheck<sizeof...(Args)> fmt, const Args&... args)
10681081
{
10691082
std::ostringstream oss;
10701083
format(oss, fmt, args...);
@@ -1073,13 +1086,13 @@ std::string format(const char* fmt, const Args&... args)
10731086

10741087
/// Format list of arguments to std::cout, according to the given format string
10751088
template<typename... Args>
1076-
void printf(const char* fmt, const Args&... args)
1089+
void printf(FormatStringCheck<sizeof...(Args)> fmt, const Args&... args)
10771090
{
10781091
format(std::cout, fmt, args...);
10791092
}
10801093

10811094
template<typename... Args>
1082-
void printfln(const char* fmt, const Args&... args)
1095+
void printfln(FormatStringCheck<sizeof...(Args)> fmt, const Args&... args)
10831096
{
10841097
format(std::cout, fmt, args...);
10851098
std::cout << '\n';
@@ -1145,15 +1158,6 @@ TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMAT_FUNCS)
11451158

11461159
#endif
11471160

1148-
// Added for Bitcoin Core
1149-
template<typename... Args>
1150-
std::string format(const std::string &fmt, const Args&... args)
1151-
{
1152-
std::ostringstream oss;
1153-
format(oss, fmt.c_str(), args...);
1154-
return oss.str();
1155-
}
1156-
11571161
} // namespace tinyformat
11581162

11591163
// Added for Bitcoin Core:

src/util/string.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#define BITCOIN_UTIL_STRING_H
77

88
#include <span.h>
9-
#include <tinyformat.h>
109

1110
#include <array>
1211
#include <cstdint>
@@ -247,12 +246,4 @@ template <typename T1, size_t PREFIX_LEN>
247246
}
248247
} // namespace util
249248

250-
namespace tinyformat {
251-
template <typename... Args>
252-
std::string format(util::ConstevalFormatString<sizeof...(Args)> fmt, const Args&... args)
253-
{
254-
return format(fmt.fmt, args...);
255-
}
256-
} // namespace tinyformat
257-
258249
#endif // BITCOIN_UTIL_STRING_H

0 commit comments

Comments
 (0)