From b34a5c2e2d9c4dc7f7b6196c43c4967a1c38c1f9 Mon Sep 17 00:00:00 2001 From: Andersama Date: Thu, 8 Jul 2021 23:27:09 -0700 Subject: [PATCH] Optimization: Check for implicit anchor Improves code generation for cases where .* can be treated as an anchor --- include/ctre/evaluation.hpp | 1 + include/ctre/has_implicit_anchor.hpp | 68 ++++++++++++++++++++++++++++ include/ctre/wrapper.hpp | 2 +- single-header/ctre-unicode.hpp | 68 +++++++++++++++++++++++++++- single-header/ctre.hpp | 68 +++++++++++++++++++++++++++- 5 files changed, 204 insertions(+), 3 deletions(-) create mode 100644 include/ctre/has_implicit_anchor.hpp diff --git a/include/ctre/evaluation.hpp b/include/ctre/evaluation.hpp index 8191be00..246c4e4e 100644 --- a/include/ctre/evaluation.hpp +++ b/include/ctre/evaluation.hpp @@ -5,6 +5,7 @@ #include "atoms.hpp" #include "atoms_unicode.hpp" #include "starts_with_anchor.hpp" +#include "has_implicit_anchor.hpp" #include "utility.hpp" #include "return_type.hpp" #include "find_captures.hpp" diff --git a/include/ctre/has_implicit_anchor.hpp b/include/ctre/has_implicit_anchor.hpp new file mode 100644 index 00000000..ea68b1ee --- /dev/null +++ b/include/ctre/has_implicit_anchor.hpp @@ -0,0 +1,68 @@ +#ifndef CTRE__HAS_IMPLICIT_ANCHOR__HPP +#define CTRE__HAS_IMPLICIT_ANCHOR__HPP + +#include "atoms.hpp" +#include "atoms_unicode.hpp" + +namespace ctre { + + template + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + template + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + + template + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + + template + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + + template + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + + template + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + + template + constexpr bool has_implicit_anchor(ctll::list, Tail...>) noexcept { + return has_implicit_anchor(ctll::list{}); + } + + //TODO: we may check captures as implicit anchors*, but they must not be backreferenced because for example "(.+)X\1" will not work properly with "1234X2345" + /* + template + constexpr bool has_implicit_anchor(ctll::list, Tail...>) noexcept { + //Id must not be backreferenced + return !id_backreference(Id) && has_implicit_anchor(ctll::list{}); + } + + template + constexpr bool has_implicit_anchor(ctll::list, Tail...>) noexcept { + //Id must not be backreferenced + return !id_backreference(Id) && has_implicit_anchor(ctll::list{}); + } + */ + + template + constexpr bool has_implicit_anchor(ctll::list, Tail...>) noexcept { + return (has_implicit_anchor(ctll::list{}) && ...); + } + + constexpr bool has_implicit_anchor(...) noexcept { + return false; + } +} + +#endif \ No newline at end of file diff --git a/include/ctre/wrapper.hpp b/include/ctre/wrapper.hpp index 5208e994..b98a7a0b 100644 --- a/include/ctre/wrapper.hpp +++ b/include/ctre/wrapper.hpp @@ -62,7 +62,7 @@ struct search_method { template constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin orig_begin, IteratorBegin begin, IteratorEnd end, RE) noexcept { using result_iterator = std::conditional_t, IteratorBegin, ResultIterator>; - constexpr bool fixed = starts_with_anchor(Modifier{}, ctll::list{}); + constexpr bool fixed = starts_with_anchor(Modifier{}, ctll::list{}) || has_implicit_anchor(ctll::list{}); auto it = begin; diff --git a/single-header/ctre-unicode.hpp b/single-header/ctre-unicode.hpp index 05ce8075..9dd5d06e 100644 --- a/single-header/ctre-unicode.hpp +++ b/single-header/ctre-unicode.hpp @@ -2720,6 +2720,72 @@ constexpr bool starts_with_anchor(const flags & f, ctll::list + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + template + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + + template + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + + template + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + + template + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + + template + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + + template + constexpr bool has_implicit_anchor(ctll::list, Tail...>) noexcept { + return has_implicit_anchor(ctll::list{}); + } + + //TODO: we may check captures as implicit anchors*, but they must not be backreferenced because for example "(.+)X\1" will not work properly with "1234X2345" + /* + template + constexpr bool has_implicit_anchor(ctll::list, Tail...>) noexcept { + //Id must not be backreferenced + return !id_backreference(Id) && has_implicit_anchor(ctll::list{}); + } + + template + constexpr bool has_implicit_anchor(ctll::list, Tail...>) noexcept { + //Id must not be backreferenced + return !id_backreference(Id) && has_implicit_anchor(ctll::list{}); + } + */ + + template + constexpr bool has_implicit_anchor(ctll::list, Tail...>) noexcept { + return (has_implicit_anchor(ctll::list{}) && ...); + } + + constexpr bool has_implicit_anchor(...) noexcept { + return false; + } +} + +#endif + #ifndef CTRE__RETURN_TYPE__HPP #define CTRE__RETURN_TYPE__HPP @@ -4878,7 +4944,7 @@ struct search_method { template constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin orig_begin, IteratorBegin begin, IteratorEnd end, RE) noexcept { using result_iterator = std::conditional_t, IteratorBegin, ResultIterator>; - constexpr bool fixed = starts_with_anchor(Modifier{}, ctll::list{}); + constexpr bool fixed = starts_with_anchor(Modifier{}, ctll::list{}) || has_implicit_anchor(ctll::list{}); auto it = begin; diff --git a/single-header/ctre.hpp b/single-header/ctre.hpp index 022a6a50..3c298293 100644 --- a/single-header/ctre.hpp +++ b/single-header/ctre.hpp @@ -2717,6 +2717,72 @@ constexpr bool starts_with_anchor(const flags & f, ctll::list + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + template + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + + template + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + + template + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + + template + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + + template + constexpr bool has_implicit_anchor(ctll::list, Content...>) noexcept { + return true; + } + + template + constexpr bool has_implicit_anchor(ctll::list, Tail...>) noexcept { + return has_implicit_anchor(ctll::list{}); + } + + //TODO: we may check captures as implicit anchors*, but they must not be backreferenced because for example "(.+)X\1" will not work properly with "1234X2345" + /* + template + constexpr bool has_implicit_anchor(ctll::list, Tail...>) noexcept { + //Id must not be backreferenced + return !id_backreference(Id) && has_implicit_anchor(ctll::list{}); + } + + template + constexpr bool has_implicit_anchor(ctll::list, Tail...>) noexcept { + //Id must not be backreferenced + return !id_backreference(Id) && has_implicit_anchor(ctll::list{}); + } + */ + + template + constexpr bool has_implicit_anchor(ctll::list, Tail...>) noexcept { + return (has_implicit_anchor(ctll::list{}) && ...); + } + + constexpr bool has_implicit_anchor(...) noexcept { + return false; + } +} + +#endif + #ifndef CTRE__RETURN_TYPE__HPP #define CTRE__RETURN_TYPE__HPP @@ -4875,7 +4941,7 @@ struct search_method { template constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin orig_begin, IteratorBegin begin, IteratorEnd end, RE) noexcept { using result_iterator = std::conditional_t, IteratorBegin, ResultIterator>; - constexpr bool fixed = starts_with_anchor(Modifier{}, ctll::list{}); + constexpr bool fixed = starts_with_anchor(Modifier{}, ctll::list{}) || has_implicit_anchor(ctll::list{}); auto it = begin;