|
@@ -1007,7 +1007,7 @@ String String::to_camel_case() const {
|
|
}
|
|
}
|
|
|
|
|
|
String String::to_pascal_case() const {
|
|
String String::to_pascal_case() const {
|
|
- return capitalize().replace(" ", "");
|
|
|
|
|
|
+ return capitalize().remove_char(' ');
|
|
}
|
|
}
|
|
|
|
|
|
String String::to_snake_case() const {
|
|
String String::to_snake_case() const {
|
|
@@ -3102,6 +3102,130 @@ String String::erase(int p_pos, int p_chars) const {
|
|
return left(p_pos) + substr(p_pos + p_chars);
|
|
return left(p_pos) + substr(p_pos + p_chars);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+template <class T>
|
|
|
|
+static bool _contains_char(char32_t p_c, const T *p_chars, int p_chars_len) {
|
|
|
|
+ for (int i = 0; i < p_chars_len; ++i) {
|
|
|
|
+ if (p_c == (char32_t)p_chars[i]) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+String String::remove_char(char32_t p_char) const {
|
|
|
|
+ if (p_char == 0) {
|
|
|
|
+ return *this;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ int len = length();
|
|
|
|
+ if (len == 0) {
|
|
|
|
+ return *this;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ int index = 0;
|
|
|
|
+ const char32_t *old_ptr = ptr();
|
|
|
|
+ for (; index < len; ++index) {
|
|
|
|
+ if (old_ptr[index] == p_char) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // If no occurrence of `char` was found, return this.
|
|
|
|
+ if (index == len) {
|
|
|
|
+ return *this;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // If we found at least one occurrence of `char`, create new string, allocating enough space for the current length minus one.
|
|
|
|
+ String new_string;
|
|
|
|
+ new_string.resize(len);
|
|
|
|
+ char32_t *new_ptr = new_string.ptrw();
|
|
|
|
+
|
|
|
|
+ // Copy part of input before `char`.
|
|
|
|
+ memcpy(new_ptr, old_ptr, index * sizeof(char32_t));
|
|
|
|
+
|
|
|
|
+ int new_size = index;
|
|
|
|
+
|
|
|
|
+ // Copy rest, skipping `char`.
|
|
|
|
+ for (++index; index < len; ++index) {
|
|
|
|
+ const char32_t old_char = old_ptr[index];
|
|
|
|
+ if (old_char != p_char) {
|
|
|
|
+ new_ptr[new_size] = old_char;
|
|
|
|
+ ++new_size;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ new_ptr[new_size] = _null;
|
|
|
|
+
|
|
|
|
+ // Shrink new string to fit.
|
|
|
|
+ new_string.resize(new_size + 1);
|
|
|
|
+
|
|
|
|
+ return new_string;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+template <class T>
|
|
|
|
+static String _remove_chars_common(const String &p_this, const T *p_chars, int p_chars_len) {
|
|
|
|
+ // Delegate if p_chars has a single element.
|
|
|
|
+ if (p_chars_len == 1) {
|
|
|
|
+ return p_this.remove_char(*p_chars);
|
|
|
|
+ } else if (p_chars_len == 0) {
|
|
|
|
+ return p_this;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ int len = p_this.length();
|
|
|
|
+
|
|
|
|
+ if (len == 0) {
|
|
|
|
+ return p_this;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ int index = 0;
|
|
|
|
+ const char32_t *old_ptr = p_this.ptr();
|
|
|
|
+ for (; index < len; ++index) {
|
|
|
|
+ if (_contains_char(old_ptr[index], p_chars, p_chars_len)) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // If no occurrence of `chars` was found, return this.
|
|
|
|
+ if (index == len) {
|
|
|
|
+ return p_this;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // If we found at least one occurrence of `chars`, create new string, allocating enough space for the current length minus one.
|
|
|
|
+ String new_string;
|
|
|
|
+ new_string.resize(len);
|
|
|
|
+ char32_t *new_ptr = new_string.ptrw();
|
|
|
|
+
|
|
|
|
+ // Copy part of input before `char`.
|
|
|
|
+ memcpy(new_ptr, old_ptr, index * sizeof(char32_t));
|
|
|
|
+
|
|
|
|
+ int new_size = index;
|
|
|
|
+
|
|
|
|
+ // Copy rest, skipping `chars`.
|
|
|
|
+ for (++index; index < len; ++index) {
|
|
|
|
+ const char32_t old_char = old_ptr[index];
|
|
|
|
+ if (!_contains_char(old_char, p_chars, p_chars_len)) {
|
|
|
|
+ new_ptr[new_size] = old_char;
|
|
|
|
+ ++new_size;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ new_ptr[new_size] = 0;
|
|
|
|
+
|
|
|
|
+ // Shrink new string to fit.
|
|
|
|
+ new_string.resize(new_size + 1);
|
|
|
|
+
|
|
|
|
+ return new_string;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+String String::remove_chars(const String &p_chars) const {
|
|
|
|
+ return _remove_chars_common(*this, p_chars.ptr(), p_chars.length());
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+String String::remove_chars(const char *p_chars) const {
|
|
|
|
+ return _remove_chars_common(*this, p_chars, strlen(p_chars));
|
|
|
|
+}
|
|
|
|
+
|
|
String String::substr(int p_from, int p_chars) const {
|
|
String String::substr(int p_from, int p_chars) const {
|
|
if (p_chars == -1) {
|
|
if (p_chars == -1) {
|
|
p_chars = length() - p_from;
|
|
p_chars = length() - p_from;
|