// Copyright (c) 1999-2002 David Muse
// See the COPYING file for more information
#include <rudiments/regularexpression.h>
#include <rudiments/rawbuffer.h>
#ifdef RUDIMENTS_HAS_PCRE
#include <pcre.h>
#else
#include <sys/types.h>
#include <regex.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#ifdef RUDIMENTS_HAS_PCRE
#include <rudiments/charstring.h>
#endif
#ifdef RUDIMENTS_NAMESPACE
namespace rudiments {
#endif
class regularexpressionprivate {
friend class regularexpression;
private:
#ifdef RUDIMENTS_HAS_PCRE
pcre *_expr;
pcre_extra *_extra;
#else
regex_t _expr;
#endif
#define RUDIMENTS_REGEX_MATCHES 128
int _matchcount;
const char *_str;
#ifdef RUDIMENTS_HAS_PCRE
int _matches[RUDIMENTS_REGEX_MATCHES*3];
#else
regmatch_t _matches[RUDIMENTS_REGEX_MATCHES];
#endif
};
regularexpression::regularexpression() {
regularexpressionInit();
}
regularexpression::regularexpression(const char *pattern) {
regularexpressionInit();
compile(pattern);
}
void regularexpression::regularexpressionInit() {
pvt=new regularexpressionprivate;
#ifdef RUDIMENTS_HAS_PCRE
pvt->_expr=NULL;
pvt->_extra=NULL;
#else
rawbuffer::zero(&pvt->_expr,sizeof(pvt->_expr));
#endif
pvt->_matchcount=0;
pvt->_str=NULL;
rawbuffer::zero(pvt->_matches,sizeof(pvt->_matches));
}
regularexpression::~regularexpression() {
#ifdef RUDIMENTS_HAS_PCRE
if (pvt->_expr) {
pcre_free(pvt->_expr);
}
if (pvt->_extra) {
delete pvt->_extra;
}
#else
regfree(&pvt->_expr);
#endif
delete pvt;
}
bool regularexpression::compile(const char *pattern) {
#ifdef RUDIMENTS_HAS_PCRE
if (pvt->_expr) {
pcre_free(pvt->_expr);
}
if (pvt->_extra) {
delete pvt->_extra;
pvt->_extra=NULL;
}
const char *error;
int erroroffset;
return (pvt->_expr=pcre_compile(pattern,0,&error,
&erroroffset,NULL))!=NULL;
#else
regfree(&pvt->_expr);
return !regcomp(&pvt->_expr,pattern,REG_EXTENDED);
#endif
}
bool regularexpression::study() {
#ifdef RUDIMENTS_HAS_PCRE
const char *error;
if (pvt->_extra) {
delete pvt->_extra;
}
pvt->_extra=pcre_study(pvt->_expr,0,&error);
return (!pvt->_extra && error)?false:true;
#else
return true;
#endif
}
bool regularexpression::match(const char *str) {
if (!str) {
return false;
}
#ifdef RUDIMENTS_HAS_PCRE
pvt->_str=str;
pvt->_matchcount=-1;
return (pvt->_expr &&
(pvt->_matchcount=pcre_exec(pvt->_expr,
pvt->_extra,
pvt->_str,
charstring::length(pvt->_str),
0,0,pvt->_matches,
RUDIMENTS_REGEX_MATCHES*3))>-1);
#else
pvt->_str=str;
for (int i=0; i<pvt->_matchcount; i++) {
pvt->_matches[i].rm_so=-1;
}
pvt->_matchcount=-1;
bool retval=!regexec(&pvt->_expr,pvt->_str,
RUDIMENTS_REGEX_MATCHES,pvt->_matches,0);
getSubstringCount();
return retval;
#endif
}
int regularexpression::getSubstringCount() {
#ifndef RUDIMENTS_HAS_PCRE
if (pvt->_matchcount==-1) {
for (int i=0; i<RUDIMENTS_REGEX_MATCHES; i++) {
if (pvt->_matches[i].rm_so==-1) {
pvt->_matchcount=i;
break;
}
}
}
#endif
if (pvt->_matchcount==-1) {
return 0;
}
return pvt->_matchcount;
}
int regularexpression::getSubstringStartOffset(int index) {
if (index<0 || index>pvt->_matchcount) {
return -1;
}
#ifdef RUDIMENTS_HAS_PCRE
return pvt->_matches[index*2];
#else
return pvt->_matches[index].rm_so;
#endif
}
int regularexpression::getSubstringEndOffset(int index) {
if (index<0 || index>pvt->_matchcount) {
return -1;
}
#ifdef RUDIMENTS_HAS_PCRE
return pvt->_matches[index*2+1];
#else
return pvt->_matches[index].rm_eo;
#endif
}
char *regularexpression::getSubstringStart(int index) {
int offset=getSubstringStartOffset(index);
return (offset>-1)?(const_cast<char *>(pvt->_str+offset)):NULL;
}
char *regularexpression::getSubstringEnd(int index) {
int offset=getSubstringEndOffset(index);
return (offset>-1)?(const_cast<char *>(pvt->_str+offset)):NULL;
}
bool regularexpression::match(const char *str, const char *pattern) {
regularexpression re;
return (re.compile(pattern) && re.match(str));
}
#ifdef RUDIMENTS_NAMESPACE
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1