#include "Riostream.h"
#include "TPRegexp.h"
#include "TObjArray.h"
#include "TObjString.h"
#include "TError.h"
#include <pcre.h>
struct PCREPriv_t {
pcre *fPCRE;
pcre_extra *fPCREExtra;
PCREPriv_t() { fPCRE = 0; fPCREExtra = 0; }
};
ClassImp(TPRegexp)
TPRegexp::TPRegexp()
{
fPriv = new PCREPriv_t;
fPCREOpts = 0;
}
TPRegexp::TPRegexp(const TString &pat)
{
fPattern = pat;
fPriv = new PCREPriv_t;
fPCREOpts = 0;
}
TPRegexp::TPRegexp(const TPRegexp &p)
{
fPattern = p.fPattern;
fPriv = new PCREPriv_t;
fPCREOpts = p.fPCREOpts;
}
TPRegexp::~TPRegexp()
{
if (fPriv->fPCRE)
pcre_free(fPriv->fPCRE);
if (fPriv->fPCREExtra)
pcre_free(fPriv->fPCREExtra);
delete fPriv;
}
TPRegexp &TPRegexp::operator=(const TPRegexp &p)
{
if (this != &p) {
fPattern = p.fPattern;
if (fPriv->fPCRE)
pcre_free(fPriv->fPCRE);
fPriv->fPCRE = 0;
if (fPriv->fPCREExtra)
pcre_free(fPriv->fPCREExtra);
fPriv->fPCREExtra = 0;
fPCREOpts = p.fPCREOpts;
}
return *this;
}
UInt_t TPRegexp::ParseMods(const TString &modStr) const
{
UInt_t opts = 0;
if (modStr.Length() <= 0)
return fPCREOpts;
const char *m = modStr;
while (*m) {
switch (*m) {
case 'g':
opts |= kPCRE_GLOBAL;
break;
case 'i':
opts |= PCRE_CASELESS;
break;
case 'm':
opts |= PCRE_MULTILINE;
break;
case 'o':
opts |= kPCRE_OPTIMIZE;
break;
case 's':
opts |= PCRE_DOTALL;
break;
case 'x':
opts |= PCRE_EXTENDED;
break;
case 'd':
opts |= kPCRE_DEBUG_MSGS;
break;
default:
Error("ParseMods", "illegal pattern modifier: %c", *m);
opts = 0;
}
++m;
}
return opts;
}
void TPRegexp::Compile()
{
if (fPriv->fPCRE)
pcre_free(fPriv->fPCRE);
if (fPCREOpts & kPCRE_DEBUG_MSGS)
Info("Compile", "PREGEX compiling %s", fPattern.Data());
const char *errstr;
Int_t patIndex;
fPriv->fPCRE = pcre_compile(fPattern.Data(), fPCREOpts & kPCRE_INTMASK,
&errstr, &patIndex, 0);
if (!fPriv->fPCRE) {
Error("Compile", "compilation of TPRegexp(%s) failed at: %d because %s",
fPattern.Data(), patIndex, errstr);
}
if (fPriv->fPCREExtra || (fPCREOpts & kPCRE_OPTIMIZE))
Optimize();
}
void TPRegexp::Optimize()
{
if (fPriv->fPCREExtra)
pcre_free(fPriv->fPCREExtra);
if (fPCREOpts & kPCRE_DEBUG_MSGS)
Info("Optimize", "PREGEX studying %s", fPattern.Data());
const char *errstr;
fPriv->fPCREExtra = pcre_study(fPriv->fPCRE, fPCREOpts & kPCRE_INTMASK, &errstr);
if (!fPriv->fPCREExtra && errstr) {
Error("Optimize", "Optimization of TPRegexp(%s) failed: %s",
fPattern.Data(), errstr);
}
}
Int_t TPRegexp::ReplaceSubs(const TString &s, TString &final,
const TString &replacePattern,
Int_t *offVec, Int_t nrMatch) const
{
Int_t nrSubs = 0;
const char *p = replacePattern;
Int_t state = 0;
Int_t subnum = 0;
while (state != -1) {
switch (state) {
case 0:
if (!*p) {
state = -1;
break;
}
if (*p == '$') {
state = 1;
subnum = 0;
if (p[1] == '&') {
p++;
if (isdigit(p[1]))
p++;
} else if (!isdigit(p[1])) {
Error("ReplaceSubs", "badly formed replacement pattern: %s",
replacePattern.Data());
}
} else
final += *p;
break;
case 1:
if (isdigit(*p)) {
subnum *= 10;
subnum += (*p)-'0';
} else {
if (fPCREOpts & kPCRE_DEBUG_MSGS)
Info("ReplaceSubs", "PREGEX appending substr #%d", subnum);
if (subnum < 0 || subnum > nrMatch-1) {
Error("ReplaceSubs","bad string number :%d",subnum);
}
const TString subStr = s(offVec[2*subnum],offVec[2*subnum+1]-offVec[2*subnum]);
final += subStr;
nrSubs++;
state = 0;
continue;
}
}
p++;
}
return nrSubs;
}
Int_t TPRegexp::Match(const TString &s, const TString &mods, Int_t start,
Int_t nMaxMatch, TArrayI *pos)
{
UInt_t opts = ParseMods(mods);
if (!fPriv->fPCRE || opts != fPCREOpts) {
fPCREOpts = opts;
Compile();
}
Int_t *offVec = new Int_t[nMaxMatch];
Int_t nrMatch = pcre_exec(fPriv->fPCRE, fPriv->fPCREExtra, s.Data(),
s.Length(), start, fPCREOpts & kPCRE_INTMASK,
offVec, nMaxMatch);
if (nrMatch == PCRE_ERROR_NOMATCH)
nrMatch = 0;
else if (nrMatch <= 0) {
Error("Match","pcre_exec error = %d", nrMatch);
delete [] offVec;
return 0;
}
if (pos)
pos->Adopt(2*nrMatch, offVec);
else
delete [] offVec;
return nrMatch;
}
TObjArray *TPRegexp::MatchS(const TString &s, const TString &mods,
Int_t start, Int_t nMaxMatch)
{
TArrayI pos;
Int_t nrMatch = Match(s, mods, start, nMaxMatch, &pos);
TObjArray *subStrL = new TObjArray();
subStrL->SetOwner();
for (Int_t i = 0; i < nrMatch; i++) {
Int_t start = pos[2*i];
Int_t stop = pos[2*i+1];
if (start >= 0 && stop >= 0) {
const TString subStr = s(pos[2*i], pos[2*i+1]-pos[2*i]);
subStrL->Add(new TObjString(subStr));
} else
subStrL->Add(new TObjString());
}
return subStrL;
}
Int_t TPRegexp::Substitute(TString &s, const TString &replacePattern,
const TString &mods, Int_t start, Int_t nMaxMatch)
{
UInt_t opts = ParseMods(mods);
Int_t nrSubs = 0;
TString final;
if (!fPriv->fPCRE || opts != fPCREOpts) {
fPCREOpts = opts;
Compile();
}
Int_t *offVec = new Int_t[nMaxMatch];
Int_t offset = start;
Int_t last = 0;
while (kTRUE) {
Int_t nrMatch = pcre_exec(fPriv->fPCRE, fPriv->fPCREExtra, s.Data(),
s.Length(), offset, fPCREOpts & kPCRE_INTMASK,
offVec, nMaxMatch);
if (nrMatch == PCRE_ERROR_NOMATCH) {
nrMatch = 0;
break;
} else if (nrMatch <= 0)
Error("Substitute", "pcre_exec error = %d", nrMatch);
if (last <= offVec[0]) {
final += s(last,offVec[0]-last);
last = offVec[1];
}
nrSubs += ReplaceSubs(s, final, replacePattern, offVec, nrMatch);
if (!(fPCREOpts & kPCRE_GLOBAL))
break;
if (offVec[0] != offVec[1])
offset = offVec[1];
else {
if (offVec[1] == s.Length())
break;
offset = offVec[1]+1;
}
}
delete [] offVec;
final += s(last,s.Length()-last);
s = final;
return nrSubs;
}
Ssiz_t TString::Index(TPRegexp& r, Ssiz_t start) const
{
TArrayI pos;
Int_t nrMatch = r.Match(*this,"",start,30,&pos);
if (nrMatch > 0)
return pos[0];
else
return -1;
}
Ssiz_t TString::Index(TPRegexp& r, Ssiz_t* extent, Ssiz_t start) const
{
TArrayI pos;
const Int_t nrMatch = r.Match(*this,"",start,30,&pos);
if (nrMatch > 0) {
*extent = pos[1]-pos[0];
return pos[0];
} else {
*extent = 0;
return -1;
}
}
TSubString TString::operator()(TPRegexp& r, Ssiz_t start)
{
Ssiz_t len;
Ssiz_t begin = Index(r, &len, start);
return TSubString(*this, begin, len);
}
TSubString TString::operator()(TPRegexp& r)
{
return (*this)(r,0);
}
TSubString TString::operator()(TPRegexp& r, Ssiz_t start) const
{
Ssiz_t len;
Ssiz_t begin = Index(r, &len, start);
return TSubString(*this, begin, len);
}
TSubString TString::operator()(TPRegexp& r) const
{
return (*this)(r, 0);
}
ROOT page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.