ENH: reorganize regular expressions and add C++11 regex support
- new regExpCxx wrapper for C++11 regex support with drop-in compatibility with existing code. - regExpPosix (was regExp), for future phase out in favour of regExpCxx. - The regExp header will continue to be used for defining an appropriate typedef corresponding to the preferred implementation.
This commit is contained in:
parent
e0e0414726
commit
487877377d
@ -1,3 +0,0 @@
|
||||
Test-regex.C
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-regex
|
3
applications/test/regex1/Make/files
Normal file
3
applications/test/regex1/Make/files
Normal file
@ -0,0 +1,3 @@
|
||||
Test-regex1.C
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-regex1
|
@ -2,10 +2,8 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
|
||||
\\ / A nd | Copyright (C) 2017-2019 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
| Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -28,13 +26,14 @@ Description
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "argList.H"
|
||||
#include "IOstreams.H"
|
||||
#include "IOobject.H"
|
||||
#include "IFstream.H"
|
||||
#include "regExp.H"
|
||||
#include "SubStrings.H"
|
||||
#include "Switch.H"
|
||||
|
||||
#include "regExpCxx.H"
|
||||
#include "regExpPosix.H"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
|
||||
@ -63,14 +62,16 @@ struct regexTest
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Needed for list output. Just treat everything as unequal.
|
||||
bool operator!=(const struct regexTest&, const struct regexTest&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Simple output of match groups
|
||||
static Ostream& operator<<(Ostream& os, const regExp::results_type& sm)
|
||||
static Ostream& operator<<(Ostream& os, const regExpCxx::results_type& sm)
|
||||
{
|
||||
for (std::smatch::size_type i = 1; i < sm.size(); ++i)
|
||||
{
|
||||
@ -81,22 +82,144 @@ static Ostream& operator<<(Ostream& os, const regExp::results_type& sm)
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
// Main program:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
// Simple output of match groups
|
||||
static Ostream& operator<<(Ostream& os, const regExpPosix::results_type& sm)
|
||||
{
|
||||
List<regexTest> rawList(IFstream("testRegexps")());
|
||||
Info<< "Test expressions:" << rawList << endl;
|
||||
IOobject::writeDivider(Info) << endl;
|
||||
for (std::smatch::size_type i = 1; i < sm.size(); ++i)
|
||||
{
|
||||
os << " " << sm.str(i);
|
||||
}
|
||||
|
||||
regExp::results_type match;
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
template<class RegexType>
|
||||
void generalTests()
|
||||
{
|
||||
Info<< nl << "test regExp(const char*) ..." << endl;
|
||||
string me("Mark");
|
||||
|
||||
// Expect some failures:
|
||||
const bool throwingError = FatalError.throwExceptions();
|
||||
|
||||
try
|
||||
{
|
||||
// Handling of null strings
|
||||
if (RegexType(nullptr).match(me))
|
||||
{
|
||||
Info<< "fail - matched: " << me << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "pass - null pointer is no expression" << endl;
|
||||
}
|
||||
}
|
||||
catch (const Foam::error& err)
|
||||
{
|
||||
Info<< "Caught FatalError " << err << nl << endl;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Normal match
|
||||
if (RegexType("[Mm]ar[ck]").match(me))
|
||||
{
|
||||
Info<< "pass - matched: " << me << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "no match" << endl;
|
||||
}
|
||||
}
|
||||
catch (const Foam::error& err)
|
||||
{
|
||||
Info<< "Caught FatalError " << err << nl << endl;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Match ignore case
|
||||
if (RegexType("mar[ck]", true).match(me))
|
||||
{
|
||||
Info<< "pass - matched: " << me << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "no match" << endl;
|
||||
}
|
||||
}
|
||||
catch (const Foam::error& err)
|
||||
{
|
||||
Info<< "Caught FatalError " << err << nl << endl;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Embedded prefix for match ignore case
|
||||
if (RegexType("(?i)mar[ck]").match(me))
|
||||
{
|
||||
Info<< "pass - matched: " << me << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "no match" << endl;
|
||||
}
|
||||
}
|
||||
catch (const Foam::error& err)
|
||||
{
|
||||
Info<< "Caught FatalError " << err << nl << endl;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Handling of empty expression
|
||||
if (RegexType("").match(me))
|
||||
{
|
||||
Info<< "fail - matched: " << me << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "pass - no match on empty expression" << endl;
|
||||
}
|
||||
}
|
||||
catch (const Foam::error& err)
|
||||
{
|
||||
Info<< "Caught FatalError " << err << nl << endl;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Embedded prefix - but expression is empty
|
||||
if (RegexType("(?i)").match(me))
|
||||
{
|
||||
Info<< "fail - matched: " << me << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "pass - no match on empty expression" << endl;
|
||||
}
|
||||
}
|
||||
catch (const Foam::error& err)
|
||||
{
|
||||
Info<< "Caught FatalError " << err << nl << endl;
|
||||
}
|
||||
|
||||
FatalError.throwExceptions(throwingError);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class RegexType>
|
||||
void testExpressions(const UList<regexTest>& tests)
|
||||
{
|
||||
typename RegexType::results_type match;
|
||||
|
||||
// Expect some failures:
|
||||
const bool throwingError = FatalError.throwExceptions();
|
||||
|
||||
// Report matches:
|
||||
for (const auto& testseq : rawList)
|
||||
for (const auto& testseq : tests)
|
||||
{
|
||||
const bool expected = testseq.expected;
|
||||
const string& pat = testseq.pattern;
|
||||
@ -105,7 +228,7 @@ int main(int argc, char *argv[])
|
||||
Info<< "Test " << Switch(expected) << ": "
|
||||
<< str << " =~ m/" << pat.c_str() << "/ == ";
|
||||
|
||||
regExp re;
|
||||
RegexType re;
|
||||
|
||||
try
|
||||
{
|
||||
@ -137,7 +260,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (false)
|
||||
{
|
||||
regExp re2(std::move(re));
|
||||
RegexType re2(std::move(re));
|
||||
Info<<"move construct: " << re.exists() << "/" << re2.exists()
|
||||
<< endl;
|
||||
|
||||
@ -151,112 +274,76 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
Info<< nl << "test regExp(const char*) ..." << endl;
|
||||
string me("Mark");
|
||||
|
||||
try
|
||||
{
|
||||
// Handling of null strings
|
||||
if (regExp(nullptr).match(me))
|
||||
{
|
||||
Info<< "fail - matched: " << me << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "pass - null pointer is no expression" << endl;
|
||||
}
|
||||
}
|
||||
catch (const Foam::error& err)
|
||||
{
|
||||
Info<< "Caught FatalError " << err << nl << endl;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Normal match
|
||||
if (regExp("[Mm]ar[ck]").match(me))
|
||||
{
|
||||
Info<< "pass - matched: " << me << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "no match" << endl;
|
||||
}
|
||||
}
|
||||
catch (const Foam::error& err)
|
||||
{
|
||||
Info<< "Caught FatalError " << err << nl << endl;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Match ignore case
|
||||
if (regExp("mar[ck]", true).match(me))
|
||||
{
|
||||
Info<< "pass - matched: " << me << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "no match" << endl;
|
||||
}
|
||||
}
|
||||
catch (const Foam::error& err)
|
||||
{
|
||||
Info<< "Caught FatalError " << err << nl << endl;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Embedded prefix for match ignore case
|
||||
if (regExp("(?i)mar[ck]").match(me))
|
||||
{
|
||||
Info<< "pass - matched: " << me << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "no match" << endl;
|
||||
}
|
||||
}
|
||||
catch (const Foam::error& err)
|
||||
{
|
||||
Info<< "Caught FatalError " << err << nl << endl;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Handling of empty expression
|
||||
if (regExp("").match(me))
|
||||
{
|
||||
Info<< "fail - matched: " << me << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "pass - no match on empty expression" << endl;
|
||||
}
|
||||
}
|
||||
catch (const Foam::error& err)
|
||||
{
|
||||
Info<< "Caught FatalError " << err << nl << endl;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Embedded prefix - but expression is empty
|
||||
if (regExp("(?i)").match(me))
|
||||
{
|
||||
Info<< "fail - matched: " << me << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "pass - no match on empty expression" << endl;
|
||||
}
|
||||
}
|
||||
catch (const Foam::error& err)
|
||||
{
|
||||
Info<< "Caught FatalError " << err << nl << endl;
|
||||
}
|
||||
|
||||
FatalError.throwExceptions(throwingError);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
// Main program:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
argList::noBanner();
|
||||
argList::noFunctionObjects();
|
||||
argList::noParallel();
|
||||
|
||||
argList::addBoolOption
|
||||
(
|
||||
"cxx",
|
||||
"Test C++11 regular expressions"
|
||||
);
|
||||
|
||||
argList::addBoolOption
|
||||
(
|
||||
"posix",
|
||||
"Test POSIX regular expressions"
|
||||
);
|
||||
|
||||
argList::addArgument("file");
|
||||
argList::addArgument("...");
|
||||
argList::addArgument("fileN");
|
||||
argList::noMandatoryArgs();
|
||||
|
||||
#include "setRootCase.H"
|
||||
|
||||
if (!args.count({"cxx", "posix"}))
|
||||
{
|
||||
Info<< "Specified one or more of -cxx, -posix" << nl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (args.size() < 2)
|
||||
{
|
||||
Info<< "No test files specified .. restrict to general tests" << nl;
|
||||
|
||||
if (args.found("cxx"))
|
||||
{
|
||||
generalTests<regExpCxx>();
|
||||
}
|
||||
|
||||
if (args.found("posix"))
|
||||
{
|
||||
generalTests<regExpPosix>();
|
||||
}
|
||||
}
|
||||
|
||||
for (label argi = 1; argi < args.size(); ++argi)
|
||||
{
|
||||
List<regexTest> tests(IFstream(args[argi])());
|
||||
|
||||
Info<< "Test expressions:" << tests << endl;
|
||||
IOobject::writeDivider(Info) << endl;
|
||||
|
||||
if (args.found("cxx"))
|
||||
{
|
||||
testExpressions<regExpCxx>(tests);
|
||||
}
|
||||
|
||||
if (args.found("posix"))
|
||||
{
|
||||
testExpressions<regExpPosix>(tests);
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "\nDone" << nl << endl;
|
||||
|
@ -4,7 +4,7 @@ signals/sigInt.C
|
||||
signals/sigQuit.C
|
||||
signals/sigStopAtWriteNow.C
|
||||
signals/sigWriteNow.C
|
||||
regExp.C
|
||||
regExpPosix.C
|
||||
timer.C
|
||||
fileStat.C
|
||||
POSIX.C
|
||||
|
@ -2,10 +2,8 @@
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
|
||||
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
| Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -23,176 +21,19 @@ License
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Typedef
|
||||
Foam::regExp
|
||||
|
||||
Description
|
||||
Wrapper around POSIX extended regular expressions.
|
||||
|
||||
The PCRE '(?i)' extension is provided to compile the regular expression
|
||||
as being case-insensitive.
|
||||
|
||||
See also
|
||||
The manpage regex(7) for more information about POSIX regular expressions.
|
||||
These differ somewhat from \c Perl and \c sed regular expressions.
|
||||
|
||||
SourceFiles
|
||||
regExpI.H
|
||||
regExp.C
|
||||
Selection of preferred regular expression implementation
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef regExp_H
|
||||
#define regExp_H
|
||||
|
||||
#include <regex.h>
|
||||
#include <string>
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declarations
|
||||
template<class String> class SubStrings;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class regExp Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class regExp
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- Precompiled regular expression
|
||||
regex_t* preg_;
|
||||
|
||||
public:
|
||||
|
||||
//- Type for matches
|
||||
typedef SubStrings<std::string> results_type;
|
||||
|
||||
|
||||
// Static Member Functions
|
||||
|
||||
//- Test if character appears to be a regular expression meta-character
|
||||
// \return true if character is one of the following:
|
||||
// - any character: '.' \n
|
||||
// - quantifiers: '*', '+', '?' \n
|
||||
// - grouping: '(', '|', ')' \n
|
||||
// - range: '[', ']' \n
|
||||
//
|
||||
// \note The presence of '{', '}' regex bounds is not considered
|
||||
inline static bool meta(char c);
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null
|
||||
inline regExp();
|
||||
|
||||
//- Copy construct - disallowed
|
||||
regExp(const regExp&) = delete;
|
||||
|
||||
//- Move construct
|
||||
inline regExp(regExp&& rgx);
|
||||
|
||||
//- Construct from character array
|
||||
inline explicit regExp(const char* pattern);
|
||||
|
||||
//- Construct from string
|
||||
inline explicit regExp(const std::string& pattern);
|
||||
|
||||
//- Construct from character array, optionally ignore case
|
||||
inline regExp(const char* pattern, bool ignoreCase);
|
||||
|
||||
//- Construct from string, optionally ignore case
|
||||
inline regExp(const std::string& pattern, bool ignoreCase);
|
||||
|
||||
|
||||
//- Destructor
|
||||
inline ~regExp();
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
// Access
|
||||
|
||||
//- Return true if a precompiled expression does not exist
|
||||
inline bool empty() const;
|
||||
|
||||
//- Return true if a precompiled expression exists
|
||||
inline bool exists() const;
|
||||
|
||||
//- The number of capture groups for a non-empty expression
|
||||
inline unsigned ngroups() const;
|
||||
|
||||
// Editing
|
||||
|
||||
//- Clear expression.
|
||||
// \return True if expression had existed prior to the clear.
|
||||
bool clear();
|
||||
|
||||
//- Swap contents
|
||||
inline void swap(regExp& rgx);
|
||||
|
||||
//- Compile pattern into a regular expression, optionally ignore case.
|
||||
// \return True if the pattern was compiled
|
||||
bool set(const char* pattern, bool ignoreCase=false);
|
||||
|
||||
//- Compile pattern into a regular expression, optionally ignore case.
|
||||
// \return True if the pattern was compiled
|
||||
bool set(const std::string& pattern, bool ignoreCase=false);
|
||||
|
||||
// Matching/Searching
|
||||
|
||||
//- Find position within the text.
|
||||
// \return The index where it begins or string::npos if not found
|
||||
std::string::size_type find(const std::string& text) const;
|
||||
|
||||
//- True if the regex matches the entire text.
|
||||
// The begin-of-line (^) and end-of-line ($) anchors are implicit
|
||||
bool match(const std::string& text) const;
|
||||
|
||||
//- True if the regex matches the text, set the matches.
|
||||
// The first group starts at index 1 (0 is the entire match).
|
||||
// The begin-of-line (^) and end-of-line ($) anchors are implicit
|
||||
bool match(const std::string& text, results_type& matches) const;
|
||||
|
||||
//- Return true if the regex was found within the text
|
||||
inline bool search(const std::string& text) const;
|
||||
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Perform match on text
|
||||
inline bool operator()(const std::string& text) const;
|
||||
|
||||
//- Copy assignment - disallowed
|
||||
void operator=(const regExp&) = delete;
|
||||
|
||||
//- Move assignment
|
||||
inline void operator=(regExp&& rgx);
|
||||
|
||||
//- Assign and compile pattern from a character array.
|
||||
// Matching is case sensitive.
|
||||
inline void operator=(const char* pattern);
|
||||
|
||||
//- Assign and compile pattern from string.
|
||||
// Matching is case sensitive.
|
||||
inline void operator=(const std::string& pattern);
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "regExpI.H"
|
||||
#include "regExpPosix.H"
|
||||
#include "regExpFwd.H"
|
||||
|
||||
#endif
|
||||
|
||||
|
49
src/OSspecific/POSIX/regExpFwd.H
Normal file
49
src/OSspecific/POSIX/regExpFwd.H
Normal file
@ -0,0 +1,49 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Typedef
|
||||
Foam::regExp
|
||||
|
||||
Description
|
||||
Selection of preferred regular expression implementation
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef regExpFwd_H
|
||||
#define regExpFwd_H
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
class regExpCxx;
|
||||
class regExpPosix;
|
||||
|
||||
typedef regExpPosix regExp;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
@ -25,22 +25,32 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "regExp.H"
|
||||
#include "regExpPosix.H"
|
||||
#include "SubStrings.H"
|
||||
#include "error.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
int Foam::regExpPosix::grammar(0);
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Verify that the entire len was matched
|
||||
static inline bool fullMatch(const regmatch_t& m, const regoff_t len)
|
||||
{
|
||||
return (m.rm_so == 0 && m.rm_eo == len);
|
||||
}
|
||||
|
||||
} // End anonymous namespace
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::regExp::clear()
|
||||
bool Foam::regExpPosix::clear()
|
||||
{
|
||||
if (preg_)
|
||||
{
|
||||
@ -55,7 +65,7 @@ bool Foam::regExp::clear()
|
||||
}
|
||||
|
||||
|
||||
bool Foam::regExp::set(const char* pattern, bool ignoreCase)
|
||||
bool Foam::regExpPosix::set(const char* pattern, bool ignoreCase)
|
||||
{
|
||||
clear();
|
||||
|
||||
@ -106,13 +116,13 @@ bool Foam::regExp::set(const char* pattern, bool ignoreCase)
|
||||
}
|
||||
|
||||
|
||||
bool Foam::regExp::set(const std::string& pattern, bool ignoreCase)
|
||||
bool Foam::regExpPosix::set(const std::string& pattern, bool ignoreCase)
|
||||
{
|
||||
return set(pattern.c_str(), ignoreCase);
|
||||
}
|
||||
|
||||
|
||||
std::string::size_type Foam::regExp::find(const std::string& text) const
|
||||
std::string::size_type Foam::regExpPosix::find(const std::string& text) const
|
||||
{
|
||||
if (preg_ && !text.empty())
|
||||
{
|
||||
@ -129,7 +139,7 @@ std::string::size_type Foam::regExp::find(const std::string& text) const
|
||||
}
|
||||
|
||||
|
||||
bool Foam::regExp::match(const std::string& text) const
|
||||
bool Foam::regExpPosix::match(const std::string& text) const
|
||||
{
|
||||
const auto len = text.size();
|
||||
|
||||
@ -151,7 +161,7 @@ bool Foam::regExp::match(const std::string& text) const
|
||||
}
|
||||
|
||||
|
||||
bool Foam::regExp::match
|
||||
bool Foam::regExpPosix::match
|
||||
(
|
||||
const std::string& text,
|
||||
SubStrings<std::string>& matches
|
204
src/OSspecific/POSIX/regExpPosix.H
Normal file
204
src/OSspecific/POSIX/regExpPosix.H
Normal file
@ -0,0 +1,204 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2004-2011, 2017-2018 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
| Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::regExpPosix
|
||||
|
||||
Description
|
||||
Wrapper around POSIX extended regular expressions.
|
||||
|
||||
The PCRE '(?i)' extension is provided to compile the regular expression
|
||||
as being case-insensitive.
|
||||
|
||||
See also
|
||||
The manpage regex(7) for more information about POSIX regular expressions.
|
||||
These differ somewhat from \c Perl and \c sed regular expressions.
|
||||
|
||||
SourceFiles
|
||||
regExpPosixI.H
|
||||
regExpPosix.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef regExpPosix_H
|
||||
#define regExpPosix_H
|
||||
|
||||
#include <regex.h>
|
||||
#include <string>
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward Declarations
|
||||
template<class String> class SubStrings;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class regExpPosix Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class regExpPosix
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Precompiled regular expression
|
||||
regex_t* preg_;
|
||||
|
||||
public:
|
||||
|
||||
//- Type for matches
|
||||
typedef SubStrings<std::string> results_type;
|
||||
|
||||
// Static Member Data
|
||||
|
||||
//- The default grammar (unused) - for future-compatibility
|
||||
static int grammar;
|
||||
|
||||
|
||||
// Static Member Functions
|
||||
|
||||
//- Test if character appears to be a regular expression meta-character
|
||||
// \return true if character is one of the following:
|
||||
// - any character: '.' \n
|
||||
// - quantifiers: '*', '+', '?' \n
|
||||
// - grouping: '(', '|', ')' \n
|
||||
// - range: '[', ']' \n
|
||||
//
|
||||
// \note The presence of '{', '}' regex bounds is not considered
|
||||
inline static bool meta(char c);
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null
|
||||
inline regExpPosix();
|
||||
|
||||
//- Copy construct - disallowed
|
||||
regExpPosix(const regExpPosix&) = delete;
|
||||
|
||||
//- Move construct
|
||||
inline regExpPosix(regExpPosix&& rgx);
|
||||
|
||||
//- Construct from character array
|
||||
inline explicit regExpPosix(const char* pattern);
|
||||
|
||||
//- Construct from string
|
||||
inline explicit regExpPosix(const std::string& pattern);
|
||||
|
||||
//- Construct from character array, optionally ignore case
|
||||
inline regExpPosix(const char* pattern, bool ignoreCase);
|
||||
|
||||
//- Construct from string, optionally ignore case
|
||||
inline regExpPosix(const std::string& pattern, bool ignoreCase);
|
||||
|
||||
|
||||
//- Destructor
|
||||
inline ~regExpPosix();
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
// Access
|
||||
|
||||
//- Return true if a precompiled expression does not exist
|
||||
inline bool empty() const;
|
||||
|
||||
//- Return true if a precompiled expression exists
|
||||
inline bool exists() const;
|
||||
|
||||
//- The number of capture groups for a non-empty expression
|
||||
inline unsigned ngroups() const;
|
||||
|
||||
// Editing
|
||||
|
||||
//- Clear expression.
|
||||
// \return True if expression had existed prior to the clear.
|
||||
bool clear();
|
||||
|
||||
//- Swap contents
|
||||
inline void swap(regExpPosix& rgx);
|
||||
|
||||
//- Compile pattern into a regular expression, optionally ignore case.
|
||||
// \return True if the pattern was compiled
|
||||
bool set(const char* pattern, bool ignoreCase=false);
|
||||
|
||||
//- Compile pattern into a regular expression, optionally ignore case.
|
||||
// \return True if the pattern was compiled
|
||||
bool set(const std::string& pattern, bool ignoreCase=false);
|
||||
|
||||
// Matching/Searching
|
||||
|
||||
//- Find position within the text.
|
||||
// \return The index where it begins or string::npos if not found
|
||||
std::string::size_type find(const std::string& text) const;
|
||||
|
||||
//- True if the regex matches the entire text.
|
||||
// The begin-of-line (^) and end-of-line ($) anchors are implicit
|
||||
bool match(const std::string& text) const;
|
||||
|
||||
//- True if the regex matches the text, set the matches.
|
||||
// The first group starts at index 1 (0 is the entire match).
|
||||
// The begin-of-line (^) and end-of-line ($) anchors are implicit
|
||||
bool match(const std::string& text, results_type& matches) const;
|
||||
|
||||
//- Return true if the regex was found within the text
|
||||
inline bool search(const std::string& text) const;
|
||||
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Perform match on text
|
||||
inline bool operator()(const std::string& text) const;
|
||||
|
||||
//- Copy assignment - disallowed
|
||||
void operator=(const regExpPosix&) = delete;
|
||||
|
||||
//- Move assignment
|
||||
inline void operator=(regExpPosix&& rgx);
|
||||
|
||||
//- Assign and compile pattern from a character array.
|
||||
// Matching is case sensitive.
|
||||
inline void operator=(const char* pattern);
|
||||
|
||||
//- Assign and compile pattern from string.
|
||||
// Matching is case sensitive.
|
||||
inline void operator=(const std::string& pattern);
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "regExpPosixI.H"
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
@ -28,7 +28,7 @@ License
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
inline bool Foam::regExp::meta(char c)
|
||||
inline bool Foam::regExpPosix::meta(char c)
|
||||
{
|
||||
return
|
||||
(
|
||||
@ -42,13 +42,13 @@ inline bool Foam::regExp::meta(char c)
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
inline Foam::regExp::regExp()
|
||||
inline Foam::regExpPosix::regExpPosix()
|
||||
:
|
||||
preg_(nullptr)
|
||||
{}
|
||||
|
||||
|
||||
inline Foam::regExp::regExp(const char* pattern)
|
||||
inline Foam::regExpPosix::regExpPosix(const char* pattern)
|
||||
:
|
||||
preg_(nullptr)
|
||||
{
|
||||
@ -56,7 +56,7 @@ inline Foam::regExp::regExp(const char* pattern)
|
||||
}
|
||||
|
||||
|
||||
inline Foam::regExp::regExp(const std::string& pattern)
|
||||
inline Foam::regExpPosix::regExpPosix(const std::string& pattern)
|
||||
:
|
||||
preg_(nullptr)
|
||||
{
|
||||
@ -64,7 +64,7 @@ inline Foam::regExp::regExp(const std::string& pattern)
|
||||
}
|
||||
|
||||
|
||||
inline Foam::regExp::regExp(const char* pattern, bool ignoreCase)
|
||||
inline Foam::regExpPosix::regExpPosix(const char* pattern, bool ignoreCase)
|
||||
:
|
||||
preg_(nullptr)
|
||||
{
|
||||
@ -72,7 +72,7 @@ inline Foam::regExp::regExp(const char* pattern, bool ignoreCase)
|
||||
}
|
||||
|
||||
|
||||
inline Foam::regExp::regExp(const std::string& pattern, bool ignoreCase)
|
||||
inline Foam::regExpPosix::regExpPosix(const std::string& pattern, bool ignoreCase)
|
||||
:
|
||||
preg_(nullptr)
|
||||
{
|
||||
@ -80,7 +80,7 @@ inline Foam::regExp::regExp(const std::string& pattern, bool ignoreCase)
|
||||
}
|
||||
|
||||
|
||||
inline Foam::regExp::regExp(regExp&& rgx)
|
||||
inline Foam::regExpPosix::regExpPosix(regExpPosix&& rgx)
|
||||
:
|
||||
preg_(rgx.preg_)
|
||||
{
|
||||
@ -90,7 +90,7 @@ inline Foam::regExp::regExp(regExp&& rgx)
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
inline Foam::regExp::~regExp()
|
||||
inline Foam::regExpPosix::~regExpPosix()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
@ -98,31 +98,31 @@ inline Foam::regExp::~regExp()
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
inline bool Foam::regExp::empty() const
|
||||
inline bool Foam::regExpPosix::empty() const
|
||||
{
|
||||
return !preg_;
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::regExp::exists() const
|
||||
inline bool Foam::regExpPosix::exists() const
|
||||
{
|
||||
return preg_ ? true : false;
|
||||
}
|
||||
|
||||
|
||||
inline unsigned Foam::regExp::ngroups() const
|
||||
inline unsigned Foam::regExpPosix::ngroups() const
|
||||
{
|
||||
return preg_ ? preg_->re_nsub : 0;
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::regExp::search(const std::string& text) const
|
||||
inline bool Foam::regExpPosix::search(const std::string& text) const
|
||||
{
|
||||
return std::string::npos != find(text);
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::regExp::swap(regExp& rgx)
|
||||
inline void Foam::regExpPosix::swap(regExpPosix& rgx)
|
||||
{
|
||||
std::swap(preg_, rgx.preg_);
|
||||
}
|
||||
@ -130,26 +130,26 @@ inline void Foam::regExp::swap(regExp& rgx)
|
||||
|
||||
// * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
|
||||
|
||||
inline bool Foam::regExp::operator()(const std::string& text) const
|
||||
inline bool Foam::regExpPosix::operator()(const std::string& text) const
|
||||
{
|
||||
return match(text);
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::regExp::operator=(regExp&& rgx)
|
||||
inline void Foam::regExpPosix::operator=(regExpPosix&& rgx)
|
||||
{
|
||||
clear();
|
||||
swap(rgx);
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::regExp::operator=(const char* pattern)
|
||||
inline void Foam::regExpPosix::operator=(const char* pattern)
|
||||
{
|
||||
set(pattern);
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::regExp::operator=(const std::string& pattern)
|
||||
inline void Foam::regExpPosix::operator=(const std::string& pattern)
|
||||
{
|
||||
set(pattern);
|
||||
}
|
@ -120,6 +120,7 @@ $(strings)/word/wordIOList.C
|
||||
$(strings)/fileName/fileName.C
|
||||
$(strings)/fileName/fileNameIO.C
|
||||
$(strings)/keyType/keyType.C
|
||||
$(strings)/regex/regExpCxx.C
|
||||
$(strings)/wordRe/wordRe.C
|
||||
$(strings)/wordRes/wordRes.C
|
||||
$(strings)/lists/CStringList.C
|
||||
|
@ -100,14 +100,14 @@ SeeAlso
|
||||
// Some common data types
|
||||
#include "label.H"
|
||||
#include "scalar.H"
|
||||
#include "regExpFwd.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declarations
|
||||
class regExp;
|
||||
// Forward Declarations
|
||||
class dictionary;
|
||||
class SHA1Digest;
|
||||
|
||||
@ -282,7 +282,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
// Private data
|
||||
// Private Data
|
||||
|
||||
//- Report optional keywords and values if not present in dictionary
|
||||
// Set/unset via an InfoSwitch
|
||||
@ -309,12 +309,6 @@ private:
|
||||
//- The storage container
|
||||
typedef IDLList<entry> parent_type;
|
||||
|
||||
typedef DLList<entry*>::iterator pattern_iterator;
|
||||
typedef DLList<entry*>::const_iterator pattern_const_iterator;
|
||||
|
||||
typedef DLList<autoPtr<regExp>>::iterator regexp_iterator;
|
||||
typedef DLList<autoPtr<regExp>>::const_iterator regexp_const_iterator;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
|
@ -277,8 +277,8 @@ Foam::dictionary::const_searcher Foam::dictionary::csearch
|
||||
|
||||
if ((matchOpt & keyType::REGEX) && patterns_.size())
|
||||
{
|
||||
pattern_const_iterator wcLink = patterns_.begin();
|
||||
regexp_const_iterator reLink = regexps_.begin();
|
||||
auto wcLink = patterns_.cbegin();
|
||||
auto reLink = regexps_.cbegin();
|
||||
|
||||
// Find in patterns using regular expressions only
|
||||
if (findInPatterns(true, keyword, wcLink, reLink))
|
||||
@ -584,8 +584,8 @@ bool Foam::dictionary::remove(const word& keyword)
|
||||
if (iter.found())
|
||||
{
|
||||
// Delete from patterns
|
||||
pattern_iterator wcLink = patterns_.begin();
|
||||
regexp_iterator reLink = regexps_.begin();
|
||||
auto wcLink = patterns_.begin();
|
||||
auto reLink = regexps_.begin();
|
||||
|
||||
// Find in pattern using exact match only
|
||||
if (findInPatterns(false, keyword, wcLink, reLink))
|
||||
@ -645,8 +645,8 @@ bool Foam::dictionary::changeKeyword
|
||||
if (iter2()->keyword().isPattern())
|
||||
{
|
||||
// Delete from patterns
|
||||
pattern_iterator wcLink = patterns_.begin();
|
||||
regexp_iterator reLink = regexps_.begin();
|
||||
auto wcLink = patterns_.begin();
|
||||
auto reLink = regexps_.begin();
|
||||
|
||||
// Find in patterns using exact match only
|
||||
if (findInPatterns(false, iter2()->keyword(), wcLink, reLink))
|
||||
|
207
src/OpenFOAM/primitives/strings/regex/regExpCxx.C
Normal file
207
src/OpenFOAM/primitives/strings/regex/regExpCxx.C
Normal file
@ -0,0 +1,207 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017-2019 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "regExpCxx.H"
|
||||
#include "debug.H"
|
||||
#include "error.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
int Foam::regExpCxx::grammar(Foam::debug::optimisationSwitch("regExpCxx", 0));
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
static std::string error_string(const std::regex_error& err)
|
||||
{
|
||||
switch (err.code())
|
||||
{
|
||||
case std::regex_constants::error_collate :
|
||||
return "invalid collating element name";
|
||||
break;
|
||||
|
||||
case std::regex_constants::error_ctype :
|
||||
return "invalid character class name";
|
||||
break;
|
||||
|
||||
case std::regex_constants::error_escape :
|
||||
return "invalid escaped character or a trailing escape";
|
||||
break;
|
||||
|
||||
case std::regex_constants::error_backref :
|
||||
return "invalid back reference";
|
||||
break;
|
||||
|
||||
case std::regex_constants::error_brack :
|
||||
return "mismatched [ and ]";
|
||||
break;
|
||||
|
||||
case std::regex_constants::error_paren :
|
||||
return "mismatched ( and )";
|
||||
break;
|
||||
|
||||
case std::regex_constants::error_brace :
|
||||
return "mismatched { and }";
|
||||
break;
|
||||
|
||||
case std::regex_constants::error_badbrace :
|
||||
return "invalid range in a {..}";
|
||||
break;
|
||||
|
||||
case std::regex_constants::error_range :
|
||||
return "invalid [..] character range";
|
||||
break;
|
||||
|
||||
case std::regex_constants::error_space :
|
||||
return "memory error";
|
||||
break;
|
||||
|
||||
case std::regex_constants::error_badrepeat :
|
||||
return "bad '*?+{' repeat";
|
||||
break;
|
||||
|
||||
case std::regex_constants::error_complexity :
|
||||
return "expression too complex";
|
||||
break;
|
||||
|
||||
case std::regex_constants::error_stack :
|
||||
return "memory stack error";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
} // End anonymous namespace
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::regExpCxx::set(const char* pattern, bool ignoreCase)
|
||||
{
|
||||
clear();
|
||||
|
||||
size_t len = (pattern ? strlen(pattern) : 0);
|
||||
|
||||
// Avoid nullptr and zero-length patterns
|
||||
if (!len)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::regex::flag_type flags = syntax();
|
||||
if (ignoreCase)
|
||||
{
|
||||
flags |= std::regex::icase;
|
||||
}
|
||||
|
||||
const char* pat = pattern;
|
||||
|
||||
// Has embedded ignore-case prefix?
|
||||
if (len >= 4 && !strncmp(pattern, "(?i)", 4))
|
||||
{
|
||||
flags |= std::regex::icase;
|
||||
pat += 4;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
if (len)
|
||||
{
|
||||
try
|
||||
{
|
||||
re_.assign(pat, flags);
|
||||
return true;
|
||||
}
|
||||
catch (const std::regex_error& err)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Failed to compile regular expression '"
|
||||
<< pattern << "'" << nl
|
||||
<< err.what() << ": " << error_string(err).c_str() << nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::regExpCxx::set(const std::string& pattern, bool ignoreCase)
|
||||
{
|
||||
clear();
|
||||
|
||||
auto len = pattern.size();
|
||||
|
||||
// Avoid zero-length patterns
|
||||
if (!len)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::regex::flag_type flags = syntax();
|
||||
if (ignoreCase)
|
||||
{
|
||||
flags |= std::regex::icase;
|
||||
}
|
||||
|
||||
auto pat = pattern.begin();
|
||||
|
||||
// Has embedded ignore-case prefix?
|
||||
if (len >= 4 && !pattern.compare(0, 4, "(?i)"))
|
||||
{
|
||||
flags |= std::regex::icase;
|
||||
pat += 4;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
if (len)
|
||||
{
|
||||
try
|
||||
{
|
||||
re_.assign(pat, pattern.end(), flags);
|
||||
return true;
|
||||
}
|
||||
catch (const std::regex_error& err)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Failed to compile regular expression '"
|
||||
<< pattern.c_str() << "'" << nl
|
||||
<< err.what() << ": " << error_string(err).c_str() << nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
219
src/OpenFOAM/primitives/strings/regex/regExpCxx.H
Normal file
219
src/OpenFOAM/primitives/strings/regex/regExpCxx.H
Normal file
@ -0,0 +1,219 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017-2019 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::regExpCxx
|
||||
|
||||
Description
|
||||
Wrapper around C++11 regular expressions.
|
||||
|
||||
Using either POSIX extended regular expressions or
|
||||
<a href=
|
||||
"http://www.cplusplus.com/reference/regex/ECMAScript"
|
||||
>modified ECMAScript regular expression grammar</a>
|
||||
|
||||
Since ECMAScript grammar may not work correctly on all installations,
|
||||
the current default is to use extended regular expressions.
|
||||
|
||||
The JAVA/PCRE '(?i)' extension is supported as a prefix to compile the
|
||||
regular expression as being case-insensitive.
|
||||
|
||||
Note
|
||||
The C++11 regular expressions may be broken on some compilers.
|
||||
For example, gcc 4.8 is known to fail.
|
||||
For these systems the POSIX implementation should be used.
|
||||
|
||||
SourceFiles
|
||||
regExpCxxI.H
|
||||
regExpCxx.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef regExpCxx_H
|
||||
#define regExpCxx_H
|
||||
|
||||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class regExpCxx Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class regExpCxx
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- Regular expression (using char type)
|
||||
std::regex re_;
|
||||
|
||||
//- Track if input pattern was OK - ie, has a length
|
||||
bool ok_;
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Select grammar based on regExpCxx optimisationSwitch
|
||||
// 0 = extended, 1 = ECMAScript
|
||||
static inline std::regex::flag_type syntax();
|
||||
|
||||
public:
|
||||
|
||||
//- Type for matches
|
||||
typedef std::smatch results_type;
|
||||
|
||||
// Static Member Data
|
||||
|
||||
//- The default grammar (extended | ECMAScript).
|
||||
static int grammar;
|
||||
|
||||
|
||||
// Static Member Functions
|
||||
|
||||
//- Test if character appears to be a regular expression meta-character
|
||||
// \return true if character is one of the following:
|
||||
// - any character: '.' \n
|
||||
// - quantifiers: '*', '+', '?' \n
|
||||
// - grouping: '(', '|', ')' \n
|
||||
// - range: '[', ']' \n
|
||||
//
|
||||
// \note The presence of '{', '}' regex bounds is not considered
|
||||
inline static bool meta(const char c);
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null
|
||||
inline regExpCxx();
|
||||
|
||||
//- Copy construct
|
||||
inline regExpCxx(const regExpCxx& rgx);
|
||||
|
||||
//- Move construct
|
||||
inline regExpCxx(regExpCxx&& rgx);
|
||||
|
||||
//- Construct from character array
|
||||
inline explicit regExpCxx(const char* pattern);
|
||||
|
||||
//- Construct from string
|
||||
inline explicit regExpCxx(const std::string& pattern);
|
||||
|
||||
//- Construct from character array, optionally ignore case
|
||||
inline regExpCxx(const char* pattern, bool ignoreCase);
|
||||
|
||||
//- Construct from string, optionally ignore case
|
||||
inline regExpCxx(const std::string& pattern, bool ignoreCase);
|
||||
|
||||
|
||||
//- Destructor
|
||||
~regExpCxx() = default;
|
||||
|
||||
|
||||
// Member functions
|
||||
|
||||
// Access
|
||||
|
||||
//- Return true if expression is empty
|
||||
inline bool empty() const;
|
||||
|
||||
//- Return true if expression is non-empty
|
||||
inline bool exists() const;
|
||||
|
||||
//- The number of capture groups for a non-empty expression
|
||||
inline unsigned ngroups() const;
|
||||
|
||||
// \return True if the pattern was set with ignore-case.
|
||||
inline bool nocase() const;
|
||||
|
||||
// Editing
|
||||
|
||||
//- Clear expression.
|
||||
// \return True if expression had existed prior to the clear.
|
||||
inline bool clear();
|
||||
|
||||
//- Swap contents
|
||||
inline void swap(regExpCxx& rgx);
|
||||
|
||||
//- Compile pattern into a regular expression, optionally ignore case.
|
||||
// \return True if the pattern was compiled
|
||||
bool set(const char* pattern, bool ignoreCase=false);
|
||||
|
||||
//- Compile pattern into a regular expression, optionally ignore case.
|
||||
// \return True if the pattern was compiled
|
||||
bool set(const std::string& pattern, bool ignoreCase=false);
|
||||
|
||||
// Matching/Searching
|
||||
|
||||
//- Find position within the text.
|
||||
// \return The index where it begins or string::npos if not found
|
||||
inline std::string::size_type find(const std::string& text) const;
|
||||
|
||||
//- True if the regex matches the entire text.
|
||||
// The begin-of-line (^) and end-of-line ($) anchors are implicit
|
||||
inline bool match(const std::string& text) const;
|
||||
|
||||
//- True if the regex matches the text, set the matches.
|
||||
// The first group starts at index 1 (0 is the entire match).
|
||||
// The begin-of-line (^) and end-of-line ($) anchors are implicit
|
||||
inline bool match(const std::string& text, results_type& matches) const;
|
||||
|
||||
//- Return true if the regex was found within the text
|
||||
inline bool search(const std::string& text) const;
|
||||
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Perform match on text
|
||||
inline bool operator()(const std::string& text) const;
|
||||
|
||||
//- Copy assignment
|
||||
inline void operator=(const regExpCxx& rgx);
|
||||
|
||||
//- Move assignment
|
||||
inline void operator=(regExpCxx&& rgx);
|
||||
|
||||
//- Assign and compile pattern from a character array.
|
||||
// Matching is case sensitive.
|
||||
inline void operator=(const char* pattern);
|
||||
|
||||
//- Assign and compile pattern from string.
|
||||
// Matching is case sensitive.
|
||||
inline void operator=(const std::string& pattern);
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "regExpCxxI.H"
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
228
src/OpenFOAM/primitives/strings/regex/regExpCxxI.H
Normal file
228
src/OpenFOAM/primitives/strings/regex/regExpCxxI.H
Normal file
@ -0,0 +1,228 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2017-2019 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
inline std::regex::flag_type Foam::regExpCxx::syntax()
|
||||
{
|
||||
// 0 = extended, 1 = ECMAScript
|
||||
return
|
||||
(
|
||||
regExpCxx::grammar
|
||||
? std::regex::ECMAScript
|
||||
: std::regex::extended
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::regExpCxx::meta(const char c)
|
||||
{
|
||||
return
|
||||
(
|
||||
(c == '.') // any character
|
||||
|| (c == '*' || c == '+' || c == '?') // quantifiers
|
||||
|| (c == '(' || c == ')' || c == '|') // grouping/branching
|
||||
|| (c == '[' || c == ']') // range
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
inline Foam::regExpCxx::regExpCxx()
|
||||
:
|
||||
re_(),
|
||||
ok_(false)
|
||||
{}
|
||||
|
||||
|
||||
inline Foam::regExpCxx::regExpCxx(const regExpCxx& rgx)
|
||||
:
|
||||
re_(rgx.re_),
|
||||
ok_(rgx.ok_)
|
||||
{}
|
||||
|
||||
|
||||
inline Foam::regExpCxx::regExpCxx(regExpCxx&& rgx)
|
||||
:
|
||||
re_(std::move(rgx.re_)),
|
||||
ok_(rgx.ok_)
|
||||
{
|
||||
rgx.ok_ = false;
|
||||
}
|
||||
|
||||
|
||||
inline Foam::regExpCxx::regExpCxx(const char* pattern)
|
||||
:
|
||||
re_(),
|
||||
ok_(false)
|
||||
{
|
||||
set(pattern, false);
|
||||
}
|
||||
|
||||
|
||||
inline Foam::regExpCxx::regExpCxx(const std::string& pattern)
|
||||
:
|
||||
re_(),
|
||||
ok_(false)
|
||||
{
|
||||
set(pattern, false);
|
||||
}
|
||||
|
||||
|
||||
inline Foam::regExpCxx::regExpCxx(const char* pattern, bool ignoreCase)
|
||||
:
|
||||
re_(),
|
||||
ok_(false)
|
||||
{
|
||||
set(pattern, ignoreCase);
|
||||
}
|
||||
|
||||
|
||||
inline Foam::regExpCxx::regExpCxx(const std::string& pattern, bool ignoreCase)
|
||||
:
|
||||
re_(),
|
||||
ok_(false)
|
||||
{
|
||||
set(pattern, ignoreCase);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
inline bool Foam::regExpCxx::empty() const
|
||||
{
|
||||
return !ok_;
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::regExpCxx::exists() const
|
||||
{
|
||||
return ok_;
|
||||
}
|
||||
|
||||
|
||||
inline unsigned Foam::regExpCxx::ngroups() const
|
||||
{
|
||||
return ok_ ? re_.mark_count() : 0;
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::regExpCxx::nocase() const
|
||||
{
|
||||
return ok_ && ((re_.flags() & std::regex::icase) == std::regex::icase);
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::regExpCxx::clear()
|
||||
{
|
||||
if (ok_)
|
||||
{
|
||||
re_.assign("");
|
||||
ok_ = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::regExpCxx::swap(regExpCxx& rgx)
|
||||
{
|
||||
re_.swap(rgx.re_);
|
||||
std::swap(ok_, rgx.ok_);
|
||||
}
|
||||
|
||||
|
||||
inline std::string::size_type Foam::regExpCxx::find(const std::string& text) const
|
||||
{
|
||||
std::smatch mat;
|
||||
if (!text.empty() && std::regex_search(text, mat, re_))
|
||||
{
|
||||
return mat.position(0);
|
||||
}
|
||||
|
||||
return std::string::npos;
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::regExpCxx::search(const std::string& text) const
|
||||
{
|
||||
return (ok_ && !text.empty() && std::regex_search(text, re_));
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::regExpCxx::match(const std::string& text) const
|
||||
{
|
||||
return (ok_ && !text.empty() && std::regex_match(text, re_));
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::regExpCxx::match
|
||||
(
|
||||
const std::string& text,
|
||||
std::smatch& matches
|
||||
) const
|
||||
{
|
||||
return std::regex_match(text, matches, re_);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
|
||||
|
||||
inline bool Foam::regExpCxx::operator()(const std::string& text) const
|
||||
{
|
||||
return match(text);
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::regExpCxx::operator=(const regExpCxx& rgx)
|
||||
{
|
||||
re_ = rgx.re_;
|
||||
ok_ = rgx.ok_;
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::regExpCxx::operator=(regExpCxx&& rgx)
|
||||
{
|
||||
clear();
|
||||
swap(rgx);
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::regExpCxx::operator=(const char* pattern)
|
||||
{
|
||||
set(pattern);
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::regExpCxx::operator=(const std::string& pattern)
|
||||
{
|
||||
set(pattern);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
Loading…
Reference in New Issue
Block a user