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