summaryrefslogtreecommitdiff
path: root/src/regex__FFI.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/regex__FFI.cc')
-rw-r--r--src/regex__FFI.cc64
1 files changed, 50 insertions, 14 deletions
diff --git a/src/regex__FFI.cc b/src/regex__FFI.cc
index 66e25a8..57d4ce8 100644
--- a/src/regex__FFI.cc
+++ b/src/regex__FFI.cc
@@ -17,6 +17,7 @@
#include <cstdio>
#include <cstring>
+#include <string>
#include <regex> // NOLINT(build/c++11)
#include <boost/numeric/conversion/cast.hpp> // NOLINT(build/include_order)
@@ -59,6 +60,25 @@ Target Number(uw_context* const context, Source arg) {
}
}
+// Compiles a regular expression.
+std::regex Compile(uw_context* const context, const char needle_string[]) {
+ std::regex needle;
+ try {
+ needle.assign(needle_string, std::regex_constants::ECMAScript);
+ } catch (const std::regex_error& e) {
+ switch (e.code()) {
+ case std::regex_constants::error_space:
+ case std::regex_constants::error_stack:
+ // We ran out of memory.
+ uw_error(context, BOUNDED_RETRY, "regex: compilation failed: %s",
+ e.what());
+ default:
+ uw_error(context, FATAL, "regex: compilation failed: %s", e.what());
+ }
+ }
+ return needle;
+}
+
} // namespace
uw_Basis_bool uw_Regex__FFI_succeeded([[gnu::unused]] uw_context* const context,
@@ -108,20 +128,7 @@ uw_Basis_string uw_Regex__FFI_subexpression_match(
uw_Regex__FFI_match uw_Regex__FFI_do_match(uw_context* const context,
const uw_Basis_string needle_string,
const uw_Basis_string haystack) {
- std::regex needle;
- try {
- needle.assign(needle_string, std::regex_constants::ECMAScript);
- } catch (const std::regex_error& e) {
- switch (e.code()) {
- case std::regex_constants::error_space:
- case std::regex_constants::error_stack:
- // We ran out of memory.
- uw_error(context, BOUNDED_RETRY, "regex: compilation failed: %s",
- e.what());
- default:
- uw_error(context, FATAL, "regex: compilation failed: %s", e.what());
- }
- }
+ std::regex needle = Compile(context, needle_string);
uw_Regex__FFI_match result;
// Make a duplicate of the string to match against, so if it goes out of
// scope in the calling Ur code, we still have it.
@@ -141,3 +148,32 @@ uw_Regex__FFI_match uw_Regex__FFI_do_match(uw_context* const context,
std::regex_search(result.haystack, *match_results, needle);
return result;
}
+
+uw_Basis_string uw_Regex__FFI_replace(uw_context* const context,
+ const uw_Basis_string needle_string,
+ const uw_Basis_string haystack,
+ const uw_Basis_string replacement) {
+ std::regex needle = Compile(context, needle_string);
+ // Perform the replacement.
+ std::string result;
+ try {
+ result = std::regex_replace(haystack, needle, replacement);
+ } catch (const std::regex_error& e) {
+ switch (e.code()) {
+ case std::regex_constants::error_space:
+ case std::regex_constants::error_stack:
+ // We ran out of memory.
+ uw_error(context, BOUNDED_RETRY, "regex: replacement failed: %s",
+ e.what());
+ default:
+ uw_error(context, FATAL, "regex: replacement failed: %s", e.what());
+ }
+ }
+ // Save the result string.
+ char* const result_string =
+ reinterpret_cast<char*>(uw_malloc(context, result.length() + 1));
+ Assert(context, std::snprintf(result_string, result.length() + 1, "%s",
+ result.c_str()) >= 0,
+ "regex: snprintf failed during replace");
+ return result_string;
+}