From 655f2bc59e11ccd16229f2e7474b013e585192fb Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Thu, 30 Jul 2015 17:26:16 -0400 Subject: Implement regex substitution --- src/regex__FFI.cc | 64 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 14 deletions(-) (limited to 'src/regex__FFI.cc') 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 #include +#include #include // NOLINT(build/c++11) #include // 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(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; +} -- cgit v1.2.3