summaryrefslogtreecommitdiff
path: root/core/ustring.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/ustring.cpp')
-rw-r--r--core/ustring.cpp272
1 files changed, 184 insertions, 88 deletions
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 3a0708851e..11d83a5733 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -56,34 +56,49 @@
#define IS_DIGIT(m_d) ((m_d) >= '0' && (m_d) <= '9')
#define IS_HEX_DIGIT(m_d) (((m_d) >= '0' && (m_d) <= '9') || ((m_d) >= 'a' && (m_d) <= 'f') || ((m_d) >= 'A' && (m_d) <= 'F'))
-/** STRING **/
+bool is_symbol(CharType c) {
+ return c != '_' && ((c >= '!' && c <= '/') || (c >= ':' && c <= '@') || (c >= '[' && c <= '`') || (c >= '{' && c <= '~') || c == '\t' || c == ' ');
+}
-bool CharString::operator<(const CharString &p_right) const {
+bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end) {
- if (length() == 0) {
- return p_right.length() != 0;
+ const String &s = p_s;
+ int beg = CLAMP(p_col, 0, s.length());
+ int end = beg;
+
+ if (s[beg] > 32 || beg == s.length()) {
+
+ bool symbol = beg < s.length() && is_symbol(s[beg]);
+
+ while (beg > 0 && s[beg - 1] > 32 && (symbol == is_symbol(s[beg - 1]))) {
+ beg--;
+ }
+ while (end < s.length() && s[end + 1] > 32 && (symbol == is_symbol(s[end + 1]))) {
+ end++;
+ }
+
+ if (end < s.length())
+ end += 1;
+
+ r_beg = beg;
+ r_end = end;
+
+ return true;
+ } else {
+
+ return false;
}
+}
- const char *this_str = get_data();
- const char *that_str = p_right.get_data();
- while (true) {
+/** STRING **/
- if (*that_str == 0 && *this_str == 0)
- return false; //this can't be equal, sadly
- else if (*this_str == 0)
- return true; //if this is empty, and the other one is not, then we're less.. I think?
- else if (*that_str == 0)
- return false; //otherwise the other one is smaller..
- else if (*this_str < *that_str) //more than
- return true;
- else if (*this_str > *that_str) //less than
- return false;
+bool CharString::operator<(const CharString &p_right) const {
- this_str++;
- that_str++;
+ if (length() == 0) {
+ return p_right.length() != 0;
}
- return false; //should never reach here anyway
+ return is_str_less(get_data(), p_right.get_data());
}
const char *CharString::get_data() const {
@@ -372,28 +387,10 @@ bool String::operator<(const CharType *p_str) const {
if (empty())
return true;
- const CharType *this_str = c_str();
- while (true) {
-
- if (*p_str == 0 && *this_str == 0)
- return false; //this can't be equal, sadly
- else if (*this_str == 0)
- return true; //if this is empty, and the other one is not, then we're less.. I think?
- else if (*p_str == 0)
- return false; //otherwise the other one is smaller..
- else if (*this_str < *p_str) //more than
- return true;
- else if (*this_str > *p_str) //less than
- return false;
-
- this_str++;
- p_str++;
- }
-
- return false; //should never reach here anyway
+ return is_str_less(c_str(), p_str);
}
-bool String::operator<=(String p_str) const {
+bool String::operator<=(const String &p_str) const {
return (*this < p_str) || (*this == p_str);
}
@@ -405,28 +402,10 @@ bool String::operator<(const char *p_str) const {
if (empty())
return true;
- const CharType *this_str = c_str();
- while (true) {
-
- if (*p_str == 0 && *this_str == 0)
- return false; //this can't be equal, sadly
- else if (*this_str == 0)
- return true; //if this is empty, and the other one is not, then we're less.. I think?
- else if (*p_str == 0)
- return false; //otherwise the other one is smaller..
- else if (*this_str < *p_str) //more than
- return true;
- else if (*this_str > *p_str) //less than
- return false;
-
- this_str++;
- p_str++;
- }
-
- return false; //should never reach here anyway
+ return is_str_less(c_str(), p_str);
}
-bool String::operator<(String p_str) const {
+bool String::operator<(const String &p_str) const {
return operator<(p_str.c_str());
}
@@ -734,7 +713,7 @@ Vector<String> String::split_spaces() const {
return ret;
}
-Vector<String> String::split(const String &p_splitter, bool p_allow_empty) const {
+Vector<String> String::split(const String &p_splitter, bool p_allow_empty, int p_maxsplit) const {
Vector<String> ret;
int from = 0;
@@ -745,8 +724,21 @@ Vector<String> String::split(const String &p_splitter, bool p_allow_empty) const
int end = find(p_splitter, from);
if (end < 0)
end = len;
- if (p_allow_empty || (end > from))
- ret.push_back(substr(from, end - from));
+ if (p_allow_empty || (end > from)) {
+ if (p_maxsplit <= 0)
+ ret.push_back(substr(from, end - from));
+ else if (p_maxsplit > 0) {
+
+ // 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;
@@ -889,7 +881,10 @@ String String::to_upper() const {
for (int i = 0; i < upper.size(); i++) {
- upper[i] = _find_upper(upper[i]);
+ const char s = upper[i];
+ const char t = _find_upper(s);
+ if (s != t) // avoid copy on write
+ upper[i] = t;
}
return upper;
@@ -897,20 +892,17 @@ String String::to_upper() const {
String String::to_lower() const {
- String upper = *this;
+ String lower = *this;
- for (int i = 0; i < upper.size(); i++) {
+ for (int i = 0; i < lower.size(); i++) {
- upper[i] = _find_lower(upper[i]);
+ const char s = lower[i];
+ const char t = _find_lower(s);
+ if (s != t) // avoid copy on write
+ lower[i] = t;
}
- return upper;
-}
-
-int String::length() const {
-
- int s = size();
- return s ? (s - 1) : 0; // length does not include zero
+ return lower;
}
const CharType *String::c_str() const {
@@ -2162,7 +2154,7 @@ Vector<uint8_t> String::sha256_buffer() const {
return ret;
}
-String String::insert(int p_at_pos, String p_string) const {
+String String::insert(int p_at_pos, const String &p_string) const {
if (p_at_pos < 0)
return *this;
@@ -2190,10 +2182,15 @@ String String::substr(int p_from, int p_chars) const {
p_chars = length() - p_from;
}
+ if (p_from == 0 && p_chars >= length()) {
+
+ return String(*this);
+ }
+
return String(&c_str()[p_from], p_chars);
}
-int String::find_last(String p_str) const {
+int String::find_last(const String &p_str) const {
int pos = -1;
int findfrom = 0;
@@ -2206,19 +2203,21 @@ int String::find_last(String p_str) const {
return pos;
}
-int String::find(String p_str, int p_from) const {
+
+int String::find(const String &p_str, int p_from) const {
if (p_from < 0)
return -1;
- int src_len = p_str.length();
+ const int src_len = p_str.length();
- int len = length();
+ const int len = length();
if (src_len == 0 || len == 0)
return -1; //wont find anything!
const CharType *src = c_str();
+ const CharType *str = p_str.c_str();
for (int i = p_from; i <= (len - src_len); i++) {
@@ -2233,7 +2232,7 @@ int String::find(String p_str, int p_from) const {
return -1;
};
- if (src[read_pos] != p_str[j]) {
+ if (src[read_pos] != str[j]) {
found = false;
break;
}
@@ -2246,6 +2245,62 @@ int String::find(String p_str, int p_from) const {
return -1;
}
+int String::find(const char *p_str, int p_from) const {
+
+ if (p_from < 0)
+ return -1;
+
+ const int len = length();
+
+ if (len == 0)
+ return -1; //wont find anything!
+
+ const CharType *src = c_str();
+
+ int src_len = 0;
+ while (p_str[src_len] != '\0')
+ src_len++;
+
+ if (src_len == 1) {
+
+ const char needle = p_str[0];
+
+ for (int i = p_from; i < len; i++) {
+
+ if (src[i] == needle) {
+ return i;
+ }
+ }
+
+ } else {
+
+ for (int i = p_from; i <= (len - src_len); i++) {
+
+ bool found = true;
+ for (int j = 0; j < src_len; j++) {
+
+ int read_pos = i + j;
+
+ if (read_pos >= len) {
+
+ ERR_PRINT("read_pos>=len");
+ return -1;
+ };
+
+ if (src[read_pos] != p_str[j]) {
+ found = false;
+ break;
+ }
+ }
+
+ if (found)
+ return i;
+ }
+ }
+
+ return -1;
+}
+
int String::findmk(const Vector<String> &p_keys, int p_from, int *r_key) const {
if (p_from < 0)
@@ -2300,7 +2355,7 @@ int String::findmk(const Vector<String> &p_keys, int p_from, int *r_key) const {
return -1;
}
-int String::findn(String p_str, int p_from) const {
+int String::findn(const String &p_str, int p_from) const {
if (p_from < 0)
return -1;
@@ -2341,7 +2396,7 @@ int String::findn(String p_str, int p_from) const {
return -1;
}
-int String::rfind(String p_str, int p_from) const {
+int String::rfind(const String &p_str, int p_from) const {
// establish a limit
int limit = length() - p_str.length();
@@ -2387,7 +2442,7 @@ int String::rfind(String p_str, int p_from) const {
return -1;
}
-int String::rfindn(String p_str, int p_from) const {
+int String::rfindn(const String &p_str, int p_from) const {
// establish a limit
int limit = length() - p_str.length();
@@ -2687,7 +2742,7 @@ String String::format(const Variant &values, String placeholder) const {
return new_string;
}
-String String::replace(String p_key, String p_with) const {
+String String::replace(const String &p_key, const String &p_with) const {
String new_string;
int search_from = 0;
@@ -2700,12 +2755,43 @@ String String::replace(String p_key, String p_with) const {
search_from = result + p_key.length();
}
+ if (search_from == 0) {
+
+ return *this;
+ }
+
+ new_string += substr(search_from, length() - search_from);
+
+ return new_string;
+}
+
+String String::replace(const char *p_key, const char *p_with) const {
+
+ String new_string;
+ int search_from = 0;
+ int result = 0;
+
+ while ((result = find(p_key, search_from)) >= 0) {
+
+ new_string += substr(search_from, result - search_from);
+ new_string += p_with;
+ int k = 0;
+ while (p_key[k] != '\0')
+ k++;
+ search_from = result + k;
+ }
+
+ if (search_from == 0) {
+
+ return *this;
+ }
+
new_string += substr(search_from, length() - search_from);
return new_string;
}
-String String::replace_first(String p_key, String p_with) const {
+String String::replace_first(const String &p_key, const String &p_with) const {
String new_string;
int search_from = 0;
@@ -2719,11 +2805,16 @@ String String::replace_first(String p_key, String p_with) const {
break;
}
+ if (search_from == 0) {
+
+ return *this;
+ }
+
new_string += substr(search_from, length() - search_from);
return new_string;
}
-String String::replacen(String p_key, String p_with) const {
+String String::replacen(const String &p_key, const String &p_with) const {
String new_string;
int search_from = 0;
@@ -2736,6 +2827,11 @@ String String::replacen(String p_key, String p_with) const {
search_from = result + p_key.length();
}
+ if (search_from == 0) {
+
+ return *this;
+ }
+
new_string += substr(search_from, length() - search_from);
return new_string;
}