]> git.lyx.org Git - lyx.git/blob - src/support/LRegex.C
LSubstring and LRegex added, some small cleanup in FileInfo, audited most of the...
[lyx.git] / src / support / LRegex.C
1 #ifdef __GNUG__
2 #pragma implementation
3 #endif
4
5 #include <config.h>
6
7 #include <sys/types.h>
8 #include <regex.h>
9 #include "LRegex.h"
10
11 ///
12 struct LRegex::Impl {
13         ///
14         re_pattern_buffer * preg;
15         
16         ///
17         int error_code;
18         
19         ///
20         mutable LRegex::SubMatches matches;
21         
22         ///
23         Impl(string const & regex) 
24                 : preg(new re_pattern_buffer), error_code(0)
25         {
26                 error_code = regcomp(preg, regex.c_str(), REG_EXTENDED);
27         }
28         
29         ///
30         ~Impl()
31         {
32                 regfree(preg);
33                 delete preg;
34         }
35         
36         ///
37         bool exact_match(string const & str) const
38         {
39                 regmatch_t tmp;
40                 if (!regexec(preg, str.c_str(), 1, &tmp, 0)) {
41                         if (tmp.rm_so == 0 && 
42                             tmp.rm_eo == static_cast<signed int>(str.length()))
43                                 return true;
44                 }
45                 // no match
46                 return false;
47         }
48         
49         ///
50         LRegex::MatchPair first_match(string const & str) const
51         {
52                 regmatch_t tmp;
53                 regexec(preg, str.c_str(), 1, &tmp, 0);
54                 unsigned int first = tmp.rm_so != -1 ?
55                         static_cast<unsigned int>(tmp.rm_so) : string::npos;
56                 unsigned int second = tmp.rm_eo != -1 ?
57                         static_cast<unsigned int>(tmp.rm_eo) : string::npos;
58                 return make_pair(first, second - first);
59         }
60         
61         ///
62         string getError() const
63         {
64                 size_t nr = regerror(error_code, preg, 0, 0);
65                 char * tmp = new char[nr];
66                 regerror(error_code, preg, tmp, nr);
67                 string ret(tmp);
68                 delete [] tmp;
69                 return ret;
70         }
71         
72         ///
73         LRegex::SubMatches const & exec(string const & str) const
74         {
75                 // Some room for improvement in this func. I realize
76                 // that it is double as expensive as needed, but that
77                 // is something I am willing to pay to get the nice
78                 // interface. One thing that can be done is to only put
79                 // valid submatches into matches. That will not make this
80                 // func much faster, but client code will be simpler,
81                 // because then it will only be needed to scan through
82                 // all the entries in matches.
83                 size_t subs = (preg->re_nsub != 0 ? (preg->re_nsub + 1) : 1);
84                 regmatch_t * mat = new regmatch_t[subs];
85                 unsigned int first = 0;
86                 unsigned int second = 0;
87                 matches.erase(matches.begin(), matches.end());
88                 if (!regexec(preg, str.c_str(), subs, mat, 0)) { // some match
89                         matches.reserve(subs);
90                         for (size_t i = 0; i < subs; ++i) {
91                                 first = mat[i].rm_so != -1 ?
92                                         static_cast<unsigned int>
93                                         (mat[i].rm_so) : string::npos;
94                                 second = mat[i].rm_eo != -1 ?
95                                         static_cast<unsigned int>
96                                         (mat[i].rm_eo) : string::npos;
97                                 matches.push_back(make_pair(first,
98                                                             second - first));
99                         }
100                 }
101                 delete[] mat;
102                 return matches;
103         }
104 };
105
106
107 LRegex::LRegex(string const & regex)
108         : impl(new Impl(regex)) {}
109
110
111 LRegex::~LRegex()
112 {
113         delete impl;
114 }
115
116
117 LRegex::SubMatches const & LRegex::exec(string const & str) const
118 {
119         return impl->exec(str);
120 }
121
122
123 bool LRegex::exact_match(string const & str) const
124 {
125         return impl->exact_match(str);
126 }
127
128
129 LRegex::MatchPair LRegex::first_match(string const & str) const
130 {
131         return impl->first_match(str);
132 }
133
134
135 string LRegex::getError() const
136 {
137         return impl->getError();
138 }
139
140
141 int LRegex::getErrorCode() const
142 {
143         return impl->error_code;
144 }
145
146
147 bool LRegex::ok() const {
148         return impl->error_code == 0;
149 }
150
151
152 #if 0
153 // some built in regular expressions
154
155 // this is good
156 const LRegex LRXwhite("[ \n\t\r\v\f]+");
157 // this is good
158 const LRegex LRXint("-?[0-9]+");
159 // this is good
160 const LRegex LRXdouble("-?(([0-9]+.[0-9]*)|"
161                      "([0-9]+)|(.[0-9]+))"
162                      "([eE][---+]?[0-9]+)?");
163 // not usable
164 // const LRegex LRXalpha("[A-Za-z]+");
165 // not usable (only ascii)
166 // const LRegex LRXlowercase("[a-z]+");
167 // not usable (only ascii)
168 // const LRegex LRXuppercase("[A-Z]+");
169 // not usable (only ascii)
170 // const LRegex LRXalphanum("[0-9A-Za-z]+");
171 // this is good
172 const LRegex LRXidentifier("[A-Za-z_][A-Za-z0-9_]*");
173 #endif