Skip to content

Commit

Permalink
Optimize StringBuilder append for static strings, and as_string().
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivorforce committed Nov 28, 2024
1 parent f128f38 commit 5f2f32a
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 19 deletions.
24 changes: 12 additions & 12 deletions core/string/string_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ StringBuilder &StringBuilder::append(const String &p_string) {
return *this;
}

StringBuilder &StringBuilder::append(const char *p_cstring) {
int32_t len = strlen(p_cstring);
StringBuilder &StringBuilder::append(const char *p_cstring, const uint32_t len) {
if (!p_cstring || len == 0) {
return *this;
}

c_strings.push_back(p_cstring);
appended_strings.push_back(len);
Expand All @@ -62,31 +64,29 @@ String StringBuilder::as_string() const {
}

char32_t *buffer = memnew_arr(char32_t, string_length);

int current_position = 0;
char32_t *buffer_ptr = buffer;

int godot_string_elem = 0;
int c_string_elem = 0;

for (int i = 0; i < appended_strings.size(); i++) {

Check failure on line 72 in core/string/string_builder.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor w/ Mono (target=editor)

comparison of integer expressions of different signedness: 'int' and 'unsigned int' [-Werror=sign-compare]

Check failure on line 72 in core/string/string_builder.cpp

View workflow job for this annotation

GitHub Actions / 🏁 Windows / Editor (target=editor, tests=yes)

the following warning is treated as an error

Check warning on line 72 in core/string/string_builder.cpp

View workflow job for this annotation

GitHub Actions / 🏁 Windows / Editor (target=editor, tests=yes)

'<': signed/unsigned mismatch

Check failure on line 72 in core/string/string_builder.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor with clang sanitizers (target=editor, tests=yes, dev_build=yes, use_asan=yes, use_ubsan=yes, use_llvm=yes, linker=lld)

comparison of integers of different signs: 'int' and 'unsigned int' [-Werror,-Wsign-compare]

Check failure on line 72 in core/string/string_builder.cpp

View workflow job for this annotation

GitHub Actions / 🏁 Windows / Template (target=template_release, tests=yes)

the following warning is treated as an error

Check warning on line 72 in core/string/string_builder.cpp

View workflow job for this annotation

GitHub Actions / 🏁 Windows / Template (target=template_release, tests=yes)

'<': signed/unsigned mismatch

Check failure on line 72 in core/string/string_builder.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor with ThreadSanitizer (target=editor, tests=yes, dev_build=yes, use_tsan=yes, use_llvm=yes, linker=lld)

comparison of integers of different signs: 'int' and 'unsigned int' [-Werror,-Wsign-compare]

Check failure on line 72 in core/string/string_builder.cpp

View workflow job for this annotation

GitHub Actions / 🏁 Windows / Template w/ GCC (target=template_release, tests=yes, use_mingw=yes)

comparison of integer expressions of different signedness: 'int' and 'unsigned int' [-Werror=sign-compare]

Check failure on line 72 in core/string/string_builder.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Template w/ Mono (target=template_release, tests=yes)

comparison of integer expressions of different signedness: 'int' and 'unsigned int' [-Werror=sign-compare]

Check failure on line 72 in core/string/string_builder.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Minimal template (target=template_release, tests=yes, everything disabled)

comparison of integer expressions of different signedness: 'int' and 'unsigned int' [-Werror=sign-compare]
if (appended_strings[i] == -1) {
const int c_string_len = appended_strings[i];

if (c_string_len == -1) {
// Godot string
const String &s = strings[godot_string_elem];

memcpy(buffer + current_position, s.ptr(), s.length() * sizeof(char32_t));

current_position += s.length();
memcpy(buffer_ptr, s.ptr(), s.length() * sizeof(char32_t));
buffer_ptr += s.length();

godot_string_elem++;
} else {
const char *s = c_strings[c_string_elem];

for (int32_t j = 0; j < appended_strings[i]; j++) {
buffer[current_position + j] = s[j];
for (int32_t j = 0; j < c_string_len; ++j, ++buffer_ptr, ++s) {
*buffer_ptr = *s;
}

current_position += appended_strings[i];

c_string_elem++;
}
}
Expand Down
33 changes: 26 additions & 7 deletions core/string/string_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,36 +32,55 @@
#define STRING_BUILDER_H

#include "core/string/ustring.h"
#include "core/templates/vector.h"
#include "core/templates/local_vector.h"

class StringBuilder {
uint32_t string_length = 0;

Vector<String> strings;
Vector<const char *> c_strings;
LocalVector<String> strings;
LocalVector<const char *> c_strings;

// -1 means it's a Godot String
// a natural number means C string.
Vector<int32_t> appended_strings;
LocalVector<int32_t> appended_strings;

public:
StringBuilder &append(const String &p_string);
StringBuilder &append(const char *p_cstring);
StringBuilder &append(const char *p_cstring, uint32_t len);

template <uint32_t len>
_FORCE_INLINE_ StringBuilder &append(const char (&p_cstring)[len]) {
return append(p_cstring, len - 1);
}

_FORCE_INLINE_ StringBuilder &append(const char *p_cstring) {
return append(p_cstring, strlen(p_cstring));
}

_FORCE_INLINE_ StringBuilder &operator+(const String &p_string) {
return append(p_string);
}

template <uint32_t len>
_FORCE_INLINE_ StringBuilder &operator+(const char (&p_cstring)[len]) {
return append(p_cstring, len - 1);
}

_FORCE_INLINE_ StringBuilder &operator+(const char *p_cstring) {
return append(p_cstring);
return append(p_cstring, strlen(p_cstring));
}

_FORCE_INLINE_ void operator+=(const String &p_string) {
append(p_string);
}

template <uint32_t len>
_FORCE_INLINE_ void operator+=(const char (&p_cstring)[len]) {
append(p_cstring, len - 1);
}

_FORCE_INLINE_ void operator+=(const char *p_cstring) {
append(p_cstring);
append(p_cstring, strlen(p_cstring));
}

_FORCE_INLINE_ int num_strings_appended() const {
Expand Down

0 comments on commit 5f2f32a

Please sign in to comment.