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