00001 #ifndef PATTERN_H
00002 #define PATTERN_H
00003
00004 #ifdef REGEX_PCRE
00005
00006 #if defined(TARGET_OS_WINDOWS) || defined(TARGET_OS_DOS)
00007 #define PCRE_STATIC
00008 #endif
00009
00010 #include <pcre.h>
00011 #endif
00012
00013 #ifdef REGEX_POSIX
00014
00015 #include <sys/types.h>
00016 #include <regex.h>
00017 #endif
00018
00019
00020 void *compile_pattern(const char *pattern, bool ignore_case = false);
00021 void free_compiled_pattern(void *cp);
00022 bool pattern_match(void *compiled_pattern, const char *text, int length);
00023
00024
00025 void *compile_glob_pattern(const char *pattern, bool ignore_case = false);
00026 void free_compiled_glob_pattern(void *cp);
00027 bool glob_pattern_match(void *compiled_pattern, const char *text, int length);
00028
00029 typedef void *(*p_compile)(const char *pattern, bool ignore_case);
00030 typedef void (*p_free)(void *cp);
00031 typedef bool (*p_match)(void *compiled_pattern, const char *text, int length);
00032
00033 class base_pattern
00034 {
00035 public:
00036 virtual ~base_pattern() { }
00037
00038 virtual bool valid() const = 0;
00039 virtual bool matches(const std::string &s) const = 0;
00040 };
00041
00042 template <p_compile pcomp, p_free pfree, p_match pmatch>
00043 class basic_text_pattern : public base_pattern
00044 {
00045 public:
00046 basic_text_pattern(const std::string &s, bool icase = false)
00047 : pattern(s), compiled_pattern(NULL),
00048 isvalid(true), ignore_case(icase)
00049 {
00050 }
00051
00052 basic_text_pattern()
00053 : pattern(), compiled_pattern(NULL),
00054 isvalid(false), ignore_case(false)
00055 {
00056 }
00057
00058 basic_text_pattern(const basic_text_pattern &tp)
00059 : base_pattern(tp),
00060 pattern(tp.pattern),
00061 compiled_pattern(NULL),
00062 isvalid(tp.isvalid),
00063 ignore_case(tp.ignore_case)
00064 {
00065 }
00066
00067 ~basic_text_pattern()
00068 {
00069 if (compiled_pattern)
00070 pfree(compiled_pattern);
00071 }
00072
00073 const basic_text_pattern &operator= (const basic_text_pattern &tp)
00074 {
00075 if (this == &tp)
00076 return tp;
00077
00078 if (compiled_pattern)
00079 pfree(compiled_pattern);
00080 pattern = tp.pattern;
00081 compiled_pattern = NULL;
00082 isvalid = tp.isvalid;
00083 ignore_case = tp.ignore_case;
00084 return *this;
00085 }
00086
00087 const basic_text_pattern &operator= (const std::string &spattern)
00088 {
00089 if (pattern == spattern)
00090 return *this;
00091
00092 if (compiled_pattern)
00093 pfree(compiled_pattern);
00094 pattern = spattern;
00095 compiled_pattern = NULL;
00096 isvalid = true;
00097
00098 return *this;
00099 }
00100
00101 bool compile() const
00102 {
00103 return !empty()?
00104 !!(compiled_pattern = pcomp(pattern.c_str(), ignore_case))
00105 : false;
00106 }
00107
00108 bool empty() const
00109 {
00110 return !pattern.length();
00111 }
00112
00113 bool valid() const
00114 {
00115 return isvalid
00116 && (compiled_pattern || (isvalid = compile()));
00117 }
00118
00119 bool matches(const char *s, int length) const
00120 {
00121 return valid() && pmatch(compiled_pattern, s, length);
00122 }
00123
00124 bool matches(const char *s) const
00125 {
00126 return matches(std::string(s));
00127 }
00128
00129 bool matches(const std::string &s) const
00130 {
00131 return matches(s.c_str(), s.length());
00132 }
00133
00134 const std::string &tostring() const
00135 {
00136 return pattern;
00137 }
00138
00139 private:
00140 std::string pattern;
00141 mutable void *compiled_pattern;
00142 mutable bool isvalid;
00143 bool ignore_case;
00144 };
00145
00146 typedef
00147 basic_text_pattern<compile_pattern,
00148 free_compiled_pattern, pattern_match> text_pattern;
00149
00150 typedef
00151 basic_text_pattern<compile_glob_pattern,
00152 free_compiled_glob_pattern,
00153 glob_pattern_match> glob_pattern;
00154
00155 #endif