From aa05cf6073cf2a6dfa46108cd5522c0171a7f1c3 Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Thu, 30 Jul 2015 16:51:31 -0400 Subject: Make library work on both client and server sides Replace the two-step compile/match process with a single compile-and-match one to avoid issues with server-client representation incompatibility. Use the browser regex engine on the client side. --- Makefile.am | 1 + src/lib.urp | 6 ++++++ src/regex.ur | 7 +------ src/regex.urs | 18 ++++-------------- src/regex__FFI.cc | 35 +++++++---------------------------- src/regex__FFI.h | 9 ++------- src/regex__FFI.js | 42 ++++++++++++++++++++++++++++++++++++++++++ src/regex__FFI.urs | 12 ++++-------- 8 files changed, 67 insertions(+), 63 deletions(-) create mode 100644 src/regex__FFI.js diff --git a/Makefile.am b/Makefile.am index cba5a94..0a9cf20 100644 --- a/Makefile.am +++ b/Makefile.am @@ -48,6 +48,7 @@ liburweb_regex_la_SOURCES = src/regex__FFI.cc liburweb_regex_la_DATA = \ src/lib.urp \ src/regex__FFI.h \ + src/regex__FFI.js \ src/regex__FFI.urs \ src/regex.urs \ src/regex.ur diff --git a/src/lib.urp b/src/lib.urp index 9f95450..2dff404 100644 --- a/src/lib.urp +++ b/src/lib.urp @@ -1,5 +1,11 @@ ffi regex__FFI include regex__FFI.h link -lurweb_regex +jsFunc Regex__FFI.succeeded=UrWeb.Regex.succeeded +jsFunc Regex__FFI.n_subexpression_matches=UrWeb.Regex.nSubexpressionMatches +jsFunc Regex__FFI.subexpression_match=UrWeb.Regex.subexpressionMatch +jsFunc Regex__FFI.do_match=UrWeb.Regex.doMatch +file /cgGvSqBi.js regex__FFI.js +script /cgGvSqBi.js regex \ No newline at end of file diff --git a/src/regex.ur b/src/regex.ur index ddc7793..cc039e2 100644 --- a/src/regex.ur +++ b/src/regex.ur @@ -1,4 +1,5 @@ (* Copyright 2015 the Massachusetts Institute of Technology +Copyright 2015 Benjamin Barenblat Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the @@ -13,12 +14,6 @@ specific language governing permissions and limitations under the License. *) structure FFI = Regex__FFI -type t = FFI.regex - -val compile = FFI.compile True - -val compile_case_insensitive = FFI.compile False - fun match regex input = (* Perform the match. *) let diff --git a/src/regex.urs b/src/regex.urs index 15ce216..2591fe8 100644 --- a/src/regex.urs +++ b/src/regex.urs @@ -1,4 +1,5 @@ (* Copyright 2015 the Massachusetts Institute of Technology +Copyright 2015 Benjamin Barenblat Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the @@ -56,22 +57,11 @@ Here's a brief syntax reminder: '[[:digit:]]'. *) -(* Creating *) - -(* A compiled regular expression. *) -type t - -(* Compiles a regular expression from a POSIX extended regular expression -string. *) -val compile : string -> t - -(* Compiles a case-insensitive regular expression from a POSIX extended regular expression string. *) -val compile_case_insensitive : string -> t - - (* Searching *) (* Matches a regular expression against any part of a string. Returns 'Some strs', where 'strs' is a list of subexpression matches, if a match succeeds, and 'None' otherwise. *) -val match : t -> string -> option (list string) +val match : string (* needle *) + -> string (* haystack *) + -> option (list string) diff --git a/src/regex__FFI.cc b/src/regex__FFI.cc index 3412e51..b4a2297 100644 --- a/src/regex__FFI.cc +++ b/src/regex__FFI.cc @@ -1,4 +1,5 @@ // Copyright (C) 2015 the Massachusetts Institute of Technology +// Copyright (C) 2015 Benjamin Barenblat // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -43,10 +44,6 @@ void Assert(uw_context* const context, const bool condition, Assert(context, condition, FATAL, message); } -void DeleteRegex(void* regex, [[gnu::unused]] const int _will_retry) { - delete reinterpret_cast(regex); -} - void DeleteMatchResults(void* match_result, [[gnu::unused]] const int _will_retry) { delete reinterpret_cast(match_result); @@ -108,23 +105,12 @@ uw_Basis_string uw_Regex__FFI_subexpression_match( return result; } -uw_Regex__FFI_regex uw_Regex__FFI_compile(uw_context* const context, - const uw_Basis_bool case_sensitive, - const uw_Basis_string input) { - // We'd like to stack-allocate the result--or, at least, to allocate it with - // uw_malloc. Unfortunately, neither of those will work, because we need to - // run a finalizer on it, and Ur finalizers can only reference addresses that - // are not managed by Ur. - auto* result = new std::regex; - Assert(context, uw_register_transactional(context, result, nullptr, nullptr, - DeleteRegex) == 0, - "regex: could not register DeleteRegex finalizer"); - auto flags = std::regex_constants::extended; - if (!case_sensitive) { - flags |= std::regex_constants::icase; - } +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 { - result->assign(input, flags); + needle.assign(needle_string, std::regex_constants::extended); } catch (const std::regex_error& e) { switch (e.code()) { case std::regex_constants::error_space: @@ -136,12 +122,6 @@ uw_Regex__FFI_regex uw_Regex__FFI_compile(uw_context* const context, uw_error(context, FATAL, "regex: compilation failed: %s", e.what()); } } - return result; -} - -uw_Regex__FFI_match uw_Regex__FFI_do_match(uw_context* const context, - const uw_Regex__FFI_regex needle, - const uw_Basis_string haystack) { 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. @@ -158,7 +138,6 @@ uw_Regex__FFI_match uw_Regex__FFI_do_match(uw_context* const context, "regex: could not register DeleteMatchResults finalizer"); result.result = match_results; // Execute the regex on the saved haystack, not the original one. - std::regex_search(result.haystack, *match_results, - *reinterpret_cast(needle)); + std::regex_search(result.haystack, *match_results, needle); return result; } diff --git a/src/regex__FFI.h b/src/regex__FFI.h index 4cf5435..695033a 100644 --- a/src/regex__FFI.h +++ b/src/regex__FFI.h @@ -1,4 +1,5 @@ /* Copyright (C) 2015 the Massachusetts Institute of Technology +Copyright (C) 2015 Benjamin Barenblat Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the @@ -24,8 +25,6 @@ extern "C" { #include -typedef void* uw_Regex__FFI_regex; - typedef struct { char* haystack; void* result; @@ -41,12 +40,8 @@ uw_Basis_string uw_Regex__FFI_subexpression_match(struct uw_context*, const uw_Regex__FFI_match, const uw_Basis_int); -uw_Regex__FFI_regex uw_Regex__FFI_compile(struct uw_context*, - const uw_Basis_bool, - const uw_Basis_string); - uw_Regex__FFI_match uw_Regex__FFI_do_match(struct uw_context*, - const uw_Regex__FFI_regex, + const uw_Basis_string, const uw_Basis_string); #ifdef __cplusplus diff --git a/src/regex__FFI.js b/src/regex__FFI.js new file mode 100644 index 0000000..fcb8927 --- /dev/null +++ b/src/regex__FFI.js @@ -0,0 +1,42 @@ +// Copyright © 2015 Benjamin Barenblat +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +var UrWeb = { Regex: { + +succeeded: function(match) { + return !!match; +}, + +nSubexpressionMatches: function(match) { + return match.length - 1; +}, + +subexpressionMatch: function(match, n) { + if (match.length - 1 <= n) { + er("regex: match does not exist"); + } + return match[n + 1]; +}, + +doMatch: function(needle_string, haystack) { + var needle; + try { + needle = new RegExp(needle_string); + } catch (e) { + er("regex: compilation failed"); + } + return haystack.match(needle); +}, + +}}; // UrWeb.Regex diff --git a/src/regex__FFI.urs b/src/regex__FFI.urs index 690ca1d..862d4f3 100644 --- a/src/regex__FFI.urs +++ b/src/regex__FFI.urs @@ -1,4 +1,5 @@ (* Copyright 2015 the Massachusetts Institute of Technology +Copyright 2015 Benjamin Barenblat Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the @@ -15,9 +16,6 @@ specific language governing permissions and limitations under the License. *) instead. *) -(* A compiled regular expression. *) -type regex - (* Data about a match. There is no function which returns all subexpression matches, as we can't build an Ur list in C. *) type match @@ -26,9 +24,7 @@ val n_subexpression_matches : match -> int val subexpression_match : match -> int -> string -(* Compiles a regular expression from a POSIX extended regular expression -string. *) -val compile : bool (* case sensitive? *) -> string -> regex - (* Matches a regular expression against any part of a string. *) -val do_match : regex -> string -> match +val do_match : string (* needle *) + -> string (* haystack *) + -> match -- cgit v1.2.3