Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
regexpr.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19// regexpr.cpp
20
21#include "always.h"
22#include "regexpr.h"
23#include "wwstring.h"
24#include <assert.h>
25
26// Pull in the gnu_regex library's definitions.
27#define __STDC__ 1
28extern "C" {
29#include "gnu_regex.h"
30}
31
32
33// The regular expression syntax options that RegularExpressionClass uses.
34// The dirty details of each option are described in "gnu_regex.h"
35#define OUR_SYNTAX_OPTIONS \
36 RE_CHAR_CLASSES | /* Support character classes such as [:alpha:] and [:digit:] */ \
37 RE_CONTEXT_INDEP_ANCHORS | /* ^ and $ are always anchors (outside bracket expressions) */ \
38 RE_CONTEXT_INDEP_OPS | /* operators such as + * ? are always considered operators */ \
39 RE_CONTEXT_INVALID_OPS | /* operators are invalid as the first characters in a string */ \
40 RE_INTERVALS | /* { } are used to define intervals */ \
41 RE_NO_BK_BRACES | /* { } are interval markers and \{ \} are literals */ \
42 RE_NO_BK_PARENS | /* ( ) are group markers and \‍( \‍) are literals */ \
43 RE_NO_BK_VBAR | /* | is the OR operator and \| is a literal */ \
44 RE_NO_EMPTY_RANGES /* [z-a] is an invalid range but [a-z] is valid */
45
46
47/*
48** Definition of private DataStruct for RegularExpressionClass
49*/
50
52{
54 : IsValid(false)
55 {
56 // Blank out the expression structure.
57 memset(&CompiledExpr, 0, sizeof(CompiledExpr));
58 }
59
61 {
63 }
64
65 void ClearExpression (void)
66 {
67 // If the expression was valid, let the gnu_regex library
68 // deallocate any memory it had allocated for it.
69 if (IsValid)
70 regfree(&CompiledExpr);
71
72 // Blank out the expression structure.
73 memset(&CompiledExpr, 0, sizeof(CompiledExpr));
74
75 // Erase the expression string.
76 ExprString = "";
77
78 // No longer a valid compiled expression.
79 IsValid = false;
80 }
81
82
83 // The regular expression that has been compiled.
85
86 // gnu_regex compiled version of the regular expression used
87 // during matching or any form of evaluation
88 regex_t CompiledExpr;
89
90 // True if CompiledExpr is valid.
91 bool IsValid;
92};
93
94
95
96/*
97** RegularExpressionClass Implementation
98*/
99
101: Data(0)
102{
103 // Allocate our private members.
104 Data = new DataStruct;
105 assert(Data);
106
107 // Compile the expression if we were given one.
108 if (expression)
109 Compile(expression);
110}
111
112
114: Data(0)
115{
116 // Allocate our private members.
117 Data = new DataStruct;
118 assert(Data);
119
120 // Compile the expression if the given object had one.
121 if (copy.Is_Valid())
122 {
123 Compile(copy.Data->ExprString);
124 assert(Is_Valid());
125 }
126}
127
128
130{
131 delete Data;
132 Data = 0;
133}
134
135
136bool RegularExpressionClass::Compile (const char *expression)
137{
138 assert(Data);
139 assert(expression);
140
141 // Clear any existing expression data. This makes it safe to
142 // call Compile() twice on one object.
143 Data->ClearExpression();
144
145 // Set the regular expression module to the syntax that we
146 // would like to use.
147 reg_syntax_t old_syntax = re_set_syntax(OUR_SYNTAX_OPTIONS);
148
149 // Compile the given expression.
150 const char *error_str = re_compile_pattern(expression,
151 strlen(expression), &Data->CompiledExpr);
152
153 // Restore the old syntax setting.
154 re_set_syntax(old_syntax);
155
156 // If no error string was returned, the expression was good!
157 if (error_str == 0)
158 {
159 Data->IsValid = true;
160 Data->ExprString = expression;
161 return true;
162 }
163 return false;
164}
165
166
168{
169 assert(Data);
170 return Data->IsValid;
171}
172
173
174bool RegularExpressionClass::Match (const char *string) const
175{
176 assert(Data);
177
178 // If we have no valid compiled expression, we can't match Jack.
179 if (!Data->IsValid)
180 return false;
181
182 // Set the regular expression module to the syntax that we
183 // would like to use.
184 reg_syntax_t old_syntax = re_set_syntax(OUR_SYNTAX_OPTIONS);
185
186 // Try to match the given string with our regular expression.
187 int retval = re_match(&Data->CompiledExpr, string, strlen(string), 0, 0);
188
189 // Restore the old syntax setting.
190 re_set_syntax(old_syntax);
191
192 // -1 means no match, -2 means internal gnu_regex lib error, otherwise
193 // re_match returned the number of characters matched. A 0 character
194 // match is valid, and distinctly different than no match at all.
195 if (retval < 0)
196 return false;
197
198 // The given string matched our regular expression!
199 return true;
200}
201
202
203/*
204** Operators
205*/
206
208{
209 // Check for assignment to self.
210 if (*this == rhs)
211 return *this;
212
213 // Assign that object to this one.
214 assert(rhs.Data);
215 Compile(rhs.Data->ExprString);
216 assert(Is_Valid());
217
218 // Return this object.
219 return *this;
220}
221
222
224{
225 // Two RegularExpressionClass objects are equivalent if they both
226 // have the same validity state, and if that state is 'true' both
227 // of their expressions are the same.
228
229 // Check validity states for equality.
230 if (Is_Valid() != rhs.Is_Valid())
231 return false;
232
233 // If they're valid, check their expressions.
234 if (Is_Valid())
235 {
236 // The objects are not equivalent if their expression strings
237 // don't match.
238 if (Data->ExprString != rhs.Data->ExprString)
239 return false;
240 }
241 return true;
242}
243
244
246{
247 return !(*this == rhs);
248}
249
250
@ false
Definition bool.h:59
RegularExpressionClass(const char *expression=0)
Definition regexpr.cpp:100
bool Match(const char *string) const
Definition regexpr.cpp:174
bool operator==(const RegularExpressionClass &rhs) const
Definition regexpr.cpp:223
RegularExpressionClass & operator=(const RegularExpressionClass &rhs)
Definition regexpr.cpp:207
bool operator!=(const RegularExpressionClass &rhs) const
Definition regexpr.cpp:245
bool Compile(const char *expression)
Definition regexpr.cpp:136
bool Is_Valid(void) const
Definition regexpr.cpp:167
#define OUR_SYNTAX_OPTIONS
Definition regexpr.cpp:35