Skip to content

Commit 354026d

Browse files
addaleaxtargos
authored andcommitted
src: allow std::string_view arguments to SPrintF() and friends
Modernize the code so there is no need to work with raw C strings anymore. PR-URL: #60058 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
1 parent 42f7d7c commit 354026d

File tree

3 files changed

+44
-32
lines changed

3 files changed

+44
-32
lines changed

src/debug_utils-inl.h

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -65,33 +65,42 @@ std::string ToBaseString(const T& value) {
6565
return ToStringHelper::BaseConvert<BASE_BITS>(value);
6666
}
6767

68-
inline std::string SPrintFImpl(const char* format) {
69-
const char* p = strchr(format, '%');
70-
if (p == nullptr) [[unlikely]]
71-
return format;
72-
CHECK_EQ(p[1], '%'); // Only '%%' allowed when there are no arguments.
68+
inline std::string SPrintFImpl(std::string_view format) {
69+
auto offset = format.find('%');
70+
if (offset == std::string_view::npos) return std::string(format);
71+
CHECK_LT(offset + 1, format.size());
72+
CHECK_EQ(format[offset + 1],
73+
'%'); // Only '%%' allowed when there are no arguments.
7374

74-
return std::string(format, p + 1) + SPrintFImpl(p + 2);
75+
return std::string(format.substr(0, offset + 1)) +
76+
SPrintFImpl(format.substr(offset + 2));
7577
}
7678

7779
template <typename Arg, typename... Args>
7880
std::string COLD_NOINLINE SPrintFImpl( // NOLINT(runtime/string)
79-
const char* format, Arg&& arg, Args&&... args) {
80-
const char* p = strchr(format, '%');
81-
CHECK_NOT_NULL(p); // If you hit this, you passed in too many arguments.
82-
std::string ret(format, p);
81+
std::string_view format,
82+
Arg&& arg,
83+
Args&&... args) {
84+
auto offset = format.find('%');
85+
CHECK_NE(offset, std::string_view::npos); // If you hit this, you passed in
86+
// too many arguments.
87+
std::string ret(format.substr(0, offset));
8388
// Ignore long / size_t modifiers
84-
while (strchr("lz", *++p) != nullptr) {}
85-
switch (*p) {
89+
while (++offset < format.size() &&
90+
(format[offset] == 'l' || format[offset] == 'z')) {
91+
}
92+
switch (offset == format.size() ? '\0' : format[offset]) {
8693
case '%': {
87-
return ret + '%' + SPrintFImpl(p + 1,
88-
std::forward<Arg>(arg),
89-
std::forward<Args>(args)...);
94+
return ret + '%' +
95+
SPrintFImpl(format.substr(offset + 1),
96+
std::forward<Arg>(arg),
97+
std::forward<Args>(args)...);
9098
}
9199
default: {
92-
return ret + '%' + SPrintFImpl(p,
93-
std::forward<Arg>(arg),
94-
std::forward<Args>(args)...);
100+
return ret + '%' +
101+
SPrintFImpl(format.substr(offset),
102+
std::forward<Arg>(arg),
103+
std::forward<Args>(args)...);
95104
}
96105
case 'd':
97106
case 'i':
@@ -120,17 +129,21 @@ std::string COLD_NOINLINE SPrintFImpl( // NOLINT(runtime/string)
120129
break;
121130
}
122131
}
123-
return ret + SPrintFImpl(p + 1, std::forward<Args>(args)...);
132+
return ret +
133+
SPrintFImpl(format.substr(offset + 1), std::forward<Args>(args)...);
124134
}
125135

126136
template <typename... Args>
127137
std::string COLD_NOINLINE SPrintF( // NOLINT(runtime/string)
128-
const char* format, Args&&... args) {
138+
std::string_view format,
139+
Args&&... args) {
129140
return SPrintFImpl(format, std::forward<Args>(args)...);
130141
}
131142

132143
template <typename... Args>
133-
void COLD_NOINLINE FPrintF(FILE* file, const char* format, Args&&... args) {
144+
void COLD_NOINLINE FPrintF(FILE* file,
145+
std::string_view format,
146+
Args&&... args) {
134147
FWrite(file, SPrintF(format, std::forward<Args>(args)...));
135148
}
136149

src/debug_utils.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ inline std::string ToString(const T& value);
3333
// - Supports %p and %s. %d, %i and %u are aliases for %s.
3434
// - Accepts any class that has a ToString() method for stringification.
3535
template <typename... Args>
36-
inline std::string SPrintF(const char* format, Args&&... args);
36+
inline std::string SPrintF(std::string_view format, Args&&... args);
3737
template <typename... Args>
38-
inline void FPrintF(FILE* file, const char* format, Args&&... args);
38+
inline void FPrintF(FILE* file, std::string_view format, Args&&... args);
3939
void NODE_EXTERN_PRIVATE FWrite(FILE* file, const std::string& str);
4040

4141
// Listing the AsyncWrap provider types first enables us to cast directly

src/node_errors.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ void OOMErrorHandler(const char* location, const v8::OOMDetails& details);
140140
#define V(code, type) \
141141
template <typename... Args> \
142142
inline v8::Local<v8::Object> code( \
143-
v8::Isolate* isolate, const char* format, Args&&... args) { \
143+
v8::Isolate* isolate, std::string_view format, Args&&... args) { \
144144
std::string message; \
145145
if (sizeof...(Args) == 0) { \
146146
message = format; \
@@ -165,17 +165,18 @@ void OOMErrorHandler(const char* location, const v8::OOMDetails& details);
165165
} \
166166
template <typename... Args> \
167167
inline void THROW_##code( \
168-
v8::Isolate* isolate, const char* format, Args&&... args) { \
168+
v8::Isolate* isolate, std::string_view format, Args&&... args) { \
169169
isolate->ThrowException( \
170170
code(isolate, format, std::forward<Args>(args)...)); \
171171
} \
172172
template <typename... Args> \
173173
inline void THROW_##code( \
174-
Environment* env, const char* format, Args&&... args) { \
174+
Environment* env, std::string_view format, Args&&... args) { \
175175
THROW_##code(env->isolate(), format, std::forward<Args>(args)...); \
176176
} \
177177
template <typename... Args> \
178-
inline void THROW_##code(Realm* realm, const char* format, Args&&... args) { \
178+
inline void THROW_##code( \
179+
Realm* realm, std::string_view format, Args&&... args) { \
179180
THROW_##code(realm->isolate(), format, std::forward<Args>(args)...); \
180181
}
181182
ERRORS_WITH_CODE(V)
@@ -258,10 +259,8 @@ PREDEFINED_ERROR_MESSAGES(V)
258259
// Errors with predefined non-static messages
259260
inline void THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(Environment* env,
260261
int64_t timeout) {
261-
std::ostringstream message;
262-
message << "Script execution timed out after ";
263-
message << timeout << "ms";
264-
THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(env, message.str().c_str());
262+
THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(
263+
env, "Script execution timed out after %dms", timeout);
265264
}
266265

267266
inline void THROW_ERR_REQUIRE_ASYNC_MODULE(
@@ -283,7 +282,7 @@ inline void THROW_ERR_REQUIRE_ASYNC_MODULE(
283282
message += "\n Requiring ";
284283
message += utf8.ToStringView();
285284
}
286-
THROW_ERR_REQUIRE_ASYNC_MODULE(env, message.c_str());
285+
THROW_ERR_REQUIRE_ASYNC_MODULE(env, message);
287286
}
288287

289288
inline v8::Local<v8::Object> ERR_BUFFER_TOO_LARGE(v8::Isolate* isolate) {

0 commit comments

Comments
 (0)