/*MT* MediaTomb - http://www.mediatomb.cc/ rexp.cc - this file is part of MediaTomb. Copyright (C) 2005 Gena Batyan , Sergey 'Jin' Bostandzhyan Copyright (C) 2006-2007 Gena Batyan , Sergey 'Jin' Bostandzhyan , Leonhard Wimmer MediaTomb is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. MediaTomb 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 version 2 along with MediaTomb; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. $Id: rexp.cc 1124 2007-02-17 21:49:15Z lww $ */ /// \file rexp.cc #ifdef HAVE_CONFIG_H #include "autoconfig.h" #endif #include "rexp.h" using namespace zmm; static String error_string(int code, regex_t *regex) { int size = regerror(code, regex, NULL, 0); String buf = String::allocate(size); regerror(code, regex, buf.c_str(), size); buf.setLength(size - 1); return buf; } RExp::RExp() : Object() { isCompiled = false; } RExp::~RExp() { if (isCompiled) { regfree(®ex); } } String RExp::getPattern() { return pattern; } void RExp::compile(String pattern, int flags) { int ret; flags |= REG_EXTENDED; // alsays use extended regexps this->pattern = pattern; ret = regcomp(®ex, pattern.c_str(), flags); if (ret != 0) throw _Exception(error_string(ret, ®ex)); isCompiled = true; } void RExp::compile(zmm::String pattern, const char *sflags) { int flags = 0; char *p = (char *)sflags; char c; while ((c = *p) != 0) { switch (c) { case 'i': flags |= REG_ICASE; break; case 's': flags |= REG_NEWLINE; break; default: throw _Exception(_("RExp: unknown flag: ")+ c); } p++; } compile(pattern, flags); } Ref RExp::matcher(String text, int nmatch) { return Ref(new Matcher(Ref(this), text, nmatch)); } Ref RExp::match(String text, int nmatch) { Ref m = matcher(text, nmatch); if (m->next()) return m; else return nil; } bool RExp::matches(String text) { Ref matcher(new Matcher(Ref(this), text, 0)); return matcher->next(); } Matcher::Matcher(zmm::Ref rexp, String text, int nmatch) { this->rexp = rexp; this->text = text; this->ptr = NULL; this->nmatch = nmatch++; if (this->nmatch) this->pmatch = (regmatch_t *)MALLOC(this->nmatch * sizeof(regmatch_t)); else this->pmatch = NULL; } Matcher::~Matcher() { if (pmatch) FREE(pmatch); } String Matcher::group(int i) { regmatch_t *m = pmatch + i; if (m->rm_so >= 0) return String(ptr + m->rm_so, m->rm_eo - m->rm_so); else return nil; } bool Matcher::next() { int ret; if (ptr == NULL) // first match { ptr = text.c_str(); } else { if (! *ptr) return false; ptr += pmatch->rm_eo; if (! *ptr) return false; } int flags = ((nmatch == 0) ? REG_NOSUB : 0); ret = regexec(&rexp->regex, ptr, nmatch, pmatch, flags); switch (ret) { case REG_NOMATCH: return false; case 0: return true; default: throw _Exception(error_string(ret, &rexp->regex)); } }