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