Merge pull request #64321 from KoBeWi/s_p_l_i_t

Add support for empty delimiter in `String.split()`
This commit is contained in:
Rémi Verschelde 2022-11-06 15:54:56 +01:00
commit 1836b4b798
No known key found for this signature in database
GPG key ID: C3336907360768E1
5 changed files with 33 additions and 12 deletions

View file

@ -1180,9 +1180,14 @@ Vector<String> String::split(const String &p_splitter, bool p_allow_empty, int p
int len = length(); int len = length();
while (true) { while (true) {
int end = find(p_splitter, from); int end;
if (end < 0) { if (p_splitter.is_empty()) {
end = len; end = from + 1;
} else {
end = find(p_splitter, from);
if (end < 0) {
end = len;
}
} }
if (p_allow_empty || (end > from)) { if (p_allow_empty || (end > from)) {
if (p_maxsplit <= 0) { if (p_maxsplit <= 0) {
@ -1223,7 +1228,15 @@ Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int
break; break;
} }
int left_edge = rfind(p_splitter, remaining_len - p_splitter.length()); int left_edge;
if (p_splitter.is_empty()) {
left_edge = remaining_len - 1;
if (left_edge == 0) {
left_edge--; // Skip to the < 0 condition.
}
} else {
left_edge = rfind(p_splitter, remaining_len - p_splitter.length());
}
if (left_edge < 0) { if (left_edge < 0) {
// no more splitters, we're done // no more splitters, we're done

View file

@ -345,8 +345,8 @@ public:
String get_slice(String p_splitter, int p_slice) const; String get_slice(String p_splitter, int p_slice) const;
String get_slicec(char32_t p_splitter, int p_slice) const; String get_slicec(char32_t p_splitter, int p_slice) const;
Vector<String> split(const String &p_splitter, bool p_allow_empty = true, int p_maxsplit = 0) const; Vector<String> split(const String &p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const;
Vector<String> rsplit(const String &p_splitter, bool p_allow_empty = true, int p_maxsplit = 0) const; Vector<String> rsplit(const String &p_splitter = "", bool p_allow_empty = true, int p_maxsplit = 0) const;
Vector<String> split_spaces() const; Vector<String> split_spaces() const;
Vector<float> split_floats(const String &p_splitter, bool p_allow_empty = true) const; Vector<float> split_floats(const String &p_splitter, bool p_allow_empty = true) const;
Vector<float> split_floats_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const; Vector<float> split_floats_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const;

View file

@ -1509,8 +1509,8 @@ static void _register_variant_builtin_methods() {
bind_method(String, to_camel_case, sarray(), varray()); bind_method(String, to_camel_case, sarray(), varray());
bind_method(String, to_pascal_case, sarray(), varray()); bind_method(String, to_pascal_case, sarray(), varray());
bind_method(String, to_snake_case, sarray(), varray()); bind_method(String, to_snake_case, sarray(), varray());
bind_method(String, split, sarray("delimiter", "allow_empty", "maxsplit"), varray(true, 0)); bind_method(String, split, sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0));
bind_method(String, rsplit, sarray("delimiter", "allow_empty", "maxsplit"), varray(true, 0)); bind_method(String, rsplit, sarray("delimiter", "allow_empty", "maxsplit"), varray("", true, 0));
bind_method(String, split_floats, sarray("delimiter", "allow_empty"), varray(true)); bind_method(String, split_floats, sarray("delimiter", "allow_empty"), varray(true));
bind_method(String, join, sarray("parts"), varray()); bind_method(String, join, sarray("parts"), varray());

View file

@ -634,11 +634,11 @@
</method> </method>
<method name="rsplit" qualifiers="const"> <method name="rsplit" qualifiers="const">
<return type="PackedStringArray" /> <return type="PackedStringArray" />
<param index="0" name="delimiter" type="String" /> <param index="0" name="delimiter" type="String" default="&quot;&quot;" />
<param index="1" name="allow_empty" type="bool" default="true" /> <param index="1" name="allow_empty" type="bool" default="true" />
<param index="2" name="maxsplit" type="int" default="0" /> <param index="2" name="maxsplit" type="int" default="0" />
<description> <description>
Splits the string by a [param delimiter] string and returns an array of the substrings, starting from right. Splits the string by a [param delimiter] string and returns an array of the substrings, starting from right. If [param delimiter] is an empty string, each substring will be a single character.
The splits in the returned array are sorted in the same order as the original string, from left to right. The splits in the returned array are sorted in the same order as the original string, from left to right.
If [param allow_empty] is [code]true[/code], and there are two adjacent delimiters in the string, it will add an empty string to the array of substrings at this position. If [param allow_empty] is [code]true[/code], and there are two adjacent delimiters in the string, it will add an empty string to the array of substrings at this position.
If [param maxsplit] is specified, it defines the number of splits to do from the right up to [param maxsplit]. The default value of 0 means that all items are split, thus giving the same result as [method split]. If [param maxsplit] is specified, it defines the number of splits to do from the right up to [param maxsplit]. The default value of 0 means that all items are split, thus giving the same result as [method split].
@ -710,11 +710,11 @@
</method> </method>
<method name="split" qualifiers="const"> <method name="split" qualifiers="const">
<return type="PackedStringArray" /> <return type="PackedStringArray" />
<param index="0" name="delimiter" type="String" /> <param index="0" name="delimiter" type="String" default="&quot;&quot;" />
<param index="1" name="allow_empty" type="bool" default="true" /> <param index="1" name="allow_empty" type="bool" default="true" />
<param index="2" name="maxsplit" type="int" default="0" /> <param index="2" name="maxsplit" type="int" default="0" />
<description> <description>
Splits the string by a [param delimiter] string and returns an array of the substrings. The [param delimiter] can be of any length. Splits the string by a [param delimiter] string and returns an array of the substrings. The [param delimiter] can be of any length. If [param delimiter] is an empty string, each substring will be a single character.
If [param allow_empty] is [code]true[/code], and there are two adjacent delimiters in the string, it will add an empty string to the array of substrings at this position. If [param allow_empty] is [code]true[/code], and there are two adjacent delimiters in the string, it will add an empty string to the array of substrings at this position.
If [param maxsplit] is specified, it defines the number of splits to do from the left up to [param maxsplit]. The default value of [code]0[/code] means that all items are split. If [param maxsplit] is specified, it defines the number of splits to do from the left up to [param maxsplit]. The default value of [code]0[/code] means that all items are split.
If you need only one element from the array at a specific index, [method get_slice] is a more performant option. If you need only one element from the array at a specific index, [method get_slice] is a more performant option.

View file

@ -485,6 +485,7 @@ TEST_CASE("[String] Splitting") {
const char *slices_l[3] = { "Mars", "Jupiter", "Saturn,Uranus" }; const char *slices_l[3] = { "Mars", "Jupiter", "Saturn,Uranus" };
const char *slices_r[3] = { "Mars,Jupiter", "Saturn", "Uranus" }; const char *slices_r[3] = { "Mars,Jupiter", "Saturn", "Uranus" };
const char *slices_3[4] = { "t", "e", "s", "t" };
l = s.split(",", true, 2); l = s.split(",", true, 2);
CHECK(l.size() == 3); CHECK(l.size() == 3);
@ -498,6 +499,13 @@ TEST_CASE("[String] Splitting") {
CHECK(l[i] == slices_r[i]); CHECK(l[i] == slices_r[i]);
} }
s = "test";
l = s.split();
CHECK(l.size() == 4);
for (int i = 0; i < l.size(); i++) {
CHECK(l[i] == slices_3[i]);
}
s = "Mars Jupiter Saturn Uranus"; s = "Mars Jupiter Saturn Uranus";
const char *slices_s[4] = { "Mars", "Jupiter", "Saturn", "Uranus" }; const char *slices_s[4] = { "Mars", "Jupiter", "Saturn", "Uranus" };
l = s.split_spaces(); l = s.split_spaces();