/*************************************************************************/ /* */ /* Regexx - Regular Expressions C++ solution. */ /* */ /* http://projects.nn.com.br/ */ /* */ /* Copyright (C) 2000 Gustavo Niemeyer */ /* */ /* This library is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Library General Public */ /* License as published by the Free Software Foundation; either */ /* version 2 of the License, or (at your option) any later version. */ /* */ /* This library 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 */ /* Library General Public License for more details. */ /* */ /* You should have received a copy of the GNU Library General Public */ /* License along with this library; if not, write to the */ /* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */ /* Boston, MA 02111-1307, USA. */ /* */ /*************************************************************************/ // $Revision: 1.6 $ // $Date: 2003/10/20 12:22:38 $ #ifndef REGEXX_HH #define REGEXX_HH #include "immsconf.h" #include #include #ifdef HAVE_PCRE_PCRE_H # include #else # include #endif using std::string; using std::vector; using std::ostream; namespace regexx { class RegexxMatchAtom { public: inline RegexxMatchAtom(std::string& _str, std::string::size_type _start, std::string::size_type _length) : m_str(_str), m_start(_start), m_length(_length) {} inline RegexxMatchAtom& operator=(const RegexxMatchAtom& _rxxma) { m_str = _rxxma.m_str; m_start = _rxxma.m_start; m_length = _rxxma.m_length; return *this; } /// Retrieves the atom string. inline std::string str() const { return m_str.substr(m_start,m_length); } /// Returns the position in the original string where the atom starts. inline const std::string::size_type& start() const { return m_start; } /// Length of the atom string. inline const std::string::size_type& length() const { return m_length; } /// Operator to transform a RegexxMatchAtom into a string. inline operator std::string() const { return m_str.substr(m_start,m_length); } /// Operator to compare a RegexxMatchAtom with a string. inline bool operator==(const std::string& _s) const { return (m_str.substr(m_start,m_length)==_s); } private: std::string &m_str; std::string::size_type m_start; std::string::size_type m_length; }; #if 0 // Breaks *compilation* \w g++ 3.2.3 and -O3 inline ostream& operator<<(ostream& _o, RegexxMatchAtom& _rxxma) { return _o << _rxxma.str(); } #endif class RegexxMatch { public: inline RegexxMatch(std::string& _str, std::string::size_type _start, std::string::size_type _length) : m_str(_str), m_start(_start), m_length(_length) {} inline RegexxMatch& operator=(const RegexxMatch& _rxxm) { m_str = _rxxm.m_str; m_start = _rxxm.m_start; m_length = _rxxm.m_length; return *this; } /// Retrieves the match string. inline std::string str() const { return m_str.substr(m_start,m_length); } /// Returns the position in the original string where the match starts. inline const std::string::size_type& start() const { return m_start; } /// Length of the match string. inline const std::string::size_type& length() const { return m_length; } /// Operator to transform a RegexxMatch into a string. inline operator std::string() const { return m_str.substr(m_start,m_length); } /// Operator to compare a RegexxMatch with a string. inline bool operator==(const std::string& _s) const { return (m_str.substr(m_start,m_length)==_s); } /// Vector of atoms found in this match. std::vector atom; private: std::string &m_str; std::string::size_type m_start; std::string::size_type m_length; }; #if 0 // Breaks *compilation* \w g++ 3.2.3 and -O3 inline ostream& operator<<(ostream& _o, RegexxMatch& _rxxm) { return (_o << _rxxm.str()); } #endif // The main Regexx class. class Regexx { public: /// These are the flags you can use with exec() and replace(). enum flags { /// Global searching, otherwise Regexx stops after the first match. global = 1, nocase = 2, nomatch = 4, noatom = 8, study = 16, newline = 32, notbol = 64, noteol = 128 }; class Exception { public: Exception(const std::string& _message) : m_message(_message) {} /// Method to retrieve Exception information. inline const std::string& message() { return m_message; } private: std::string m_message; }; /** This exception is thrown when there are errors while compiling * expressions. */ class CompileException : public Exception { public: CompileException(const std::string& _message) : Exception(_message) {} }; /// Constructor inline Regexx() : m_compiled(false), m_study(false), m_matches(0), m_extra(NULL) {} /// Destructor inline ~Regexx() { match.clear(); if (!m_compiled) return; free((void *)m_preg); if(m_study) free((void *)m_extra); } // Constructor with regular expression execution. inline Regexx(const std::string& _str, const std::string& _expr, int _flags = 0) throw(CompileException) : m_compiled(false), m_study(false), m_matches(0), m_extra(NULL) { exec(_str,_expr,_flags); } // Set the regular expression to use with exec() and replace(). inline Regexx& expr(const std::string& _expr); // Set the string to use with exec() and replace(). inline Regexx& str(const std::string& _str); // Execute a regular expression. const unsigned int& exec(int _flags = 0) throw(CompileException); // Execute a regular expression. inline const unsigned int& exec(const std::string& _str, const std::string& _expr, int _flags = 0) throw(CompileException); // Replace string with regular expression. const std::string& replace(const std::string& _repstr, int _flags = 0) throw(CompileException); inline const std::string& replace(const std::string& _str, const std::string& _expr, const std::string& _repstr, int _flags = 0) throw(CompileException); // Customized replace string with regular expression. inline const std::string& replacef(const std::string& _str, const std::string& _expr, std::string (*_func)(const RegexxMatch&), int _flags = 0) throw(CompileException); /** Returns the number of matches of the last exec()/replace()/replacef(). */ inline const unsigned int& matches() const { return m_matches; } inline operator unsigned int() const { return m_matches; } /// Returns the string of the last replace() or replacef(). inline operator std::string() const { return m_replaced; } // The vector of matches. std::vector match; private: bool m_compiled; bool m_study; std::string m_expr; std::string m_str; int m_capturecount; unsigned int m_matches; std::string m_replaced; const pcre* m_preg; const pcre_extra* m_extra; }; inline Regexx& Regexx::expr(const std::string& _expr) { if(m_compiled) { free((void *)m_preg); m_compiled = false; if(m_study) { free((void *)m_extra); m_study = false; m_extra = NULL; } } m_expr = _expr; return *this; } inline Regexx& Regexx::str(const std::string& _str) { m_str = _str; return *this; } inline const unsigned int& Regexx::exec(const std::string& _str, const std::string& _expr, int _flags) throw(CompileException) { str(_str); expr(_expr); return exec(_flags); } inline const std::string& Regexx::replace(const std::string& _str, const std::string& _expr, const std::string& _repstr, int _flags) throw(CompileException) { str(_str); expr(_expr); return replace(_repstr,_flags); } inline const std::string& Regexx::replacef(const std::string& _str, const std::string& _expr, std::string (*_func)(const RegexxMatch&), int _flags) throw(CompileException) { str(_str); expr(_expr); exec(_flags&~nomatch); m_replaced = m_str; std::vector::reverse_iterator m; for(m = match.rbegin(); m != match.rend(); m++) m_replaced.replace(m->start(),m->length(),_func(*m)); return m_replaced; } } #endif // REGEXX_HH