summaryrefslogtreecommitdiff
path: root/modules/regex
diff options
context:
space:
mode:
Diffstat (limited to 'modules/regex')
-rw-r--r--modules/regex/doc_classes/RegEx.xml6
-rw-r--r--modules/regex/doc_classes/RegExMatch.xml34
-rw-r--r--modules/regex/regex.cpp31
3 files changed, 35 insertions, 36 deletions
diff --git a/modules/regex/doc_classes/RegEx.xml b/modules/regex/doc_classes/RegEx.xml
index 8cd163b0c8..75e8903ff8 100644
--- a/modules/regex/doc_classes/RegEx.xml
+++ b/modules/regex/doc_classes/RegEx.xml
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RegEx" inherits="Reference" category="Core" version="3.0-beta">
+<class name="RegEx" inherits="Reference" category="Core" version="3.1">
<brief_description>
Class for searching text for patterns using regular expressions.
</brief_description>
<description>
- Regular Expression (or regex) is a compact programming language that can be used to recognise strings that follow a specific pattern, such as URLs, email addresses, complete sentences, etc. For instance, a regex of [code]ab[0-9][/code] would find any string that is [code]ab[/code] followed by any number from [code]0[/code] to [code]9[/code]. For a more in-depth look, you can easily find various tutorials and detailed explainations on the Internet.
+ Regular Expression (or regex) is a compact programming language that can be used to recognise strings that follow a specific pattern, such as URLs, email addresses, complete sentences, etc. For instance, a regex of [code]ab[0-9][/code] would find any string that is [code]ab[/code] followed by any number from [code]0[/code] to [code]9[/code]. For a more in-depth look, you can easily find various tutorials and detailed explanations on the Internet.
To begin, the RegEx object needs to be compiled with the search pattern using [method compile] before it can be used.
[codeblock]
var regex = RegEx.new()
regex.compile("\\w-(\\d+)")
[/codeblock]
The search pattern must be escaped first for gdscript before it is escaped for the expression. For example, [code]compile("\\d+")[/code] would be read by RegEx as [code]\d+[/code]. Similarly, [code]compile("\"(?:\\\\.|[^\"])*\"")[/code] would be read as [code]"(?:\\.|[^"])*"[/code]
- Using [method search] you can find the pattern within the given text. If a pattern is found, [RegExMatch] is returned and you can retrieve details of the results using fuctions such as [method RegExMatch.get_string] and [method RegExMatch.get_start].
+ Using [method search] you can find the pattern within the given text. If a pattern is found, [RegExMatch] is returned and you can retrieve details of the results using functions such as [method RegExMatch.get_string] and [method RegExMatch.get_start].
[codeblock]
var regex = RegEx.new()
regex.compile("\\w-(\\d+)")
diff --git a/modules/regex/doc_classes/RegExMatch.xml b/modules/regex/doc_classes/RegExMatch.xml
index 0217099ce6..3d070d2786 100644
--- a/modules/regex/doc_classes/RegExMatch.xml
+++ b/modules/regex/doc_classes/RegExMatch.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RegExMatch" inherits="Reference" category="Core" version="3.0-beta">
+<class name="RegExMatch" inherits="Reference" category="Core" version="3.1">
<brief_description>
Contains the results of a regex search.
</brief_description>
@@ -28,13 +28,6 @@
Returns the number of capturing groups.
</description>
</method>
- <method name="get_names" qualifiers="const">
- <return type="Dictionary">
- </return>
- <description>
- Returns a dictionary of named groups and its corresponding group number. Only groups with that were matched are included. If multiple groups have the same name, that name would refer to the first matching one.
- </description>
- </method>
<method name="get_start" qualifiers="const">
<return type="int">
</return>
@@ -55,21 +48,18 @@
Returns an empty string if the group did not match or doesn't exist.
</description>
</method>
- <method name="get_strings" qualifiers="const">
- <return type="Array">
- </return>
- <description>
- Returns an [Array] of the match and its capturing groups.
- </description>
- </method>
- <method name="get_subject" qualifiers="const">
- <return type="String">
- </return>
- <description>
- Returns the source string used with the search pattern to find this matching result.
- </description>
- </method>
</methods>
+ <members>
+ <member name="names" type="Dictionary" setter="" getter="get_names">
+ A dictionary of named groups and its corresponding group number. Only groups with that were matched are included. If multiple groups have the same name, that name would refer to the first matching one.
+ </member>
+ <member name="strings" type="Array" setter="" getter="get_strings">
+ An [Array] of the match and its capturing groups.
+ </member>
+ <member name="subject" type="String" setter="" getter="get_subject">
+ The source string used with the search pattern to find this matching result.
+ </member>
+ </members>
<constants>
</constants>
</class>
diff --git a/modules/regex/regex.cpp b/modules/regex/regex.cpp
index 9bcbc4c4ea..6f2bb46fc8 100644
--- a/modules/regex/regex.cpp
+++ b/modules/regex/regex.cpp
@@ -156,6 +156,10 @@ void RegExMatch::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_string", "name"), &RegExMatch::get_string, DEFVAL(0));
ClassDB::bind_method(D_METHOD("get_start", "name"), &RegExMatch::get_start, DEFVAL(0));
ClassDB::bind_method(D_METHOD("get_end", "name"), &RegExMatch::get_end, DEFVAL(0));
+
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "subject"), "", "get_subject");
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "names"), "", "get_names");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "strings"), "", "get_strings");
}
void RegEx::_pattern_info(uint32_t what, void *where) const {
@@ -343,15 +347,20 @@ String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_a
ERR_FAIL_COND_V(!is_valid(), String());
- String output;
- output.resize(p_subject.length());
+ // safety_zone is the number of chars we allocate in addition to the number of chars expected in order to
+ // guard against the PCRE API writing one additional \0 at the end. PCRE's API docs are unclear on whether
+ // PCRE understands outlength in pcre2_substitute() as counting an implicit additional terminating char or
+ // not. always allocating one char more than telling PCRE has us on the safe side.
+ const int safety_zone = 1;
+
+ PCRE2_SIZE olength = p_subject.length() + 1; // space for output string and one terminating \0 character
+ Vector<CharType> output;
+ output.resize(olength + safety_zone);
uint32_t flags = PCRE2_SUBSTITUTE_OVERFLOW_LENGTH;
if (p_all)
flags |= PCRE2_SUBSTITUTE_GLOBAL;
- PCRE2_SIZE olength = output.length();
-
PCRE2_SIZE length = p_subject.length();
if (p_end >= 0 && (uint32_t)p_end < length)
length = p_end;
@@ -363,15 +372,15 @@ String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_a
pcre2_match_context_16 *mctx = pcre2_match_context_create_16(gctx);
PCRE2_SPTR16 s = (PCRE2_SPTR16)p_subject.c_str();
PCRE2_SPTR16 r = (PCRE2_SPTR16)p_replacement.c_str();
- PCRE2_UCHAR16 *o = (PCRE2_UCHAR16 *)output.c_str();
+ PCRE2_UCHAR16 *o = (PCRE2_UCHAR16 *)output.ptrw();
pcre2_match_data_16 *match = pcre2_match_data_create_from_pattern_16(c, gctx);
int res = pcre2_substitute_16(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength);
if (res == PCRE2_ERROR_NOMEMORY) {
- output.resize(olength);
- o = (PCRE2_UCHAR16 *)output.c_str();
+ output.resize(olength + safety_zone);
+ o = (PCRE2_UCHAR16 *)output.ptrw();
res = pcre2_substitute_16(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength);
}
@@ -388,15 +397,15 @@ String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_a
pcre2_match_context_32 *mctx = pcre2_match_context_create_32(gctx);
PCRE2_SPTR32 s = (PCRE2_SPTR32)p_subject.c_str();
PCRE2_SPTR32 r = (PCRE2_SPTR32)p_replacement.c_str();
- PCRE2_UCHAR32 *o = (PCRE2_UCHAR32 *)output.c_str();
+ PCRE2_UCHAR32 *o = (PCRE2_UCHAR32 *)output.ptrw();
pcre2_match_data_32 *match = pcre2_match_data_create_from_pattern_32(c, gctx);
int res = pcre2_substitute_32(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength);
if (res == PCRE2_ERROR_NOMEMORY) {
- output.resize(olength);
- o = (PCRE2_UCHAR32 *)output.c_str();
+ output.resize(olength + safety_zone);
+ o = (PCRE2_UCHAR32 *)output.ptrw();
res = pcre2_substitute_32(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength);
}
@@ -407,7 +416,7 @@ String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_a
return String();
}
- return output;
+ return String(output.ptr(), olength);
}
bool RegEx::is_valid() const {