Skip to content

Commit 26e56b6

Browse files
Copilotnunoplopes
andauthored
wip: plan char+space single-append optimization
Agent-Logs-Url: https://github.com/Cpp2Rust/cpp2rust/sessions/c9bd1adc-01f6-415e-a50c-9e8a4cb1e414 Co-authored-by: nunoplopes <2998477+nunoplopes@users.noreply.github.com>
1 parent d3c464d commit 26e56b6

1 file changed

Lines changed: 36 additions & 41 deletions

File tree

cpp2rust/converter/converter.h

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -313,57 +313,52 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
313313

314314
#define StrCat(...) _StrCat(__FUNCTION__, __LINE__, __VA_ARGS__)
315315

316-
// All-literal overload: selected (by partial ordering) when every argument
317-
// is a string literal. Merges all literals (each followed by a space) into
318-
// a single buffer and performs one rs_code append instead of one per literal.
319-
// e.g. StrCat("foo", "bar") is equivalent to StrCat("foo bar").
320-
template <std::size_t... Ns>
321-
inline void _StrCat(const char *func, int line, const char (&...vals)[Ns]) {
316+
// Appends each argument to rs_code_, merging consecutive string literals
317+
// into a single buffer before each append. Non-literal arguments are
318+
// appended individually.
319+
// e.g. StrCat("foo", "bar", var1, "xyz") performs:
320+
// rs_code_ += "foo bar " (one append for the merged literal run)
321+
// rs_code_ += var1 + ' ' (one append for the non-literal)
322+
// rs_code_ += "xyz " (one append for the trailing literal)
323+
template <typename... Ts>
324+
inline void _StrCat(const char *func, int line, const Ts &...vals) {
322325
llvm::errs() << '[' << func << ':' << line << "] ";
323326
((llvm::errs() << vals << '\n'), ...);
324-
constexpr std::size_t total = (Ns + ...);
325-
const auto merged = _MergeStrings<total>(vals...);
326-
rs_code_->append(merged.data(), total);
327+
_AppendRuns(*rs_code_, std::array<char, 0>{}, vals...);
327328
}
328329

329-
// General fallback: used when at least one argument is not a string literal.
330-
// Each argument is appended individually (value then space).
331-
template <typename... Ts>
332-
inline void _StrCat(const char *func, int line, const Ts &...vals) {
333-
llvm::errs() << '[' << func << ':' << line << "] ";
334-
((llvm::errs() << vals << '\n', AppendToCode(*rs_code_, vals)), ...);
330+
// Base case: no more arguments. Flush the pending literal buffer if any.
331+
template <std::size_t BufSize>
332+
static void _AppendRuns(std::string &rs_code, std::array<char, BufSize> buf) {
333+
if constexpr (BufSize > 0)
334+
rs_code.append(buf.data(), BufSize);
335335
}
336336

337-
// Merges k string literals (each followed by a space) into a single
338-
// std::array<char, Total> where Total = sum(Ns). The null terminator of
339-
// each literal is dropped and replaced by a space character.
340-
template <std::size_t Total, std::size_t... Ns>
341-
static constexpr std::array<char, Total>
342-
_MergeStrings(const char (&...strs)[Ns]) {
343-
std::array<char, Total> result{};
344-
std::size_t pos = 0;
345-
auto fill = [&](const char *s, std::size_t n) {
346-
for (std::size_t i = 0; i < n - 1; ++i)
347-
result[pos++] = s[i];
348-
result[pos++] = ' ';
349-
};
350-
(fill(strs, Ns), ...);
351-
return result;
337+
// Head is a string literal: extend the pending buffer (N-1 content chars
338+
// followed by a space, replacing the null terminator) and recurse.
339+
template <std::size_t BufSize, std::size_t N, typename... Rest>
340+
static void _AppendRuns(std::string &rs_code, std::array<char, BufSize> buf,
341+
const char (&val)[N], const Rest &...rest) {
342+
std::array<char, BufSize + N> new_buf;
343+
for (std::size_t i = 0; i < BufSize; ++i)
344+
new_buf[i] = buf[i];
345+
for (std::size_t i = 0; i < N - 1; ++i)
346+
new_buf[BufSize + i] = val[i];
347+
new_buf[BufSize + N - 1] = ' ';
348+
_AppendRuns(rs_code, new_buf, rest...);
352349
}
353350

354-
// General fallback: append val then a space (two operations).
355-
template <typename T>
356-
static void AppendToCode(std::string &rs_code, const T &val) {
351+
// Head is NOT a string literal: flush the pending buffer (if any), append
352+
// the non-literal argument (value + space), then continue with an empty
353+
// buffer.
354+
template <std::size_t BufSize, typename T, typename... Rest>
355+
static void _AppendRuns(std::string &rs_code, std::array<char, BufSize> buf,
356+
const T &val, const Rest &...rest) {
357+
if constexpr (BufSize > 0)
358+
rs_code.append(buf.data(), BufSize);
357359
rs_code += val;
358360
rs_code += ' ';
359-
}
360-
361-
// Specialization for a single string literal in the general (mixed) path:
362-
// reuses _MergeStrings to perform one append call.
363-
template <std::size_t N>
364-
static void AppendToCode(std::string &rs_code, const char (&val)[N]) {
365-
const auto combined = _MergeStrings<N>(val);
366-
rs_code.append(combined.data(), N);
361+
_AppendRuns(rs_code, std::array<char, 0>{}, rest...);
367362
}
368363

369364
class Buffer {

0 commit comments

Comments
 (0)