summaryrefslogtreecommitdiff
path: root/Libraries/LibRegex/RegexOptions.h
diff options
context:
space:
mode:
Diffstat (limited to 'Libraries/LibRegex/RegexOptions.h')
-rw-r--r--Libraries/LibRegex/RegexOptions.h159
1 files changed, 159 insertions, 0 deletions
diff --git a/Libraries/LibRegex/RegexOptions.h b/Libraries/LibRegex/RegexOptions.h
new file mode 100644
index 0000000000..36cc0ce40a
--- /dev/null
+++ b/Libraries/LibRegex/RegexOptions.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2020, Emanuel Sprung <emanuel.sprung@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/Types.h>
+#include <stdio.h>
+#ifdef __serenity__
+# include <regex.h>
+#else
+# include <LibC/regex.h>
+#endif
+
+namespace regex {
+
+using FlagsUnderlyingType = u16;
+
+enum class AllFlags {
+ Global = __Regex_Global, // All matches (don't return after first match)
+ Insensitive = __Regex_Insensitive, // Case insensitive match (ignores case of [a-zA-Z])
+ Ungreedy = __Regex_Ungreedy, // The match becomes lazy by default. Now a ? following a quantifier makes it greedy
+ Unicode = __Regex_Unicode, // Enable all unicode features and interpret all unicode escape sequences as such
+ Extended = __Regex_Extended, // Ignore whitespaces. Spaces and text after a # in the pattern are ignored
+ Extra = __Regex_Extra, // Disallow meaningless escapes. A \ followed by a letter with no special meaning is faulted
+ MatchNotBeginOfLine = __Regex_MatchNotBeginOfLine, // Pattern is not forced to ^ -> search in whole string!
+ MatchNotEndOfLine = __Regex_MatchNotEndOfLine, // Don't Force the dollar sign, $, to always match end of the string, instead of end of the line. This option is ignored if the Multiline-flag is set
+ SkipSubExprResults = __Regex_SkipSubExprResults, // Do not return sub expressions in the result
+ StringCopyMatches = __Regex_StringCopyMatches, // Do explicitly copy results into new allocated string instead of StringView to original string.
+ SingleLine = __Regex_SingleLine, // Dot matches newline characters
+ Sticky = __Regex_Sticky, // Force the pattern to only match consecutive matches from where the previous match ended.
+ Multiline = __Regex_Multiline, // Handle newline characters. Match each line, one by one.
+ SkipTrimEmptyMatches = __Regex_SkipTrimEmptyMatches, // Do not remove empty capture group results.
+ Last = SkipTrimEmptyMatches
+};
+
+enum class PosixFlags : FlagsUnderlyingType {
+ Global = (FlagsUnderlyingType)AllFlags::Global,
+ Insensitive = (FlagsUnderlyingType)AllFlags::Insensitive,
+ Ungreedy = (FlagsUnderlyingType)AllFlags::Ungreedy,
+ Unicode = (FlagsUnderlyingType)AllFlags::Unicode,
+ Extended = (FlagsUnderlyingType)AllFlags::Extended,
+ Extra = (FlagsUnderlyingType)AllFlags::Extra,
+ MatchNotBeginOfLine = (FlagsUnderlyingType)AllFlags::MatchNotBeginOfLine,
+ MatchNotEndOfLine = (FlagsUnderlyingType)AllFlags::MatchNotEndOfLine,
+ SkipSubExprResults = (FlagsUnderlyingType)AllFlags::SkipSubExprResults,
+ Multiline = (FlagsUnderlyingType)AllFlags::Multiline,
+ StringCopyMatches = (FlagsUnderlyingType)AllFlags::StringCopyMatches,
+};
+
+enum class ECMAScriptFlags : FlagsUnderlyingType {
+ Global = (FlagsUnderlyingType)AllFlags::Global,
+ Insensitive = (FlagsUnderlyingType)AllFlags::Insensitive,
+ Ungreedy = (FlagsUnderlyingType)AllFlags::Ungreedy,
+ Unicode = (FlagsUnderlyingType)AllFlags::Unicode,
+ Extended = (FlagsUnderlyingType)AllFlags::Extended,
+ Extra = (FlagsUnderlyingType)AllFlags::Extra,
+ SingleLine = (FlagsUnderlyingType)AllFlags::SingleLine,
+ Sticky = (FlagsUnderlyingType)AllFlags::Sticky,
+ Multiline = (FlagsUnderlyingType)AllFlags::Multiline,
+ StringCopyMatches = (FlagsUnderlyingType)AllFlags::StringCopyMatches,
+};
+
+template<class T>
+class RegexOptions {
+public:
+ using FlagsType = T;
+
+ RegexOptions() = default;
+
+ RegexOptions(T flags)
+ : m_flags(flags)
+ {
+ }
+
+ template<class U>
+ RegexOptions(RegexOptions<U> other)
+ : m_flags((T) static_cast<FlagsUnderlyingType>(other.value()))
+ {
+ }
+
+ operator bool() const { return !!*this; }
+ bool operator!() const { return (FlagsUnderlyingType)m_flags == 0; }
+
+ RegexOptions<T> operator|(T flag) const { return RegexOptions<T> { (T)((FlagsUnderlyingType)m_flags | (FlagsUnderlyingType)flag) }; }
+ RegexOptions<T> operator&(T flag) const { return RegexOptions<T> { (T)((FlagsUnderlyingType)m_flags & (FlagsUnderlyingType)flag) }; }
+
+ RegexOptions<T>& operator|=(T flag)
+ {
+ m_flags = (T)((FlagsUnderlyingType)m_flags | (FlagsUnderlyingType)flag);
+ return *this;
+ }
+
+ RegexOptions<T>& operator&=(T flag)
+ {
+ m_flags = (T)((FlagsUnderlyingType)m_flags & (FlagsUnderlyingType)flag);
+ return *this;
+ }
+
+ void reset_flags() { m_flags = (T)0; }
+ void reset_flag(T flag) { m_flags = (T)((FlagsUnderlyingType)m_flags & ~(FlagsUnderlyingType)flag); }
+ void set_flag(T flag) { *this |= flag; }
+ bool has_flag_set(T flag) const { return *this & flag; }
+ T value() const { return m_flags; }
+
+private:
+ T m_flags { 0 };
+};
+
+template<class T>
+inline RegexOptions<T> operator|(T lhs, T rhs)
+{
+ return RegexOptions<T> { lhs } |= rhs;
+}
+
+template<class T>
+inline RegexOptions<T> operator&(T lhs, T rhs)
+{
+ return RegexOptions<T> { lhs } &= rhs;
+}
+
+template<class T>
+inline T operator~(T flag)
+{
+ return (T) ~((FlagsUnderlyingType)flag);
+}
+
+using AllOptions = RegexOptions<AllFlags>;
+using ECMAScriptOptions = RegexOptions<ECMAScriptFlags>;
+using PosixOptions = RegexOptions<PosixFlags>;
+
+}
+
+using regex::ECMAScriptFlags;
+using regex::ECMAScriptOptions;
+using regex::PosixFlags;
+using regex::PosixOptions;