1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-25 15:37:42 +00:00

Add const char * overloads to String class

Co-authored-by: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com>
This commit is contained in:
Wilson E. Alvarez
2023-11-02 15:15:48 -04:00
parent 55b8724bd5
commit d4154dbc55
5 changed files with 670 additions and 158 deletions

View File

@@ -1184,6 +1184,26 @@ int String::get_slice_count(const String &p_splitter) const {
return slices;
}
int String::get_slice_count(const char *p_splitter) const {
if (is_empty()) {
return 0;
}
if (p_splitter == nullptr || *p_splitter == '\0') {
return 0;
}
int pos = 0;
int slices = 1;
int splitter_length = strlen(p_splitter);
while ((pos = find(p_splitter, pos)) >= 0) {
slices++;
pos += splitter_length;
}
return slices;
}
String String::get_slice(const String &p_splitter, int p_slice) const {
if (is_empty() || p_splitter.is_empty()) {
return "";
@@ -1224,6 +1244,47 @@ String String::get_slice(const String &p_splitter, int p_slice) const {
return ""; //no find!
}
String String::get_slice(const char *p_splitter, int p_slice) const {
if (is_empty() || p_splitter == nullptr || *p_splitter == '\0') {
return "";
}
int pos = 0;
int prev_pos = 0;
//int slices=1;
if (p_slice < 0) {
return "";
}
if (find(p_splitter) == -1) {
return *this;
}
int i = 0;
int splitter_length = strlen(p_splitter);
while (true) {
pos = find(p_splitter, pos);
if (pos == -1) {
pos = length(); //reached end
}
int from = prev_pos;
//int to=pos;
if (p_slice == i) {
return substr(from, pos - from);
}
if (pos == length()) { //reached end and no find
break;
}
pos += splitter_length;
prev_pos = pos;
i++;
}
return ""; //no find!
}
String String::get_slicec(char32_t p_splitter, int p_slice) const {
if (is_empty()) {
return String();
@@ -1338,6 +1399,54 @@ Vector<String> String::split(const String &p_splitter, bool p_allow_empty, int p
return ret;
}
Vector<String> String::split(const char *p_splitter, bool p_allow_empty, int p_maxsplit) const {
Vector<String> ret;
if (is_empty()) {
if (p_allow_empty) {
ret.push_back("");
}
return ret;
}
int from = 0;
int len = length();
while (true) {
int end;
if (p_splitter == nullptr || *p_splitter == '\0') {
end = from + 1;
} else {
end = find(p_splitter, from);
if (end < 0) {
end = len;
}
}
if (p_allow_empty || (end > from)) {
if (p_maxsplit <= 0) {
ret.push_back(substr(from, end - from));
} else {
// Put rest of the string and leave cycle.
if (p_maxsplit == ret.size()) {
ret.push_back(substr(from, len));
break;
}
// Otherwise, push items until positive limit is reached.
ret.push_back(substr(from, end - from));
}
}
if (end == len) {
break;
}
from = end + strlen(p_splitter);
}
return ret;
}
Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int p_maxsplit) const {
Vector<String> ret;
const int len = length();
@@ -1380,6 +1489,49 @@ Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int
return ret;
}
Vector<String> String::rsplit(const char *p_splitter, bool p_allow_empty, int p_maxsplit) const {
Vector<String> ret;
const int len = length();
const int splitter_length = strlen(p_splitter);
int remaining_len = len;
while (true) {
if (remaining_len < splitter_length || (p_maxsplit > 0 && p_maxsplit == ret.size())) {
// no room for another splitter or hit max splits, push what's left and we're done
if (p_allow_empty || remaining_len > 0) {
ret.push_back(substr(0, remaining_len));
}
break;
}
int left_edge;
if (p_splitter == nullptr || *p_splitter == '\0') {
left_edge = remaining_len - 1;
if (left_edge == 0) {
left_edge--; // Skip to the < 0 condition.
}
} else {
left_edge = rfind(p_splitter, remaining_len - splitter_length);
}
if (left_edge < 0) {
// no more splitters, we're done
ret.push_back(substr(0, remaining_len));
break;
}
int substr_start = left_edge + splitter_length;
if (p_allow_empty || substr_start < remaining_len) {
ret.push_back(substr(substr_start, remaining_len - substr_start));
}
remaining_len = left_edge;
}
ret.reverse();
return ret;
}
Vector<double> String::split_floats(const String &p_splitter, bool p_allow_empty) const {
Vector<double> ret;
int from = 0;
@@ -3087,23 +3239,20 @@ int String::find(const String &p_str, int p_from) const {
}
int String::find(const char *p_str, int p_from) const {
if (p_from < 0) {
if (p_from < 0 || !p_str) {
return -1;
}
const int src_len = strlen(p_str);
const int len = length();
if (len == 0) {
if (len == 0 || src_len == 0) {
return -1; // won't find anything!
}
const char32_t *src = get_data();
int src_len = 0;
while (p_str[src_len] != '\0') {
src_len++;
}
if (src_len == 1) {
const char32_t needle = p_str[0];
@@ -3238,6 +3387,46 @@ int String::findn(const String &p_str, int p_from) const {
return -1;
}
int String::findn(const char *p_str, int p_from) const {
if (p_from < 0) {
return -1;
}
int src_len = strlen(p_str);
if (src_len == 0 || length() == 0) {
return -1; // won't find anything!
}
const char32_t *srcd = get_data();
for (int i = p_from; i <= (length() - src_len); i++) {
bool found = true;
for (int j = 0; j < src_len; j++) {
int read_pos = i + j;
if (read_pos >= length()) {
ERR_PRINT("read_pos>=length()");
return -1;
}
char32_t src = _find_lower(srcd[read_pos]);
char32_t dst = _find_lower(p_str[j]);
if (src != dst) {
found = false;
break;
}
}
if (found) {
return i;
}
}
return -1;
}
int String::rfind(const String &p_str, int p_from) const {
// establish a limit
int limit = length() - p_str.length();
@@ -3285,6 +3474,57 @@ int String::rfind(const String &p_str, int p_from) const {
return -1;
}
int String::rfind(const char *p_str, int p_from) const {
const int source_length = length();
int substring_length = strlen(p_str);
if (source_length == 0 || substring_length == 0) {
return -1; // won't find anything!
}
// establish a limit
int limit = length() - substring_length;
if (limit < 0) {
return -1;
}
// establish a starting point
int starting_point;
if (p_from < 0) {
starting_point = limit;
} else if (p_from > limit) {
starting_point = limit;
} else {
starting_point = p_from;
}
const char32_t *source = get_data();
for (int i = starting_point; i >= 0; i--) {
bool found = true;
for (int j = 0; j < substring_length; j++) {
int read_pos = i + j;
if (read_pos >= source_length) {
ERR_PRINT("read_pos>=source_length");
return -1;
}
const char32_t key_needle = p_str[j];
if (source[read_pos] != key_needle) {
found = false;
break;
}
}
if (found) {
return i;
}
}
return -1;
}
int String::rfindn(const String &p_str, int p_from) const {
// establish a limit
int limit = length() - p_str.length();
@@ -3335,6 +3575,60 @@ int String::rfindn(const String &p_str, int p_from) const {
return -1;
}
int String::rfindn(const char *p_str, int p_from) const {
const int source_length = length();
int substring_length = strlen(p_str);
if (source_length == 0 || substring_length == 0) {
return -1; // won't find anything!
}
// establish a limit
int limit = length() - substring_length;
if (limit < 0) {
return -1;
}
// establish a starting point
int starting_point;
if (p_from < 0) {
starting_point = limit;
} else if (p_from > limit) {
starting_point = limit;
} else {
starting_point = p_from;
}
const char32_t *source = get_data();
for (int i = starting_point; i >= 0; i--) {
bool found = true;
for (int j = 0; j < substring_length; j++) {
int read_pos = i + j;
if (read_pos >= source_length) {
ERR_PRINT("read_pos>=source_length");
return -1;
}
const char32_t key_needle = p_str[j];
int srcc = _find_lower(source[read_pos]);
int keyc = _find_lower(key_needle);
if (srcc != keyc) {
found = false;
break;
}
}
if (found) {
return i;
}
}
return -1;
}
bool String::ends_with(const String &p_string) const {
int l = p_string.length();
if (l > length()) {
@@ -3357,6 +3651,31 @@ bool String::ends_with(const String &p_string) const {
return true;
}
bool String::ends_with(const char *p_string) const {
if (!p_string) {
return false;
}
int l = strlen(p_string);
if (l > length()) {
return false;
}
if (l == 0) {
return true;
}
const char32_t *s = &operator[](length() - l);
for (int i = 0; i < l; i++) {
if (static_cast<char32_t>(p_string[i]) != s[i]) {
return false;
}
}
return true;
}
bool String::begins_with(const String &p_string) const {
int l = p_string.length();
if (l > length()) {
@@ -3380,11 +3699,11 @@ bool String::begins_with(const String &p_string) const {
}
bool String::begins_with(const char *p_string) const {
int l = length();
if (!p_string) {
return false;
}
int l = length();
if (l == 0) {
return *p_string == 0;
}
@@ -3456,14 +3775,61 @@ int String::_count(const String &p_string, int p_from, int p_to, bool p_case_ins
return c;
}
int String::_count(const char *p_string, int p_from, int p_to, bool p_case_insensitive) const {
int substring_length = strlen(p_string);
if (substring_length == 0) {
return 0;
}
const int source_length = length();
if (source_length < substring_length) {
return 0;
}
String str;
int search_limit = p_to;
if (p_from >= 0 && p_to >= 0) {
if (p_to == 0) {
search_limit = source_length;
} else if (p_from >= p_to) {
return 0;
}
if (p_from == 0 && search_limit == source_length) {
str = String();
str.copy_from_unchecked(&get_data()[0], source_length);
} else {
str = substr(p_from, search_limit - p_from);
}
} else {
return 0;
}
int c = 0;
int idx = -1;
do {
idx = p_case_insensitive ? str.findn(p_string) : str.find(p_string);
if (idx != -1) {
str = str.substr(idx + substring_length, str.length() - substring_length);
++c;
}
} while (idx != -1);
return c;
}
int String::count(const String &p_string, int p_from, int p_to) const {
return _count(p_string, p_from, p_to, false);
}
int String::count(const char *p_string, int p_from, int p_to) const {
return _count(p_string, p_from, p_to, false);
}
int String::countn(const String &p_string, int p_from, int p_to) const {
return _count(p_string, p_from, p_to, true);
}
int String::countn(const char *p_string, int p_from, int p_to) const {
return _count(p_string, p_from, p_to, true);
}
bool String::_base_is_subsequence_of(const String &p_string, bool case_insensitive) const {
int len = length();
if (len == 0) {
@@ -3673,6 +4039,16 @@ String String::replace_first(const String &p_key, const String &p_with) const {
return *this;
}
String String::replace_first(const char *p_key, const char *p_with) const {
int pos = find(p_key);
if (pos >= 0) {
int substring_length = strlen(p_key);
return substr(0, pos) + p_with + substr(pos + substring_length, length());
}
return *this;
}
String String::replacen(const String &p_key, const String &p_with) const {
String new_string;
int search_from = 0;
@@ -3692,6 +4068,31 @@ String String::replacen(const String &p_key, const String &p_with) const {
return new_string;
}
String String::replacen(const char *p_key, const char *p_with) const {
String new_string;
int search_from = 0;
int result = 0;
int substring_length = strlen(p_key);
if (substring_length == 0) {
return *this; // there's nothing to match or substitute
}
while ((result = findn(p_key, search_from)) >= 0) {
new_string += substr(search_from, result - search_from);
new_string += p_with;
search_from = result + substring_length;
}
if (search_from == 0) {
return *this;
}
new_string += substr(search_from, length() - search_from);
return new_string;
}
String String::repeat(int p_count) const {
ERR_FAIL_COND_V_MSG(p_count < 0, "", "Parameter count should be a positive number.");
@@ -4420,6 +4821,15 @@ String String::trim_prefix(const String &p_prefix) const {
return s;
}
String String::trim_prefix(const char *p_prefix) const {
String s = *this;
if (s.begins_with(p_prefix)) {
int prefix_length = strlen(p_prefix);
return s.substr(prefix_length, s.length() - prefix_length);
}
return s;
}
String String::trim_suffix(const String &p_suffix) const {
String s = *this;
if (s.ends_with(p_suffix)) {
@@ -4428,6 +4838,14 @@ String String::trim_suffix(const String &p_suffix) const {
return s;
}
String String::trim_suffix(const char *p_suffix) const {
String s = *this;
if (s.ends_with(p_suffix)) {
return s.substr(0, s.length() - strlen(p_suffix));
}
return s;
}
bool String::is_valid_int() const {
int len = length();