]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.c
MdeModulePkg: Regular expression protocol
[mirror_edk2.git] / MdeModulePkg / Universal / RegularExpressionDxe / RegularExpressionDxe.c
1 /**
2 @file
3
4 EFI_REGULAR_EXPRESSION_PROTOCOL Implementation
5
6 Copyright (c) 2015, Hewlett Packard Enterprise Development, L.P.<BR>
7
8 This program and the accompanying materials are licensed and made available
9 under the terms and conditions of the BSD License that accompanies this
10 distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php.
12
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
14 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 **/
16
17 #include "RegularExpressionDxe.h"
18
19 STATIC
20 EFI_REGEX_SYNTAX_TYPE * CONST mSupportedSyntaxes[] = {
21 &gEfiRegexSyntaxTypePosixExtendedGuid,
22 &gEfiRegexSyntaxTypePerlGuid
23 };
24
25 STATIC
26 EFI_REGULAR_EXPRESSION_PROTOCOL mProtocolInstance = {
27 RegularExpressionMatch,
28 RegularExpressionGetInfo
29 };
30
31
32
33 #define CHAR16_ENCODING ONIG_ENCODING_UTF16_LE
34
35 /**
36 Call the Oniguruma regex match API.
37
38 Same parameters as RegularExpressionMatch, except SyntaxType is required.
39
40 @retval EFI_SUCCESS Regex compilation and match completed successfully.
41 @retval EFI_DEVICE_ERROR Regex compilation failed.
42 **/
43 STATIC
44 EFI_STATUS
45 OnigurumaMatch (
46 IN CHAR16 *String,
47 IN CHAR16 *Pattern,
48 IN EFI_REGEX_SYNTAX_TYPE *SyntaxType,
49 OUT BOOLEAN *Result,
50 OUT EFI_REGEX_CAPTURE **Captures, OPTIONAL
51 OUT UINTN *CapturesCount
52 )
53 {
54 regex_t *OnigRegex;
55 OnigSyntaxType *OnigSyntax;
56 OnigRegion *Region;
57 INT32 OnigResult;
58 OnigErrorInfo ErrorInfo;
59 CHAR8 ErrorMessage[ONIG_MAX_ERROR_MESSAGE_LEN];
60 UINT32 Index;
61 OnigUChar *Start;
62
63 //
64 // Detemine the internal syntax type
65 //
66 OnigSyntax = ONIG_SYNTAX_DEFAULT;
67 if (CompareGuid (SyntaxType, &gEfiRegexSyntaxTypePosixExtendedGuid)) {
68 OnigSyntax = ONIG_SYNTAX_POSIX_EXTENDED;
69 } else if (CompareGuid (SyntaxType, &gEfiRegexSyntaxTypePerlGuid)) {
70 OnigSyntax = ONIG_SYNTAX_PERL;
71 } else {
72 DEBUG ((DEBUG_ERROR, "Unsupported regex syntax - using default\n"));
73 ASSERT (FALSE);
74 }
75
76 //
77 // Compile pattern
78 //
79 Start = (OnigUChar*)Pattern;
80 OnigResult = onig_new (
81 &OnigRegex,
82 Start,
83 Start + onigenc_str_bytelen_null (CHAR16_ENCODING, Start),
84 ONIG_OPTION_DEFAULT,
85 CHAR16_ENCODING,
86 OnigSyntax,
87 &ErrorInfo
88 );
89
90 if (OnigResult != ONIG_NORMAL) {
91 onig_error_code_to_str (ErrorMessage, OnigResult, &ErrorInfo);
92 DEBUG ((DEBUG_ERROR, "Regex compilation failed: %a\n", ErrorMessage));
93 return EFI_DEVICE_ERROR;
94 }
95
96 //
97 // Try to match
98 //
99 Start = (OnigUChar*)String;
100 Region = onig_region_new ();
101 OnigResult = onig_search (
102 OnigRegex,
103 Start,
104 Start + onigenc_str_bytelen_null (CHAR16_ENCODING, Start),
105 Start,
106 Start + onigenc_str_bytelen_null (CHAR16_ENCODING, Start),
107 Region,
108 ONIG_OPTION_NONE
109 );
110 if (OnigResult >= 0) {
111 *Result = TRUE;
112 } else {
113 *Result = FALSE;
114 if (OnigResult != ONIG_MISMATCH) {
115 onig_error_code_to_str (ErrorMessage, OnigResult);
116 DEBUG ((DEBUG_ERROR, "Regex match failed: %a\n", ErrorMessage));
117 }
118 }
119
120 //
121 // If successful, copy out the region (capture) information
122 //
123 if (*Result && Captures != NULL) {
124 *CapturesCount = Region->num_regs;
125 *Captures = AllocatePool (*CapturesCount * sizeof(**Captures));
126 if (*Captures != NULL) {
127 for (Index = 0; Index < *CapturesCount; ++Index) {
128 //
129 // Region beg/end values represent bytes, not characters
130 //
131 (*Captures)[Index].CapturePtr = (CHAR16*)((UINTN)String + Region->beg[Index]);
132 (*Captures)[Index].Length = (Region->end[Index] - Region->beg[Index]) / sizeof(CHAR16);
133 }
134 }
135 }
136
137 onig_region_free (Region, 1);
138 onig_free (OnigRegex);
139
140 return EFI_SUCCESS;
141 }
142
143 /**
144 Returns information about the regular expression syntax types supported
145 by the implementation.
146
147 This A pointer to the EFI_REGULAR_EXPRESSION_PROTOCOL
148 instance.
149
150 RegExSyntaxTypeListSize On input, the size in bytes of RegExSyntaxTypeList.
151 On output with a return code of EFI_SUCCESS, the
152 size in bytes of the data returned in
153 RegExSyntaxTypeList. On output with a return code
154 of EFI_BUFFER_TOO_SMALL, the size of
155 RegExSyntaxTypeList required to obtain the list.
156
157 RegExSyntaxTypeList A caller-allocated memory buffer filled by the
158 driver with one EFI_REGEX_SYNTAX_TYPE element
159 for each supported Regular expression syntax
160 type. The list must not change across multiple
161 calls to the same driver. The first syntax
162 type in the list is the default type for the
163 driver.
164
165 @retval EFI_SUCCESS The regular expression syntax types list
166 was returned successfully.
167 @retval EFI_UNSUPPORTED The service is not supported by this driver.
168 @retval EFI_DEVICE_ERROR The list of syntax types could not be
169 retrieved due to a hardware or firmware error.
170 @retval EFI_BUFFER_TOO_SMALL The buffer RegExSyntaxTypeList is too small
171 to hold the result.
172 @retval EFI_INVALID_PARAMETER RegExSyntaxTypeListSize is NULL
173
174 **/
175 EFI_STATUS
176 EFIAPI
177 RegularExpressionGetInfo (
178 IN EFI_REGULAR_EXPRESSION_PROTOCOL *This,
179 IN OUT UINTN *RegExSyntaxTypeListSize,
180 OUT EFI_REGEX_SYNTAX_TYPE *RegExSyntaxTypeList
181 )
182 {
183 UINTN SyntaxSize;
184 UINTN Index;
185
186 if (This == NULL || RegExSyntaxTypeListSize == NULL) {
187 return EFI_INVALID_PARAMETER;
188 }
189
190 if (*RegExSyntaxTypeListSize != 0 && RegExSyntaxTypeList == NULL) {
191 return EFI_INVALID_PARAMETER;
192 }
193
194 SyntaxSize = ARRAY_SIZE (mSupportedSyntaxes) * sizeof(**mSupportedSyntaxes);
195
196 if (*RegExSyntaxTypeListSize < SyntaxSize) {
197 *RegExSyntaxTypeListSize = SyntaxSize;
198 return EFI_BUFFER_TOO_SMALL;
199 }
200
201 for (Index = 0; Index < ARRAY_SIZE (mSupportedSyntaxes); ++Index) {
202 CopyMem (&RegExSyntaxTypeList[Index], mSupportedSyntaxes[Index], sizeof(**mSupportedSyntaxes));
203 }
204 *RegExSyntaxTypeListSize = SyntaxSize;
205
206 return EFI_SUCCESS;
207 }
208
209 /**
210 Checks if the input string matches to the regular expression pattern.
211
212 This A pointer to the EFI_REGULAR_EXPRESSION_PROTOCOL instance.
213 Type EFI_REGULAR_EXPRESSION_PROTOCOL is defined in Section
214 XYZ.
215
216 String A pointer to a NULL terminated string to match against the
217 regular expression string specified by Pattern.
218
219 Pattern A pointer to a NULL terminated string that represents the
220 regular expression.
221
222 SyntaxType A pointer to the EFI_REGEX_SYNTAX_TYPE that identifies the
223 regular expression syntax type to use. May be NULL in which
224 case the function will use its default regular expression
225 syntax type.
226
227 Result On return, points to TRUE if String fully matches against
228 the regular expression Pattern using the regular expression
229 SyntaxType. Otherwise, points to FALSE.
230
231 Captures A Pointer to an array of EFI_REGEX_CAPTURE objects to receive
232 the captured groups in the event of a match. The full
233 sub-string match is put in Captures[0], and the results of N
234 capturing groups are put in Captures[1:N]. If Captures is
235 NULL, then this function doesn't allocate the memory for the
236 array and does not build up the elements. It only returns the
237 number of matching patterns in CapturesCount. If Captures is
238 not NULL, this function returns a pointer to an array and
239 builds up the elements in the array. CapturesCount is also
240 updated to the number of matching patterns found. It is the
241 caller's responsibility to free the memory pool in Captures
242 and in each CapturePtr in the array elements.
243
244 CapturesCount On output, CapturesCount is the number of matching patterns
245 found in String. Zero means no matching patterns were found
246 in the string.
247
248 @retval EFI_SUCCESS The regular expression string matching
249 completed successfully.
250 @retval EFI_UNSUPPORTED The regular expression syntax specified by
251 SyntaxType is not supported by this driver.
252 @retval EFI_DEVICE_ERROR The regular expression string matching
253 failed due to a hardware or firmware error.
254 @retval EFI_INVALID_PARAMETER String, Pattern, Result, or CapturesCountis
255 NULL.
256
257 **/
258 EFI_STATUS
259 EFIAPI
260 RegularExpressionMatch (
261 IN EFI_REGULAR_EXPRESSION_PROTOCOL *This,
262 IN CHAR16 *String,
263 IN CHAR16 *Pattern,
264 IN EFI_REGEX_SYNTAX_TYPE *SyntaxType, OPTIONAL
265 OUT BOOLEAN *Result,
266 OUT EFI_REGEX_CAPTURE **Captures, OPTIONAL
267 OUT UINTN *CapturesCount
268 )
269 {
270 EFI_STATUS Status;
271 UINT32 Index;
272 BOOLEAN Supported;
273
274 if (This == NULL || String == NULL || Pattern == NULL || Result == NULL || CapturesCount == NULL) {
275 return EFI_INVALID_PARAMETER;
276 }
277
278 //
279 // Figure out which syntax to use
280 //
281 if (SyntaxType == NULL) {
282 SyntaxType = mSupportedSyntaxes[0];
283 } else {
284 Supported = FALSE;
285 for (Index = 0; Index < ARRAY_SIZE (mSupportedSyntaxes); ++Index) {
286 if (CompareGuid (SyntaxType, mSupportedSyntaxes[Index])) {
287 Supported = TRUE;
288 break;
289 }
290 }
291 if (!Supported) {
292 return EFI_UNSUPPORTED;
293 }
294 }
295
296 Status = OnigurumaMatch (String, Pattern, SyntaxType, Result, Captures, CapturesCount);
297
298 return Status;
299 }
300
301 /**
302 Entry point for RegularExpressionDxe.
303 **/
304 EFI_STATUS
305 EFIAPI
306 RegularExpressionDxeEntry (
307 IN EFI_HANDLE ImageHandle,
308 IN EFI_SYSTEM_TABLE *SystemTable
309 )
310 {
311 EFI_STATUS Status;
312
313 Status = gBS->InstallMultipleProtocolInterfaces (
314 &ImageHandle,
315 &gEfiRegularExpressionProtocolGuid,
316 &mProtocolInstance,
317 NULL
318 );
319
320 return Status;
321 }