KWSys 2017-12-05 (9376537e)

Code extracted from:

    https://gitlab.kitware.com/utils/kwsys.git

at commit 9376537ec0e4770a28f4b1705cfacf79650f71b6 (master).

Upstream Shortlog
-----------------

Brad King (1):
      e9557f37 RegularExpression: Fix regression in 'find' method

Sebastian Holtermann (4):
      4d1e8738 RegularExpression: Make compile() reentrant (thread safe)
      64f80068 RegularExpression: Make find() reentrant (thread safe)
      bbc94ba8 RegularExpression: Remove unused code
      cff58f07 RegularExpression: New RegularExpressionMatch class
This commit is contained in:
KWSys Upstream
2017-12-05 11:30:36 -05:00
committed by Brad King
parent 740ccb1f1d
commit 52a5c4a877
2 changed files with 274 additions and 146 deletions

View File

@@ -45,9 +45,9 @@ RegularExpression::RegularExpression(const RegularExpression& rxp)
this->program = new char[this->progsize]; // Allocate storage this->program = new char[this->progsize]; // Allocate storage
for (ind = this->progsize; ind-- != 0;) // Copy regular expresion for (ind = this->progsize; ind-- != 0;) // Copy regular expresion
this->program[ind] = rxp.program[ind]; this->program[ind] = rxp.program[ind];
this->startp[0] = rxp.startp[0]; // Copy pointers into last // Copy pointers into last successful "find" operation
this->endp[0] = rxp.endp[0]; // Successful "find" operation this->regmatch = rxp.regmatch;
this->regmust = rxp.regmust; // Copy field this->regmust = rxp.regmust; // Copy field
if (rxp.regmust != 0) { if (rxp.regmust != 0) {
char* dum = rxp.program; char* dum = rxp.program;
ind = 0; ind = 0;
@@ -78,9 +78,9 @@ RegularExpression& RegularExpression::operator=(const RegularExpression& rxp)
this->program = new char[this->progsize]; // Allocate storage this->program = new char[this->progsize]; // Allocate storage
for (ind = this->progsize; ind-- != 0;) // Copy regular expresion for (ind = this->progsize; ind-- != 0;) // Copy regular expresion
this->program[ind] = rxp.program[ind]; this->program[ind] = rxp.program[ind];
this->startp[0] = rxp.startp[0]; // Copy pointers into last // Copy pointers into last successful "find" operation
this->endp[0] = rxp.endp[0]; // Successful "find" operation this->regmatch = rxp.regmatch;
this->regmust = rxp.regmust; // Copy field this->regmust = rxp.regmust; // Copy field
if (rxp.regmust != 0) { if (rxp.regmust != 0) {
char* dum = rxp.program; char* dum = rxp.program;
ind = 0; ind = 0;
@@ -123,8 +123,9 @@ bool RegularExpression::deep_equal(const RegularExpression& rxp) const
while (ind-- != 0) // Else while still characters while (ind-- != 0) // Else while still characters
if (this->program[ind] != rxp.program[ind]) // If regexp are different if (this->program[ind] != rxp.program[ind]) // If regexp are different
return false; // Return failure return false; // Return failure
return (this->startp[0] == rxp.startp[0] && // Else if same start/end ptrs, // Else if same start/end ptrs, return true
this->endp[0] == rxp.endp[0]); // Return true return (this->regmatch.start() == rxp.regmatch.start() &&
this->regmatch.end() == rxp.regmatch.end());
} }
// The remaining code in this file is derived from the regular expression code // The remaining code in this file is derived from the regular expression code
@@ -276,31 +277,35 @@ const unsigned char MAGIC = 0234;
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
/* /*
* Global work variables for compile(). * Read only utility variables.
*/ */
static const char* regparse; // Input-scan pointer.
static int regnpar; // () count.
static char regdummy; static char regdummy;
static char* regcode; // Code-emit pointer; &regdummy = don't. static char* const regdummyptr = &regdummy;
static long regsize; // Code size.
/* /*
* Forward declarations for compile()'s friends. * Utility class for RegularExpression::compile().
*/ */
// #ifndef static class RegExpCompile
// #define static static {
// #endif public:
static char* reg(int, int*); const char* regparse; // Input-scan pointer.
static char* regbranch(int*); int regnpar; // () count.
static char* regpiece(int*); char* regcode; // Code-emit pointer; regdummyptr = don't.
static char* regatom(int*); long regsize; // Code size.
static char* regnode(char);
char* reg(int, int*);
char* regbranch(int*);
char* regpiece(int*);
char* regatom(int*);
char* regnode(char);
void regc(char);
void reginsert(char, char*);
static void regtail(char*, const char*);
static void regoptail(char*, const char*);
};
static const char* regnext(const char*); static const char* regnext(const char*);
static char* regnext(char*); static char* regnext(char*);
static void regc(char);
static void reginsert(char, char*);
static void regtail(char*, const char*);
static void regoptail(char*, const char*);
#ifdef STRCSPN #ifdef STRCSPN
static int strcspn(); static int strcspn();
@@ -337,19 +342,20 @@ bool RegularExpression::compile(const char* exp)
} }
// First pass: determine size, legality. // First pass: determine size, legality.
regparse = exp; RegExpCompile comp;
regnpar = 1; comp.regparse = exp;
regsize = 0L; comp.regnpar = 1;
regcode = &regdummy; comp.regsize = 0L;
regc(static_cast<char>(MAGIC)); comp.regcode = regdummyptr;
if (!reg(0, &flags)) { comp.regc(static_cast<char>(MAGIC));
if (!comp.reg(0, &flags)) {
printf("RegularExpression::compile(): Error in compile.\n"); printf("RegularExpression::compile(): Error in compile.\n");
return false; return false;
} }
this->startp[0] = this->endp[0] = this->searchstring = 0; this->regmatch.clear();
// Small enough for pointer-storage convention? // Small enough for pointer-storage convention?
if (regsize >= 32767L) { // Probably could be 65535L. if (comp.regsize >= 32767L) { // Probably could be 65535L.
// RAISE Error, SYM(RegularExpression), SYM(Expr_Too_Big), // RAISE Error, SYM(RegularExpression), SYM(Expr_Too_Big),
printf("RegularExpression::compile(): Expression too big.\n"); printf("RegularExpression::compile(): Expression too big.\n");
return false; return false;
@@ -360,8 +366,8 @@ bool RegularExpression::compile(const char* exp)
if (this->program != 0) if (this->program != 0)
delete[] this->program; delete[] this->program;
//#endif //#endif
this->program = new char[regsize]; this->program = new char[comp.regsize];
this->progsize = static_cast<int>(regsize); this->progsize = static_cast<int>(comp.regsize);
if (this->program == 0) { if (this->program == 0) {
// RAISE Error, SYM(RegularExpression), SYM(Out_Of_Memory), // RAISE Error, SYM(RegularExpression), SYM(Out_Of_Memory),
@@ -370,11 +376,11 @@ bool RegularExpression::compile(const char* exp)
} }
// Second pass: emit code. // Second pass: emit code.
regparse = exp; comp.regparse = exp;
regnpar = 1; comp.regnpar = 1;
regcode = this->program; comp.regcode = this->program;
regc(static_cast<char>(MAGIC)); comp.regc(static_cast<char>(MAGIC));
reg(0, &flags); comp.reg(0, &flags);
// Dig out information for optimizations. // Dig out information for optimizations.
this->regstart = '\0'; // Worst-case defaults. this->regstart = '\0'; // Worst-case defaults.
@@ -423,7 +429,7 @@ bool RegularExpression::compile(const char* exp)
* is a trifle forced, but the need to tie the tails of the branches to what * is a trifle forced, but the need to tie the tails of the branches to what
* follows makes it hard to avoid. * follows makes it hard to avoid.
*/ */
static char* reg(int paren, int* flagp) char* RegExpCompile::reg(int paren, int* flagp)
{ {
char* ret; char* ret;
char* br; char* br;
@@ -435,7 +441,7 @@ static char* reg(int paren, int* flagp)
// Make an OPEN node, if parenthesized. // Make an OPEN node, if parenthesized.
if (paren) { if (paren) {
if (regnpar >= RegularExpression::NSUBEXP) { if (regnpar >= RegularExpressionMatch::NSUBEXP) {
// RAISE Error, SYM(RegularExpression), SYM(Too_Many_Parens), // RAISE Error, SYM(RegularExpression), SYM(Too_Many_Parens),
printf("RegularExpression::compile(): Too many parentheses.\n"); printf("RegularExpression::compile(): Too many parentheses.\n");
return 0; return 0;
@@ -501,7 +507,7 @@ static char* reg(int paren, int* flagp)
* *
* Implements the concatenation operator. * Implements the concatenation operator.
*/ */
static char* regbranch(int* flagp) char* RegExpCompile::regbranch(int* flagp)
{ {
char* ret; char* ret;
char* chain; char* chain;
@@ -538,7 +544,7 @@ static char* regbranch(int* flagp)
* It might seem that this node could be dispensed with entirely, but the * It might seem that this node could be dispensed with entirely, but the
* endmarker role is not redundant. * endmarker role is not redundant.
*/ */
static char* regpiece(int* flagp) char* RegExpCompile::regpiece(int* flagp)
{ {
char* ret; char* ret;
char op; char op;
@@ -605,7 +611,7 @@ static char* regpiece(int* flagp)
* faster to run. Backslashed characters are exceptions, each becoming a * faster to run. Backslashed characters are exceptions, each becoming a
* separate node; the code is simpler that way and it's not worth fixing. * separate node; the code is simpler that way and it's not worth fixing.
*/ */
static char* regatom(int* flagp) char* RegExpCompile::regatom(int* flagp)
{ {
char* ret; char* ret;
int flags; int flags;
@@ -724,13 +730,13 @@ static char* regatom(int* flagp)
- regnode - emit a node - regnode - emit a node
Location. Location.
*/ */
static char* regnode(char op) char* RegExpCompile::regnode(char op)
{ {
char* ret; char* ret;
char* ptr; char* ptr;
ret = regcode; ret = regcode;
if (ret == &regdummy) { if (ret == regdummyptr) {
regsize += 3; regsize += 3;
return (ret); return (ret);
} }
@@ -747,9 +753,9 @@ static char* regnode(char op)
/* /*
- regc - emit (if appropriate) a byte of code - regc - emit (if appropriate) a byte of code
*/ */
static void regc(char b) void RegExpCompile::regc(char b)
{ {
if (regcode != &regdummy) if (regcode != regdummyptr)
*regcode++ = b; *regcode++ = b;
else else
regsize++; regsize++;
@@ -760,13 +766,13 @@ static void regc(char b)
* *
* Means relocating the operand. * Means relocating the operand.
*/ */
static void reginsert(char op, char* opnd) void RegExpCompile::reginsert(char op, char* opnd)
{ {
char* src; char* src;
char* dst; char* dst;
char* place; char* place;
if (regcode == &regdummy) { if (regcode == regdummyptr) {
regsize += 3; regsize += 3;
return; return;
} }
@@ -786,13 +792,13 @@ static void reginsert(char op, char* opnd)
/* /*
- regtail - set the next-pointer at the end of a node chain - regtail - set the next-pointer at the end of a node chain
*/ */
static void regtail(char* p, const char* val) void RegExpCompile::regtail(char* p, const char* val)
{ {
char* scan; char* scan;
char* temp; char* temp;
int offset; int offset;
if (p == &regdummy) if (p == regdummyptr)
return; return;
// Find last node. // Find last node.
@@ -815,10 +821,10 @@ static void regtail(char* p, const char* val)
/* /*
- regoptail - regtail on operand of first argument; nop if operandless - regoptail - regtail on operand of first argument; nop if operandless
*/ */
static void regoptail(char* p, const char* val) void RegExpCompile::regoptail(char* p, const char* val)
{ {
// "Operandless" and "op != BRANCH" are synonymous in practice. // "Operandless" and "op != BRANCH" are synonymous in practice.
if (p == 0 || p == &regdummy || OP(p) != BRANCH) if (p == 0 || p == regdummyptr || OP(p) != BRANCH)
return; return;
regtail(OPERAND(p), val); regtail(OPERAND(p), val);
} }
@@ -830,34 +836,30 @@ static void regoptail(char* p, const char* val)
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
/* /*
* Global work variables for find(). * Utility class for RegularExpression::find().
*/ */
static const char* reginput; // String-input pointer. class RegExpFind
static const char* regbol; // Beginning of input, for ^ check. {
static const char** regstartp; // Pointer to startp array. public:
static const char** regendp; // Ditto for endp. const char* reginput; // String-input pointer.
const char* regbol; // Beginning of input, for ^ check.
const char** regstartp; // Pointer to startp array.
const char** regendp; // Ditto for endp.
/* int regtry(const char*, const char**, const char**, const char*);
* Forwards. int regmatch(const char*);
*/ int regrepeat(const char*);
static int regtry(const char*, const char**, const char**, const char*); };
static int regmatch(const char*);
static int regrepeat(const char*);
#ifdef DEBUG
int regnarrate = 0;
void regdump();
static char* regprop();
#endif
// find -- Matches the regular expression to the given string. // find -- Matches the regular expression to the given string.
// Returns true if found, and sets start and end indexes accordingly. // Returns true if found, and sets start and end indexes accordingly.
bool RegularExpression::find(char const* string,
bool RegularExpression::find(const char* string) RegularExpressionMatch& rmatch) const
{ {
const char* s; const char* s;
this->searchstring = string; rmatch.clear();
rmatch.searchstring = string;
if (!this->program) { if (!this->program) {
return false; return false;
@@ -868,7 +870,7 @@ bool RegularExpression::find(const char* string)
// RAISE Error, SYM(RegularExpression), SYM(Internal_Error), // RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
printf( printf(
"RegularExpression::find(): Compiled regular expression corrupted.\n"); "RegularExpression::find(): Compiled regular expression corrupted.\n");
return 0; return false;
} }
// If there is a "must appear" string, look for it. // If there is a "must appear" string, look for it.
@@ -880,42 +882,45 @@ bool RegularExpression::find(const char* string)
s++; s++;
} }
if (s == 0) // Not present. if (s == 0) // Not present.
return (0); return false;
} }
RegExpFind regFind;
// Mark beginning of line for ^ . // Mark beginning of line for ^ .
regbol = string; regFind.regbol = string;
// Simplest case: anchored match need be tried only once. // Simplest case: anchored match need be tried only once.
if (this->reganch) if (this->reganch)
return (regtry(string, this->startp, this->endp, this->program) != 0); return (
regFind.regtry(string, rmatch.startp, rmatch.endp, this->program) != 0);
// Messy cases: unanchored match. // Messy cases: unanchored match.
s = string; s = string;
if (this->regstart != '\0') if (this->regstart != '\0')
// We know what char it must start with. // We know what char it must start with.
while ((s = strchr(s, this->regstart)) != 0) { while ((s = strchr(s, this->regstart)) != 0) {
if (regtry(s, this->startp, this->endp, this->program)) if (regFind.regtry(s, rmatch.startp, rmatch.endp, this->program))
return (1); return true;
s++; s++;
} }
else else
// We don't -- general case. // We don't -- general case.
do { do {
if (regtry(s, this->startp, this->endp, this->program)) if (regFind.regtry(s, rmatch.startp, rmatch.endp, this->program))
return (1); return true;
} while (*s++ != '\0'); } while (*s++ != '\0');
// Failure. // Failure.
return (0); return false;
} }
/* /*
- regtry - try match at specific point - regtry - try match at specific point
0 failure, 1 success 0 failure, 1 success
*/ */
static int regtry(const char* string, const char** start, const char** end, int RegExpFind::regtry(const char* string, const char** start,
const char* prog) const char** end, const char* prog)
{ {
int i; int i;
const char** sp1; const char** sp1;
@@ -927,7 +932,7 @@ static int regtry(const char* string, const char** start, const char** end,
sp1 = start; sp1 = start;
ep = end; ep = end;
for (i = RegularExpression::NSUBEXP; i > 0; i--) { for (i = RegularExpressionMatch::NSUBEXP; i > 0; i--) {
*sp1++ = 0; *sp1++ = 0;
*ep++ = 0; *ep++ = 0;
} }
@@ -950,7 +955,7 @@ static int regtry(const char* string, const char** start, const char** end,
* by recursion. * by recursion.
* 0 failure, 1 success * 0 failure, 1 success
*/ */
static int regmatch(const char* prog) int RegExpFind::regmatch(const char* prog)
{ {
const char* scan; // Current node. const char* scan; // Current node.
const char* next; // Next node. const char* next; // Next node.
@@ -1129,7 +1134,7 @@ static int regmatch(const char* prog)
/* /*
- regrepeat - repeatedly match something simple, report how many - regrepeat - repeatedly match something simple, report how many
*/ */
static int regrepeat(const char* p) int RegExpFind::regrepeat(const char* p)
{ {
int count = 0; int count = 0;
const char* scan; const char* scan;
@@ -1176,7 +1181,7 @@ static const char* regnext(const char* p)
{ {
int offset; int offset;
if (p == &regdummy) if (p == regdummyptr)
return (0); return (0);
offset = NEXT(p); offset = NEXT(p);
@@ -1193,7 +1198,7 @@ static char* regnext(char* p)
{ {
int offset; int offset;
if (p == &regdummy) if (p == regdummyptr)
return (0); return (0);
offset = NEXT(p); offset = NEXT(p);

View File

@@ -34,6 +34,115 @@
namespace @KWSYS_NAMESPACE@ { namespace @KWSYS_NAMESPACE@ {
// Forward declaration
class RegularExpression;
/** \class RegularExpressionMatch
* \brief Stores the pattern matches of a RegularExpression
*/
class @KWSYS_NAMESPACE@_EXPORT RegularExpressionMatch
{
public:
RegularExpressionMatch();
bool isValid() const;
void clear();
std::string::size_type start() const;
std::string::size_type end() const;
std::string::size_type start(int n) const;
std::string::size_type end(int n) const;
std::string match(int n) const;
enum
{
NSUBEXP = 10
};
private:
friend class RegularExpression;
const char* startp[NSUBEXP];
const char* endp[NSUBEXP];
const char* searchstring;
};
/**
* \brief Creates an invalid match object
*/
inline RegularExpressionMatch::RegularExpressionMatch()
{
startp[0] = 0;
endp[0] = 0;
searchstring = 0;
}
/**
* \brief Returns true if the match pointers are valid
*/
inline bool RegularExpressionMatch::isValid() const
{
return (this->startp[0] != 0);
}
/**
* \brief Resets to the (invalid) construction state.
*/
inline void RegularExpressionMatch::clear()
{
startp[0] = 0;
endp[0] = 0;
searchstring = 0;
}
/**
* \brief Returns the start index of the full match.
*/
inline std::string::size_type RegularExpressionMatch::start() const
{
return static_cast<std::string::size_type>(this->startp[0] - searchstring);
}
/**
* \brief Returns the end index of the full match.
*/
inline std::string::size_type RegularExpressionMatch::end() const
{
return static_cast<std::string::size_type>(this->endp[0] - searchstring);
}
/**
* \brief Returns the start index of nth submatch.
* start(0) is the start of the full match.
*/
inline std::string::size_type RegularExpressionMatch::start(int n) const
{
return static_cast<std::string::size_type>(this->startp[n] -
this->searchstring);
}
/**
* \brief Returns the end index of nth submatch.
* end(0) is the end of the full match.
*/
inline std::string::size_type RegularExpressionMatch::end(int n) const
{
return static_cast<std::string::size_type>(this->endp[n] -
this->searchstring);
}
/**
* \brief Returns the nth submatch as a string.
*/
inline std::string RegularExpressionMatch::match(int n) const
{
if (this->startp[n] == 0) {
return std::string();
} else {
return std::string(this->startp[n], static_cast<std::string::size_type>(
this->endp[n] - this->startp[n]));
}
}
/** \class RegularExpression /** \class RegularExpression
* \brief Implements pattern matching with regular expressions. * \brief Implements pattern matching with regular expressions.
* *
@@ -170,6 +279,9 @@ namespace @KWSYS_NAMESPACE@ {
* the same as the two characters before the first p encounterd in * the same as the two characters before the first p encounterd in
* the line. It would match "drepa qrepb" in "rep drepa qrepb". * the line. It would match "drepa qrepb" in "rep drepa qrepb".
* *
* All methods of RegularExpression can be called simultaneously from
* different threads but only if each invocation uses an own instance of
* RegularExpression.
*/ */
class @KWSYS_NAMESPACE@_EXPORT RegularExpression class @KWSYS_NAMESPACE@_EXPORT RegularExpression
{ {
@@ -211,11 +323,21 @@ public:
*/ */
inline bool compile(std::string const&); inline bool compile(std::string const&);
/**
* Matches the regular expression to the given string.
* Returns true if found, and sets start and end indexes
* in the RegularExpressionMatch instance accordingly.
*
* This method is thread safe when called with different
* RegularExpressionMatch instances.
*/
bool find(char const*, RegularExpressionMatch&) const;
/** /**
* Matches the regular expression to the given string. * Matches the regular expression to the given string.
* Returns true if found, and sets start and end indexes accordingly. * Returns true if found, and sets start and end indexes accordingly.
*/ */
bool find(char const*); inline bool find(char const*);
/** /**
* Matches the regular expression to the given std string. * Matches the regular expression to the given std string.
@@ -224,14 +346,18 @@ public:
inline bool find(std::string const&); inline bool find(std::string const&);
/** /**
* Index to start of first find. * Match indices
*/ */
inline RegularExpressionMatch const& regMatch() const;
inline std::string::size_type start() const; inline std::string::size_type start() const;
inline std::string::size_type end() const;
inline std::string::size_type start(int n) const;
inline std::string::size_type end(int n) const;
/** /**
* Index to end of first find. * Match strings
*/ */
inline std::string::size_type end() const; inline std::string match(int n) const;
/** /**
* Copy the given regular expression. * Copy the given regular expression.
@@ -266,29 +392,14 @@ public:
*/ */
inline void set_invalid(); inline void set_invalid();
/**
* Destructor.
*/
// awf added
std::string::size_type start(int n) const;
std::string::size_type end(int n) const;
std::string match(int n) const;
enum
{
NSUBEXP = 10
};
private: private:
const char* startp[NSUBEXP]; RegularExpressionMatch regmatch;
const char* endp[NSUBEXP];
char regstart; // Internal use only char regstart; // Internal use only
char reganch; // Internal use only char reganch; // Internal use only
const char* regmust; // Internal use only const char* regmust; // Internal use only
std::string::size_type regmlen; // Internal use only std::string::size_type regmlen; // Internal use only
char* program; char* program;
int progsize; int progsize;
const char* searchstring;
}; };
/** /**
@@ -340,6 +451,15 @@ inline bool RegularExpression::compile(std::string const& s)
return this->compile(s.c_str()); return this->compile(s.c_str());
} }
/**
* Matches the regular expression to the given std string.
* Returns true if found, and sets start and end indexes accordingly.
*/
inline bool RegularExpression::find(const char* s)
{
return this->find(s, this->regmatch);
}
/** /**
* Matches the regular expression to the given std string. * Matches the regular expression to the given std string.
* Returns true if found, and sets start and end indexes accordingly. * Returns true if found, and sets start and end indexes accordingly.
@@ -350,19 +470,51 @@ inline bool RegularExpression::find(std::string const& s)
} }
/** /**
* Set the start position for the regular expression. * Returns the internal match object
*/ */
inline std::string::size_type RegularExpression::start() const inline RegularExpressionMatch const& RegularExpression::regMatch() const
{ {
return static_cast<std::string::size_type>(this->startp[0] - searchstring); return this->regmatch;
} }
/** /**
* Returns the start/end index of the last item found. * Returns the start index of the full match.
*/
inline std::string::size_type RegularExpression::start() const
{
return regmatch.start();
}
/**
* Returns the end index of the full match.
*/ */
inline std::string::size_type RegularExpression::end() const inline std::string::size_type RegularExpression::end() const
{ {
return static_cast<std::string::size_type>(this->endp[0] - searchstring); return regmatch.end();
}
/**
* Return start index of nth submatch. start(0) is the start of the full match.
*/
inline std::string::size_type RegularExpression::start(int n) const
{
return regmatch.start(n);
}
/**
* Return end index of nth submatch. end(0) is the end of the full match.
*/
inline std::string::size_type RegularExpression::end(int n) const
{
return regmatch.end(n);
}
/**
* Return nth submatch as a string.
*/
inline std::string RegularExpression::match(int n) const
{
return regmatch.match(n);
} }
/** /**
@@ -391,35 +543,6 @@ inline void RegularExpression::set_invalid()
this->program = 0; this->program = 0;
} }
/**
* Return start index of nth submatch. start(0) is the start of the full match.
*/
inline std::string::size_type RegularExpression::start(int n) const
{
return static_cast<std::string::size_type>(this->startp[n] - searchstring);
}
/**
* Return end index of nth submatch. end(0) is the end of the full match.
*/
inline std::string::size_type RegularExpression::end(int n) const
{
return static_cast<std::string::size_type>(this->endp[n] - searchstring);
}
/**
* Return nth submatch as a string.
*/
inline std::string RegularExpression::match(int n) const
{
if (this->startp[n] == 0) {
return std::string("");
} else {
return std::string(this->startp[n], static_cast<std::string::size_type>(
this->endp[n] - this->startp[n]));
}
}
} // namespace @KWSYS_NAMESPACE@ } // namespace @KWSYS_NAMESPACE@
#endif #endif