/** * @file op_regex.h * This file contains various definitions and interface for a * lightweight wrapper around libc regex, providing match * and replace facility. * * @remark Copyright 2003 OProfile authors * @remark Read the file COPYING * @remark Idea comes from TextFilt project <http://textfilt.sourceforge.net> * * @author Philippe Elie */ #ifndef OP_REGEX_H #define OP_REGEX_H // required by posix before including regex.h #include <sys/types.h> #include <regex.h> #include <string> #include <vector> #include <map> #include "op_exception.h" /** * ill formed regular expression or expression throw such exception */ struct bad_regex : op_exception { bad_regex(std::string const & pattern); }; /** * lightweight encapsulation of regex lib search and replace * * See stl.pat for further details and examples of used syntax. */ class regular_expression_replace { public: /** * @param limit limit on number of search and replace done * @param limit_defs_expansion limit on number of expansion done * during replacement of regular definition name by their expansion * * build an object holding regular defintion and regular expression * & replace, preparing it for substitution ala sed */ regular_expression_replace(size_t limit = 100, size_t limit_defs_expansion = 100); ~regular_expression_replace(); /** * @param name a regular definition name * @param replace the string to subsitute in other regular definition * or regular exepression when this regular defintion name is * encoutered. */ void add_definition(std::string const & name, std::string const & replace); /** * @param pattern a regular expression pattern, POSIX extended notation * @param replace the replace string to use when this regular * expression is matched * * You can imbed regular definition in pattern but not in replace. */ void add_pattern(std::string const & pattern, std::string const & replace); /** * @param str the input/output string where we search pattern and * replace them. * * Execute loop at max limit time on the set of regular expression * * Return true if too many match occur and replacing has been stopped * due to reach limit_defs_expansion. You can test if some pattern has * been matched by saving the input string and comparing it to the new * value. There is no way to detect s/a/a because the output string * will be identical to the input string. */ bool execute(std::string & str) const; private: struct replace_t { // when this regexp is matched regex_t regexp; // replace the matched part with this string std::string replace; }; // helper to execute bool do_execute(std::string & str, replace_t const & regexp) const; void do_replace(std::string & str, std::string const & replace, regmatch_t const * match) const; // helper to add_definition() and add_pattern() std::string expand_string(std::string const & input); // helper to add_pattern std::string substitute_definition(std::string const & pattern); // return the match of throw if idx is invalid regmatch_t const & get_match(regmatch_t const * match, char idx) const; // don't increase too, it have direct impact on performance. This limit // the number of grouping expression allowed in a regular expression // Note than you can use grouping match operator > 9 only in the // replace rule not in match regular expression since POSIX don't allow // more than \9 in matching sequence. static const size_t max_match = 16; size_t limit; size_t limit_defs_expansion; std::vector<replace_t> regex_replace; /// dictionary of regular definition typedef std::map<std::string, std::string> defs_dict; defs_dict defs; }; /** * @param regex the regular_expression_replace to fill * @param filename the filename from where the deifnition and pattern are read * * add to regex pattern and regular definition read from the given file */ void setup_regex(regular_expression_replace& regex, std::string const & filename); #endif /* !OP_REGEX_H */