mirror of
https://github.com/godotengine/godot.git
synced 2024-12-15 10:12:40 +08:00
Merge pull request #25090 from Chaosus/string_count
Added String.count method
This commit is contained in:
commit
aa062c54fc
@ -2729,6 +2729,51 @@ bool String::is_quoted() const {
|
|||||||
return is_enclosed_in("\"") || is_enclosed_in("'");
|
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 {
|
bool String::_base_is_subsequence_of(const String &p_string, bool case_insensitive) const {
|
||||||
|
|
||||||
int len = length();
|
int len = length();
|
||||||
|
@ -137,6 +137,7 @@ class String {
|
|||||||
void copy_from(const CharType &p_char);
|
void copy_from(const CharType &p_char);
|
||||||
void copy_from_unchecked(const CharType *p_char, const int p_length);
|
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;
|
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:
|
public:
|
||||||
enum {
|
enum {
|
||||||
@ -279,6 +280,9 @@ public:
|
|||||||
String to_upper() const;
|
String to_upper() const;
|
||||||
String to_lower() 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 left(int p_pos) const;
|
||||||
String right(int p_pos) const;
|
String right(int p_pos) const;
|
||||||
String dedent() const;
|
String dedent() const;
|
||||||
|
@ -237,6 +237,8 @@ struct _VariantCall {
|
|||||||
VCALL_LOCALMEM1R(String, casecmp_to);
|
VCALL_LOCALMEM1R(String, casecmp_to);
|
||||||
VCALL_LOCALMEM1R(String, nocasecmp_to);
|
VCALL_LOCALMEM1R(String, nocasecmp_to);
|
||||||
VCALL_LOCALMEM0R(String, length);
|
VCALL_LOCALMEM0R(String, length);
|
||||||
|
VCALL_LOCALMEM3R(String, count);
|
||||||
|
VCALL_LOCALMEM3R(String, countn);
|
||||||
VCALL_LOCALMEM2R(String, substr);
|
VCALL_LOCALMEM2R(String, substr);
|
||||||
VCALL_LOCALMEM2R(String, find);
|
VCALL_LOCALMEM2R(String, find);
|
||||||
VCALL_LOCALMEM1R(String, find_last);
|
VCALL_LOCALMEM1R(String, find_last);
|
||||||
@ -1502,6 +1504,9 @@ void register_variant_methods() {
|
|||||||
|
|
||||||
ADDFUNC2R(STRING, INT, String, find, STRING, "what", INT, "from", varray(0));
|
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());
|
ADDFUNC1R(STRING, INT, String, find_last, STRING, "what", varray());
|
||||||
ADDFUNC2R(STRING, INT, String, findn, STRING, "what", INT, "from", varray(0));
|
ADDFUNC2R(STRING, INT, String, findn, STRING, "what", INT, "from", varray(0));
|
||||||
ADDFUNC2R(STRING, INT, String, rfind, STRING, "what", INT, "from", varray(-1));
|
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.
|
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>
|
</description>
|
||||||
</method>
|
</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">
|
<method name="dedent">
|
||||||
<return type="String">
|
<return type="String">
|
||||||
</return>
|
</return>
|
||||||
|
@ -1078,6 +1078,44 @@ bool test_34() {
|
|||||||
return state;
|
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);
|
typedef bool (*TestFunc)(void);
|
||||||
|
|
||||||
TestFunc test_funcs[] = {
|
TestFunc test_funcs[] = {
|
||||||
@ -1116,6 +1154,7 @@ TestFunc test_funcs[] = {
|
|||||||
test_32,
|
test_32,
|
||||||
test_33,
|
test_33,
|
||||||
test_34,
|
test_34,
|
||||||
|
test_35,
|
||||||
0
|
0
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -186,6 +186,20 @@ godot_bool GDAPI godot_string_ends_with(const godot_string *p_self, const godot_
|
|||||||
return self->ends_with(*string);
|
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) {
|
godot_int GDAPI godot_string_find(const godot_string *p_self, godot_string p_what) {
|
||||||
const String *self = (const String *)p_self;
|
const String *self = (const String *)p_self;
|
||||||
String *what = (String *)&p_what;
|
String *what = (String *)&p_what;
|
||||||
|
@ -44,6 +44,26 @@
|
|||||||
["const godot_vector2 *", "p_to"],
|
["const godot_vector2 *", "p_to"],
|
||||||
["const godot_real", "p_delta"]
|
["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_array GDAPI godot_string_bigrams(const godot_string *p_self);
|
||||||
godot_string GDAPI godot_string_chr(wchar_t p_character);
|
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_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(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_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);
|
godot_int GDAPI godot_string_findmk(const godot_string *p_self, const godot_array *p_keys);
|
||||||
|
@ -97,6 +97,66 @@ namespace Godot
|
|||||||
return b;
|
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>
|
// <summary>
|
||||||
// Return a copy of the string with special characters escaped using the C language standard.
|
// Return a copy of the string with special characters escaped using the C language standard.
|
||||||
// </summary>
|
// </summary>
|
||||||
|
Loading…
Reference in New Issue
Block a user