Added count method to String
This commit is contained in:
parent
c7a427241e
commit
080c0bb7fe
9 changed files with 217 additions and 0 deletions
|
@ -2729,6 +2729,51 @@ bool String::is_quoted() const {
|
|||
return is_enclosed_in("\"") || is_enclosed_in("'");
|
||||
}
|
||||
|
||||
int String::_count(const String &p_string, int p_from, int p_to, bool p_case_insensitive) const {
|
||||
if (p_string.empty()) {
|
||||
return 0;
|
||||
}
|
||||
int len = length();
|
||||
int slen = p_string.length();
|
||||
if (len < slen) {
|
||||
return 0;
|
||||
}
|
||||
String str;
|
||||
if (p_from >= 0 && p_to >= 0) {
|
||||
if (p_to == 0) {
|
||||
p_to = len;
|
||||
} else if (p_from >= p_to) {
|
||||
return 0;
|
||||
}
|
||||
if (p_from == 0 && p_to == len) {
|
||||
str = String();
|
||||
str.copy_from_unchecked(&c_str()[0], len);
|
||||
} else {
|
||||
str = substr(p_from, p_to - 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 + slen, str.length() - slen);
|
||||
++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::countn(const String &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();
|
||||
|
|
|
@ -137,6 +137,7 @@ class String {
|
|||
void copy_from(const CharType &p_char);
|
||||
void copy_from_unchecked(const CharType *p_char, const int p_length);
|
||||
bool _base_is_subsequence_of(const String &p_string, bool case_insensitive) const;
|
||||
int _count(const String &p_string, int p_from, int p_to, bool p_case_insensitive) const;
|
||||
|
||||
public:
|
||||
enum {
|
||||
|
@ -279,6 +280,9 @@ public:
|
|||
String to_upper() const;
|
||||
String to_lower() const;
|
||||
|
||||
int count(const String &p_string, int p_from = 0, int p_to = 0) const;
|
||||
int countn(const String &p_string, int p_from = 0, int p_to = 0) const;
|
||||
|
||||
String left(int p_pos) const;
|
||||
String right(int p_pos) const;
|
||||
String dedent() const;
|
||||
|
|
|
@ -237,6 +237,8 @@ struct _VariantCall {
|
|||
VCALL_LOCALMEM1R(String, casecmp_to);
|
||||
VCALL_LOCALMEM1R(String, nocasecmp_to);
|
||||
VCALL_LOCALMEM0R(String, length);
|
||||
VCALL_LOCALMEM3R(String, count);
|
||||
VCALL_LOCALMEM3R(String, countn);
|
||||
VCALL_LOCALMEM2R(String, substr);
|
||||
VCALL_LOCALMEM2R(String, find);
|
||||
VCALL_LOCALMEM1R(String, find_last);
|
||||
|
@ -1502,6 +1504,9 @@ void register_variant_methods() {
|
|||
|
||||
ADDFUNC2R(STRING, INT, String, find, STRING, "what", INT, "from", varray(0));
|
||||
|
||||
ADDFUNC3R(STRING, INT, String, count, STRING, "what", INT, "from", INT, "to", varray(0, 0));
|
||||
ADDFUNC3R(STRING, INT, String, countn, STRING, "what", INT, "from", INT, "to", varray(0, 0));
|
||||
|
||||
ADDFUNC1R(STRING, INT, String, find_last, STRING, "what", varray());
|
||||
ADDFUNC2R(STRING, INT, String, findn, STRING, "what", INT, "from", varray(0));
|
||||
ADDFUNC2R(STRING, INT, String, rfind, STRING, "what", INT, "from", varray(-1));
|
||||
|
|
|
@ -272,6 +272,34 @@
|
|||
Performs a case-sensitive comparison to another string. Returns [code]-1[/code] if less than, [code]+1[/code] if greater than, or [code]0[/code] if equal.
|
||||
</description>
|
||||
</method>
|
||||
<method name="count">
|
||||
<return type="int">
|
||||
</return>
|
||||
<argument index="0" name="what" type="String">
|
||||
</argument>
|
||||
<argument index="1" name="from" type="int" default="0">
|
||||
</argument>
|
||||
<argument index="2" name="to" type="int" default="0">
|
||||
</argument>
|
||||
</argument>
|
||||
<description>
|
||||
Returns the number of occurrences of substring [code]what[/code] between [code]from[/code] and [code]to[/code] positions. If [code]from[/code] and [code]to[/code] equals 0 the whole string will be used. If only [code]to[/code] equals 0 the remained substring will be used.
|
||||
</description>
|
||||
</method>
|
||||
<method name="countn">
|
||||
<return type="int">
|
||||
</return>
|
||||
<argument index="0" name="what" type="String">
|
||||
</argument>
|
||||
<argument index="1" name="from" type="int" default="0">
|
||||
</argument>
|
||||
<argument index="2" name="to" type="int" default="0">
|
||||
</argument>
|
||||
</argument>
|
||||
<description>
|
||||
Returns the number of occurrences of substring [code]what[/code] (ignoring case) between [code]from[/code] and [code]to[/code] positions. If [code]from[/code] and [code]to[/code] equals 0 the whole string will be used. If only [code]to[/code] equals 0 the remained substring will be used.
|
||||
</description>
|
||||
</method>
|
||||
<method name="dedent">
|
||||
<return type="String">
|
||||
</return>
|
||||
|
|
|
@ -1078,6 +1078,44 @@ bool test_34() {
|
|||
return state;
|
||||
}
|
||||
|
||||
bool test_35() {
|
||||
#define COUNT_TEST(x) \
|
||||
{ \
|
||||
bool success = x; \
|
||||
state = state && success; \
|
||||
if (!success) { \
|
||||
OS::get_singleton()->print("\tfailed at: %s\n", #x); \
|
||||
} \
|
||||
}
|
||||
|
||||
OS::get_singleton()->print("\n\nTest 35: count and countn function\n");
|
||||
bool state = true;
|
||||
|
||||
COUNT_TEST(String("").count("Test") == 0);
|
||||
COUNT_TEST(String("Test").count("") == 0);
|
||||
COUNT_TEST(String("Test").count("test") == 0);
|
||||
COUNT_TEST(String("Test").count("TEST") == 0);
|
||||
COUNT_TEST(String("TEST").count("TEST") == 1);
|
||||
COUNT_TEST(String("Test").count("Test") == 1);
|
||||
COUNT_TEST(String("aTest").count("Test") == 1);
|
||||
COUNT_TEST(String("Testa").count("Test") == 1);
|
||||
COUNT_TEST(String("TestTestTest").count("Test") == 3);
|
||||
COUNT_TEST(String("TestTestTest").count("TestTest") == 1);
|
||||
COUNT_TEST(String("TestGodotTestGodotTestGodot").count("Test") == 3);
|
||||
|
||||
COUNT_TEST(String("TestTestTestTest").count("Test", 4, 8) == 1);
|
||||
COUNT_TEST(String("TestTestTestTest").count("Test", 4, 12) == 2);
|
||||
COUNT_TEST(String("TestTestTestTest").count("Test", 4, 16) == 3);
|
||||
COUNT_TEST(String("TestTestTestTest").count("Test", 4) == 3);
|
||||
|
||||
COUNT_TEST(String("Test").countn("test") == 1);
|
||||
COUNT_TEST(String("Test").countn("TEST") == 1);
|
||||
COUNT_TEST(String("testTest-Testatest").countn("tEst") == 4);
|
||||
COUNT_TEST(String("testTest-TeStatest").countn("tEsT", 4, 16) == 2);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
typedef bool (*TestFunc)(void);
|
||||
|
||||
TestFunc test_funcs[] = {
|
||||
|
@ -1116,6 +1154,7 @@ TestFunc test_funcs[] = {
|
|||
test_32,
|
||||
test_33,
|
||||
test_34,
|
||||
test_35,
|
||||
0
|
||||
|
||||
};
|
||||
|
|
|
@ -186,6 +186,20 @@ godot_bool GDAPI godot_string_ends_with(const godot_string *p_self, const godot_
|
|||
return self->ends_with(*string);
|
||||
}
|
||||
|
||||
godot_int GDAPI godot_string_count(const godot_string *p_self, godot_string p_what, godot_int p_from, godot_int p_to) {
|
||||
const String *self = (const String *)p_self;
|
||||
String *what = (String *)&p_what;
|
||||
|
||||
return self->count(*what, p_from, p_to);
|
||||
}
|
||||
|
||||
godot_int GDAPI godot_string_countn(const godot_string *p_self, godot_string p_what, godot_int p_from, godot_int p_to) {
|
||||
const String *self = (const String *)p_self;
|
||||
String *what = (String *)&p_what;
|
||||
|
||||
return self->countn(*what, p_from, p_to);
|
||||
}
|
||||
|
||||
godot_int GDAPI godot_string_find(const godot_string *p_self, godot_string p_what) {
|
||||
const String *self = (const String *)p_self;
|
||||
String *what = (String *)&p_what;
|
||||
|
|
|
@ -44,6 +44,26 @@
|
|||
["const godot_vector2 *", "p_to"],
|
||||
["const godot_real", "p_delta"]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "godot_string_count",
|
||||
"return_type": "godot_int",
|
||||
"arguments": [
|
||||
["const godot_string *", "p_self"],
|
||||
["godot_string", "p_what"],
|
||||
["godot_int", "p_from"],
|
||||
["godot_int", "p_to"]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "godot_string_countn",
|
||||
"return_type": "godot_int",
|
||||
"arguments": [
|
||||
["const godot_string *", "p_self"],
|
||||
["godot_string", "p_what"],
|
||||
["godot_int", "p_from"],
|
||||
["godot_int", "p_to"]
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -102,6 +102,8 @@ godot_bool GDAPI godot_string_begins_with_char_array(const godot_string *p_self,
|
|||
godot_array GDAPI godot_string_bigrams(const godot_string *p_self);
|
||||
godot_string GDAPI godot_string_chr(wchar_t p_character);
|
||||
godot_bool GDAPI godot_string_ends_with(const godot_string *p_self, const godot_string *p_string);
|
||||
godot_int GDAPI godot_string_count(const godot_string *p_self, godot_string p_what, godot_int p_from, godot_int p_to);
|
||||
godot_int GDAPI godot_string_countn(const godot_string *p_self, godot_string p_what, godot_int p_from, godot_int p_to);
|
||||
godot_int GDAPI godot_string_find(const godot_string *p_self, godot_string p_what);
|
||||
godot_int GDAPI godot_string_find_from(const godot_string *p_self, godot_string p_what, godot_int p_from);
|
||||
godot_int GDAPI godot_string_findmk(const godot_string *p_self, const godot_array *p_keys);
|
||||
|
|
|
@ -97,6 +97,66 @@ namespace Godot
|
|||
return b;
|
||||
}
|
||||
|
||||
// <summary>
|
||||
// Return the amount of substrings in string.
|
||||
// </summary>
|
||||
public static int Count(this string instance, string what, bool caseSensitive = true, int from = 0, int to = 0)
|
||||
{
|
||||
if (what.Length == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int len = instance.Length;
|
||||
int slen = what.Length;
|
||||
|
||||
if (len < slen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
string str;
|
||||
|
||||
if (from >= 0 && to >= 0)
|
||||
{
|
||||
if (to == 0)
|
||||
{
|
||||
to = len;
|
||||
}
|
||||
else if (from >= to)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (from == 0 && to == len)
|
||||
{
|
||||
str = instance;
|
||||
}
|
||||
else
|
||||
{
|
||||
str = instance.Substring(from, to - from);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int c = 0;
|
||||
int idx;
|
||||
|
||||
do
|
||||
{
|
||||
idx = str.IndexOf(what, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
|
||||
if (idx != -1)
|
||||
{
|
||||
str = str.Substring(idx + slen);
|
||||
++c;
|
||||
}
|
||||
} while (idx != -1);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
// <summary>
|
||||
// Return a copy of the string with special characters escaped using the C language standard.
|
||||
// </summary>
|
||||
|
|
Loading…
Reference in a new issue