ecere/gui/Window: Prevent uninitialized values if base Window methods not overridden...
[sdk] / extras / Regex.ec
1
2 #define __restrict
3 #ifndef __restrict_arr
4 #define __restrict_arr
5 #endif
6
7 #define uint _uint
8 #ifdef __WIN32__
9 #include <sys/types.h>
10 #endif
11 #include <regex.h>
12 #undef uint
13
14 #ifdef BUILDING_ECERE_COM
15 namespace sys;
16 import "instance"
17 #else
18 #ifdef ECERE_STATIC
19 public import static "ecere"
20 #else
21 public import "ecere"
22 #endif
23 #endif
24
25 public class Regex : struct
26 {
27 public:
28    property const String regex
29    {
30       set
31       {
32          if((value || regex) && (value != regex || strcmp(value, regex)))
33          {
34             if(value)
35             {
36                delete regex;
37                regex = CopyString(value);
38                Compile();
39             }
40             else
41                Free();
42          }
43
44       }
45       get { return regex; }
46    }
47
48    property bool caseInsensitive
49    {
50       set
51       {
52          if(value != ((compileFlags & REG_ICASE) != 0))
53          {
54             value ? (compileFlags |= REG_ICASE) : (compileFlags &= ~REG_ICASE);
55             if(regex)
56                Compile();
57          }
58       }
59       get { return (compileFlags & REG_ICASE) != 0; }
60    }
61
62    property bool newLineException
63    {
64       set
65       {
66          //if(value != ((compileFlags & REG_NEWLINE) != 0))
67          if(value != ((compileFlags & REG_EXTENDED)))
68          {
69             value ? (compileFlags |= REG_NEWLINE) : (compileFlags &= ~REG_NEWLINE);
70             if(regex)
71                Compile();
72          }
73       }
74       get { return (compileFlags & REG_NEWLINE) != 0; }
75    }
76
77    property bool lineStartException
78    {
79       set
80       {
81          if(value != ((executeFlags & REG_NOTBOL) != 0))
82             value ? (executeFlags |= REG_NOTBOL) : (executeFlags &= ~REG_NOTBOL);
83       }
84       get { return (executeFlags & REG_NOTBOL) != 0; }
85    }
86
87    property bool lineEndException
88    {
89       set
90       {
91          if(value != ((executeFlags & REG_NOTEOL) != 0))
92             value ? (executeFlags |= executeFlags | REG_NOTEOL) : (executeFlags &= ~REG_NOTEOL);
93       }
94       get { return (executeFlags & REG_NOTEOL) != 0; }
95    }
96
97    property bool extendedSyntax
98    {
99       set
100       {
101          if(value != ((compileFlags & REG_EXTENDED) != 0))
102          {
103             value ? (compileFlags |= REG_EXTENDED) : (compileFlags &= ~REG_EXTENDED);
104             if(regex)
105                Compile();
106          }
107       }
108       get { return (compileFlags & REG_EXTENDED) != 0; }
109    }
110
111    property bool valid { get { return valid; } }
112
113    property int maxMatchCount
114    {
115       set
116       {
117          if(value != maxMatchCount)
118          {
119             maxMatchCount = value > 0 ? value : 1;
120             delete matches;
121             matches = new regmatch_t[maxMatchCount];
122          }
123       }
124       get { return maxMatchCount; }
125    }
126
127    property int matchCount { get { return matchCount; } }
128
129    char * Match(const String string)
130    {
131       if(valid)
132       {
133          int c;
134          int result;
135          result = regexec(&compiledRegex, string, maxMatchCount, matches, executeFlags);
136          if(result == 0) // != REG_NOMATCH
137          {
138             for(c = 0; c < maxMatchCount; c++)
139             {
140                if(matches[c].rm_so == -1)
141                {
142                   matchCount = c;
143                   break;
144                }
145             }
146             if(c == maxMatchCount)
147                matchCount = maxMatchCount;
148             return (char *)string + matches[0].rm_so;
149          }
150          else
151             matchCount = 0;
152       }
153       return null;
154    }
155
156    int GetMatchStartOffset(int matchPos)
157    {
158       return matches[matchPos].rm_so;
159    }
160
161    int GetMatchEndOffset(int matchPos)
162    {
163       return matches[matchPos].rm_eo;
164    }
165
166 private:
167    bool valid;
168    int compileFlags;
169    int executeFlags;
170    int matchCount;
171    int maxMatchCount;
172    regex_t compiledRegex;
173    regmatch_t * matches;
174
175    ~Regex()
176    {
177       Free();
178    }
179
180    void Free()
181    {
182       delete matches;
183       delete regex;
184       regfree(&compiledRegex);
185       valid = false;
186    }
187
188    void Compile()
189    {
190       int result;
191       regfree(&compiledRegex);
192       // compileFlags -- REG_NOSUB --  no substring addressing of matches -- nmatch and pmatch in regexec(...) are ignored if used
193       result = regcomp(&compiledRegex, regex, compileFlags/* | REG_NOSUB*/);
194       valid = result == 0;
195       if(valid && !maxMatchCount)
196          property::maxMatchCount = 1;
197
198       // TODO: handle errors?
199       // size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
200       // REG_BADBR      Invalid use of back reference operator.
201       // REG_BADPAT     Invalid use of pattern operators such as group or list.
202       // REG_BADRPT     Invalid use of repetition operators such as using '*' as the first character.
203       // REG_EBRACE     Un-matched brace interval operators.
204       // REG_EBRACK     Un-matched bracket list operators.
205       // REG_ECOLLATE   Invalid collating element.
206       // REG_ECTYPE     Unknown character class name.
207       // REG_EEND       Non specific error. This is not defined by POSIX.2.
208       // REG_EESCAPE    Trailing backslash.
209       // REG_EPAREN     Un-matched parenthesis group operators.
210       // REG_ERANGE     Invalid use of the range operator, eg. the ending point of the range occurs prior to the starting point.
211       // REG_ESIZE      Compiled regular expression requires a pattern buffer larger than 64Kb. This is not defined by POSIX.2.
212       // REG_ESPACE     The regex routines ran out of memory.
213       // REG_ESUBREG    Invalid back reference to a subexpression.
214    }
215
216    String regex;
217 }