Skip to content

Commit e6086e0

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

File tree

2 files changed

+15
-20
lines changed

2 files changed

+15
-20
lines changed

src/tinyformat.h

Lines changed: 15 additions & 11 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...);
@@ -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>
@@ -258,12 +257,4 @@ template <typename T1, size_t PREFIX_LEN>
258257
}
259258
} // namespace util
260259

261-
namespace tinyformat {
262-
template <typename... Args>
263-
std::string format(util::ConstevalFormatString<sizeof...(Args)> fmt, const Args&... args)
264-
{
265-
return format(fmt.fmt, args...);
266-
}
267-
} // namespace tinyformat
268-
269260
#endif // BITCOIN_UTIL_STRING_H

0 commit comments

Comments
 (0)