Apply the new ground_level method.
[crawl.git] / crawl-ref / source / pattern.h
blob8c55785ef7e30596a65a18c4be089489e6361a0d
1 #ifndef PATTERN_H
2 #define PATTERN_H
4 #ifdef REGEX_PCRE
5 // Statically link pcre on Windows
6 #if defined(TARGET_OS_WINDOWS) || defined(TARGET_OS_DOS)
7 #define PCRE_STATIC
8 #endif
10 #include <pcre.h>
11 #endif
13 #ifdef REGEX_POSIX
14 // Do we still need to include sys/types.h?
15 #include <sys/types.h>
16 #include <regex.h>
17 #endif
19 // Pattern matching
20 void *compile_pattern(const char *pattern, bool ignore_case = false);
21 void free_compiled_pattern(void *cp);
22 bool pattern_match(void *compiled_pattern, const char *text, int length);
24 // Globs are always available.
25 void *compile_glob_pattern(const char *pattern, bool ignore_case = false);
26 void free_compiled_glob_pattern(void *cp);
27 bool glob_pattern_match(void *compiled_pattern, const char *text, int length);
29 typedef void *(*p_compile)(const char *pattern, bool ignore_case);
30 typedef void (*p_free)(void *cp);
31 typedef bool (*p_match)(void *compiled_pattern, const char *text, int length);
33 class base_pattern
35 public:
36 virtual ~base_pattern() { }
38 virtual bool valid() const = 0;
39 virtual bool matches(const std::string &s) const = 0;
42 template <p_compile pcomp, p_free pfree, p_match pmatch>
43 class basic_text_pattern : public base_pattern
45 public:
46 basic_text_pattern(const std::string &s, bool icase = false)
47 : pattern(s), compiled_pattern(NULL),
48 isvalid(true), ignore_case(icase)
52 basic_text_pattern()
53 : pattern(), compiled_pattern(NULL),
54 isvalid(false), ignore_case(false)
58 basic_text_pattern(const basic_text_pattern &tp)
59 : base_pattern(tp),
60 pattern(tp.pattern),
61 compiled_pattern(NULL),
62 isvalid(tp.isvalid),
63 ignore_case(tp.ignore_case)
67 ~basic_text_pattern()
69 if (compiled_pattern)
70 pfree(compiled_pattern);
73 const basic_text_pattern &operator= (const basic_text_pattern &tp)
75 if (this == &tp)
76 return tp;
78 if (compiled_pattern)
79 pfree(compiled_pattern);
80 pattern = tp.pattern;
81 compiled_pattern = NULL;
82 isvalid = tp.isvalid;
83 ignore_case = tp.ignore_case;
84 return *this;
87 const basic_text_pattern &operator= (const std::string &spattern)
89 if (pattern == spattern)
90 return *this;
92 if (compiled_pattern)
93 pfree(compiled_pattern);
94 pattern = spattern;
95 compiled_pattern = NULL;
96 isvalid = true;
97 // We don't change ignore_case
98 return *this;
101 bool compile() const
103 return !empty()?
104 !!(compiled_pattern = pcomp(pattern.c_str(), ignore_case))
105 : false;
108 bool empty() const
110 return !pattern.length();
113 bool valid() const
115 return isvalid
116 && (compiled_pattern || (isvalid = compile()));
119 bool matches(const char *s, int length) const
121 return valid() && pmatch(compiled_pattern, s, length);
124 bool matches(const char *s) const
126 return matches(std::string(s));
129 bool matches(const std::string &s) const
131 return matches(s.c_str(), s.length());
134 const std::string &tostring() const
136 return pattern;
139 private:
140 std::string pattern;
141 mutable void *compiled_pattern;
142 mutable bool isvalid;
143 bool ignore_case;
146 typedef
147 basic_text_pattern<compile_pattern,
148 free_compiled_pattern, pattern_match> text_pattern;
150 typedef
151 basic_text_pattern<compile_glob_pattern,
152 free_compiled_glob_pattern,
153 glob_pattern_match> glob_pattern;
155 #endif