00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include "autoconfig.h"
00034 #endif
00035
00036 #include "rexp.h"
00037
00038 using namespace zmm;
00039
00040 static String error_string(int code, regex_t *regex)
00041 {
00042 int size = regerror(code, regex, NULL, 0);
00043 String buf = String::allocate(size);
00044 regerror(code, regex, buf.c_str(), size);
00045 buf.setLength(size - 1);
00046 return buf;
00047 }
00048
00049 RExp::RExp() : Object()
00050 {
00051 isCompiled = false;
00052 }
00053 RExp::~RExp()
00054 {
00055 if (isCompiled)
00056 {
00057 regfree(®ex);
00058 }
00059 }
00060 String RExp::getPattern()
00061 {
00062 return pattern;
00063 }
00064 void RExp::compile(String pattern, int flags)
00065 {
00066 int ret;
00067 flags |= REG_EXTENDED;
00068 this->pattern = pattern;
00069 ret = regcomp(®ex, pattern.c_str(), flags);
00070 if (ret != 0)
00071 throw _Exception(error_string(ret, ®ex));
00072 isCompiled = true;
00073 }
00074
00075 void RExp::compile(zmm::String pattern, const char *sflags)
00076 {
00077 int flags = 0;
00078 char *p = (char *)sflags;
00079 char c;
00080 while ((c = *p) != 0)
00081 {
00082 switch (c)
00083 {
00084 case 'i': flags |= REG_ICASE; break;
00085 case 's': flags |= REG_NEWLINE; break;
00086 default: throw _Exception(_("RExp: unknown flag: ")+ c);
00087 }
00088 p++;
00089 }
00090 compile(pattern, flags);
00091 }
00092
00093 Ref<Matcher> RExp::matcher(String text, int nmatch)
00094 {
00095 return Ref<Matcher>(new Matcher(Ref<RExp>(this), text, nmatch));
00096 }
00097 Ref<Matcher> RExp::match(String text, int nmatch)
00098 {
00099 Ref<Matcher> m = matcher(text, nmatch);
00100 if (m->next())
00101 return m;
00102 else
00103 return nil;
00104 }
00105
00106 bool RExp::matches(String text)
00107 {
00108 Ref<Matcher> matcher(new Matcher(Ref<RExp>(this), text, 0));
00109 return matcher->next();
00110 }
00111
00112 Matcher::Matcher(zmm::Ref<RExp> rexp, String text, int nmatch)
00113 {
00114 this->rexp = rexp;
00115 this->text = text;
00116 this->ptr = NULL;
00117 this->nmatch = nmatch++;
00118 if (this->nmatch)
00119 this->pmatch = (regmatch_t *)MALLOC(this->nmatch * sizeof(regmatch_t));
00120 else
00121 this->pmatch = NULL;
00122 }
00123 Matcher::~Matcher()
00124 {
00125 if (pmatch)
00126 FREE(pmatch);
00127 }
00128 String Matcher::group(int i)
00129 {
00130 regmatch_t *m = pmatch + i;
00131 if (m->rm_so >= 0)
00132 return String(ptr + m->rm_so, m->rm_eo - m->rm_so);
00133 else
00134 return nil;
00135 }
00136 bool Matcher::next()
00137 {
00138 int ret;
00139
00140 if (ptr == NULL)
00141 {
00142 ptr = text.c_str();
00143 }
00144 else
00145 {
00146 if (! *ptr)
00147 return false;
00148 ptr += pmatch->rm_eo;
00149 if (! *ptr)
00150 return false;
00151 }
00152
00153 int flags = ((nmatch == 0) ? REG_NOSUB : 0);
00154 ret = regexec(&rexp->regex, ptr, nmatch, pmatch, flags);
00155 switch (ret)
00156 {
00157 case REG_NOMATCH:
00158 return false;
00159 case 0:
00160 return true;
00161 default:
00162 throw _Exception(error_string(ret, &rexp->regex));
00163 }
00164 }