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