1 /*
2
3 Simple wildcard matching with pattern matching
4
5 copyright (c) 2004 squell <squell@alumina.nl>
6
7 use, modification, copying and distribution of this software is permitted
8 under the conditions described in the file 'COPYING'.
9
10 Usage:
11
12 Construct a varexp object using a wildcard specification and a test
13 string, and then access the matched variables (if any) using the
14 index operator. Example:
15
16 varexp v("*, *", "foo, bar")
17 v[0]; // == "foo"
18 v[1]; // == "bar"
19
20 The index operator returns a std::string. Use the cpy() member if you
21 want a copy in plain-old-C style.
22
23 In a boolean context, a varexp object converts to a boolean value which
24 holds the results of the pattern match (failed/succeed). Thus, varexp can
25 also be used like an ordinary wildcard test:
26
27 if( varexp("r*.txt", str) )
28 ... // executes if str matched "r*.txt"
29
30 Restrictions:
31
32 The result of using operator[] or cpy() is undefined if the string used
33 to generate the varexp object is changed. However, values returned before
34 the point of alteration will remain safe.
35
36 operator[] performs range checking, and throws an out_of_range exception
37 if an index is not >= 0 && < size()
38
39 cpy(), true to form, will not perform any range checking and is a
40 potential can of worms, generally. :)
41
42 The wildcard match will fail in certain cases where filenames are in a
43 multi-byte encodings that is not filesystem-safe, like EUC-JP.
44
45 */
46
47 #ifndef __ZF_VAREXP
48 #define __ZF_VAREXP
49
50 #include <cstring>
51 #include <vector>
52 #include <utility>
53 #include <string>
54 #include <stdexcept>
55 #include <iterator>
56
57 class varexp {
58 public:
varexp(const char * mask,const char * test)59 varexp(const char* mask, const char* test) : var()
60 { result = match(mask,test); };
varexp()61 varexp() : var()
62 { result = 0; }
63
64 operator bool() const
65 { return result; }
66
67 std::string operator[](std::size_t i) const;
68
size()69 std::size_t size() const
70 { return var.size(); }
71
72 char* cpy(char* dest, std::size_t i) const;
73
74 class iterator;
75 iterator begin() const;
76 iterator end() const;
77
78 protected:
79 typedef std::vector< std::pair<const char*, int> > pairvec;
80 pairvec var;
81 bool result;
82
83 bool match(const char* mask, const char* test);
84 const char* in_set(char c, const char* set);
85 friend class iterator;
86 };
87
88 inline std::string varexp::operator[](std::size_t i) const
89 {
90 if( i >= var.size() ) // bounds check
91 throw std::out_of_range("varexp: index out of range");
92
93 return std::string( var[i].first, var[i].second );
94 }
95
cpy(char * dest,std::size_t i)96 inline char* varexp::cpy(char* dest, std::size_t i) const
97 {
98 return std::strncpy(dest, var[i].first, var[i].second );
99 }
100
101 class varexp::iterator : public std::iterator_traits<pairvec::const_iterator> {
102 friend class varexp;
103 pairvec::const_iterator p;
104
iterator(const pairvec::const_iterator & _p)105 iterator(const pairvec::const_iterator& _p) : p(_p) { }
106 public:
107 std::string operator*() const { return std::string(p->first, p->second); }
108 iterator& operator++() { return ++p, *this; }
109 iterator operator++(int) { iterator tmp(*this);
110 return ++p, tmp; }
111
112 friend bool operator==(const iterator& a, const iterator& b)
113 { return a.p == b.p; }
114 friend bool operator!=(const iterator& a, const iterator& b)
115 { return a.p != b.p; }
116
117 typedef std::input_iterator_tag iterator_category;
118 typedef std::string value_type;
119 typedef const std::string* pointer;
120 typedef const std::string& reference;
121 };
122
begin()123 inline varexp::iterator varexp::begin() const
124 {
125 return iterator(var.begin());
126 }
127
end()128 inline varexp::iterator varexp::end() const
129 {
130 return iterator(var.end());
131 }
132
133 #endif
134
135