From 9f1f4d4d8d58fb6dc1bb884715a7cd8ed0516537 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 16 Mar 2026 19:59:18 +0100 Subject: [PATCH] utils.h: added helpers for efficient string concatination [skip ci] --- lib/tokenize.cpp | 5 +- lib/utils.h | 67 ++++++++++++++++++++ test/testutils.cpp | 151 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+), 3 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index a371df76e5d..1734a7ca2fd 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2418,8 +2418,7 @@ namespace { while (scope && scope->parent) { if (scope->name.empty()) break; - fullName.insert(0, " :: "); - fullName.insert(0, scope->name); + utils::string::prepend(fullName, scope->name, " :: "); scope = scope->parent; } } @@ -2588,7 +2587,7 @@ namespace { } // inline member function else if ((scopeInfo->type == ScopeInfo3::Record || scopeInfo->type == ScopeInfo3::Namespace) && tok1 && Token::Match(tok1->tokAt(-1), "%name% (")) { - std::string scope = scopeInfo->name + "::" + tok1->strAt(-1); + std::string scope = utils::string::create(scopeInfo->name, "::", tok1->strAt(-1)); scopeInfo = scopeInfo->addChild(ScopeInfo3::MemberFunction, std::move(scope), tok, tok->link()); added = true; } diff --git a/lib/utils.h b/lib/utils.h index 5a6927a5d96..3095473b7f4 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -436,6 +436,73 @@ namespace utils { return result; }; } + + namespace string + { + template + void concat(std::string &str, const char (&data)[size]) + { + str.append(data, size-1); + } + + inline void concat(std::string &str, char c) + { + str.append(1, c); + } + + template + void concat(std::string &str, T&& t) + { + str.append(t); + } + + template + void concat(std::string& str, T&& t, Args&&... args) + { + concat(str, t); + concat(str, args...); + } + + template + std::string create(char c, const Args&... args) + { + std::string str(1, c); + concat(str, args...); + return str; + } + + template + std::string create(const T& t, const Args&... args) + { + std::string str(t); + concat(str, args...); + return str; + } + + template + void prepend(std::string &str, const char (&data)[size]) + { + str.insert(0, data, size-1); + } + + inline void prepend(std::string &str, char c) + { + str.insert(0, 1, c); + } + + template + void prepend(std::string &str, T&& t) + { + str.insert(0, t); + } + + template + void prepend(std::string& str, T&& t, Args&&... args) + { + prepend(str, args...); + prepend(str, t); + } + } } #endif diff --git a/test/testutils.cpp b/test/testutils.cpp index b3da9b1f6dc..344e9735a82 100644 --- a/test/testutils.cpp +++ b/test/testutils.cpp @@ -45,6 +45,9 @@ class TestUtils : public TestFixture { TEST_CASE(as_const); TEST_CASE(memoize); TEST_CASE(endsWith); + TEST_CASE(stringConcat); + TEST_CASE(stringCreate); + TEST_CASE(stringPrepend); } void isValidGlobPattern() const { @@ -575,6 +578,154 @@ class TestUtils : public TestFixture { ASSERT(!::endsWith("tes", "test")); ASSERT(!::endsWith("2test", "2")); } + + void stringConcat() const + { + { + std::string s = "0"; + utils::string::concat(s, "a"); + utils::string::concat(s, "b"); + utils::string::concat(s, "c"); + ASSERT_EQUALS("0abc", s); + } + { + std::string s = "0"; + utils::string::concat(s, "a", "b", "c"); + ASSERT_EQUALS("0abc", s); + } + { + const std::string a_str = "a"; + const std::string b_str = "b"; + const std::string c_str = "c"; + { + std::string s = "0"; + utils::string::concat(s, a_str); + utils::string::concat(s, b_str); + utils::string::concat(s, c_str); + ASSERT_EQUALS("0abc", s); + } + { + std::string s = "0"; + utils::string::concat(s, a_str, b_str, c_str); + ASSERT_EQUALS("0abc", s); + } + } + { + std::string s = "0"; + utils::string::concat(s, 'a'); + utils::string::concat(s, 'b'); + utils::string::concat(s, 'c'); + ASSERT_EQUALS("0abc", s); + } + { + std::string s = "0"; + utils::string::concat(s, 'a', 'b', 'c'); + ASSERT_EQUALS("0abc", s); + } + { + const std::string a_str = "a"; + { + std::string s = "0"; + utils::string::concat(s, a_str); + utils::string::concat(s, 'b'); + utils::string::concat(s, "c"); + ASSERT_EQUALS("0abc", s); + } + { + std::string s = "0"; + utils::string::concat(s, a_str, 'b', "c"); + ASSERT_EQUALS("0abc", s); + } + } + } + + void stringCreate() const + { + { + std::string s = utils::string::create("a", "b", "c"); + ASSERT_EQUALS("abc", s); + } + { + const std::string a_str = "a"; + const std::string b_str = "b"; + const std::string c_str = "c"; + { + std::string s = utils::string::create(a_str, b_str, c_str); + ASSERT_EQUALS("abc", s); + } + } + { + std::string s = utils::string::create('a', 'b', 'c'); + ASSERT_EQUALS("abc", s); + } + { + const std::string a_str = "a"; + { + std::string s = utils::string::create(a_str, 'b', "c"); + ASSERT_EQUALS("abc", s); + } + } + } + + void stringPrepend() const + { + { + std::string s = "0"; + utils::string::prepend(s, "a"); + utils::string::prepend(s, "b"); + utils::string::prepend(s, "c"); + ASSERT_EQUALS("cba0", s); + } + { + std::string s = "0"; + utils::string::prepend(s, "a", "b", "c"); + ASSERT_EQUALS("abc0", s); + } + { + const std::string a_str = "a"; + const std::string b_str = "b"; + const std::string c_str = "c"; + { + std::string s = "0"; + utils::string::prepend(s, a_str); + utils::string::prepend(s, b_str); + utils::string::prepend(s, c_str); + ASSERT_EQUALS("cba0", s); + } + { + std::string s = "0"; + utils::string::prepend(s, a_str, b_str, c_str); + ASSERT_EQUALS("abc0", s); + } + } + { + std::string s = "0"; + utils::string::prepend(s, 'a'); + utils::string::prepend(s, 'b'); + utils::string::prepend(s, 'c'); + ASSERT_EQUALS("cba0", s); + } + { + std::string s = "0"; + utils::string::prepend(s, 'a', 'b', 'c'); + ASSERT_EQUALS("abc0", s); + } + { + const std::string a_str = "a"; + { + std::string s = "0"; + utils::string::prepend(s, a_str); + utils::string::prepend(s, 'b'); + utils::string::prepend(s, "c"); + ASSERT_EQUALS("cba0", s); + } + { + std::string s = "0"; + utils::string::prepend(s, a_str, 'b', "c"); + ASSERT_EQUALS("abc0", s); + } + } + } }; REGISTER_TEST(TestUtils)