]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.c
MdeModulePkg: Regular expression protocol
[mirror_edk2.git] / MdeModulePkg / Universal / RegularExpressionDxe / RegularExpressionDxe.c
diff --git a/MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.c b/MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.c
new file mode 100644 (file)
index 0000000..6c62957
--- /dev/null
@@ -0,0 +1,321 @@
+/**\r
+  @file\r
+\r
+  EFI_REGULAR_EXPRESSION_PROTOCOL Implementation\r
+\r
+  Copyright (c) 2015, Hewlett Packard Enterprise Development, L.P.<BR>\r
+\r
+  This program and the accompanying materials are licensed and made available\r
+  under the terms and conditions of the BSD License that accompanies this\r
+  distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#include "RegularExpressionDxe.h"\r
+\r
+STATIC\r
+EFI_REGEX_SYNTAX_TYPE * CONST mSupportedSyntaxes[] = {\r
+  &gEfiRegexSyntaxTypePosixExtendedGuid,\r
+  &gEfiRegexSyntaxTypePerlGuid\r
+};\r
+\r
+STATIC\r
+EFI_REGULAR_EXPRESSION_PROTOCOL mProtocolInstance = {\r
+  RegularExpressionMatch,\r
+  RegularExpressionGetInfo\r
+};\r
+\r
+\r
+\r
+#define CHAR16_ENCODING ONIG_ENCODING_UTF16_LE\r
+\r
+/**\r
+  Call the Oniguruma regex match API.\r
+\r
+  Same parameters as RegularExpressionMatch, except SyntaxType is required.\r
+\r
+  @retval EFI_SUCCESS       Regex compilation and match completed successfully.\r
+  @retval EFI_DEVICE_ERROR  Regex compilation failed.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+OnigurumaMatch (\r
+  IN  CHAR16                *String,\r
+  IN  CHAR16                *Pattern,\r
+  IN  EFI_REGEX_SYNTAX_TYPE *SyntaxType,\r
+  OUT BOOLEAN               *Result,\r
+  OUT EFI_REGEX_CAPTURE     **Captures,     OPTIONAL\r
+  OUT UINTN                 *CapturesCount\r
+  )\r
+{\r
+  regex_t         *OnigRegex;\r
+  OnigSyntaxType  *OnigSyntax;\r
+  OnigRegion      *Region;\r
+  INT32           OnigResult;\r
+  OnigErrorInfo   ErrorInfo;\r
+  CHAR8           ErrorMessage[ONIG_MAX_ERROR_MESSAGE_LEN];\r
+  UINT32          Index;\r
+  OnigUChar       *Start;\r
+\r
+  //\r
+  // Detemine the internal syntax type\r
+  //\r
+  OnigSyntax = ONIG_SYNTAX_DEFAULT;\r
+  if (CompareGuid (SyntaxType, &gEfiRegexSyntaxTypePosixExtendedGuid)) {\r
+    OnigSyntax = ONIG_SYNTAX_POSIX_EXTENDED;\r
+  } else if (CompareGuid (SyntaxType, &gEfiRegexSyntaxTypePerlGuid)) {\r
+    OnigSyntax = ONIG_SYNTAX_PERL;\r
+  } else {\r
+    DEBUG ((DEBUG_ERROR, "Unsupported regex syntax - using default\n"));\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+  //\r
+  // Compile pattern\r
+  //\r
+  Start = (OnigUChar*)Pattern;\r
+  OnigResult = onig_new (\r
+                 &OnigRegex,\r
+                 Start,\r
+                 Start + onigenc_str_bytelen_null (CHAR16_ENCODING, Start),\r
+                 ONIG_OPTION_DEFAULT,\r
+                 CHAR16_ENCODING,\r
+                 OnigSyntax,\r
+                 &ErrorInfo\r
+                 );\r
+\r
+  if (OnigResult != ONIG_NORMAL) {\r
+    onig_error_code_to_str (ErrorMessage, OnigResult, &ErrorInfo);\r
+    DEBUG ((DEBUG_ERROR, "Regex compilation failed: %a\n", ErrorMessage));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Try to match\r
+  //\r
+  Start = (OnigUChar*)String;\r
+  Region = onig_region_new ();\r
+  OnigResult = onig_search (\r
+                 OnigRegex,\r
+                 Start,\r
+                 Start + onigenc_str_bytelen_null (CHAR16_ENCODING, Start),\r
+                 Start,\r
+                 Start + onigenc_str_bytelen_null (CHAR16_ENCODING, Start),\r
+                 Region,\r
+                 ONIG_OPTION_NONE\r
+                 );\r
+  if (OnigResult >= 0) {\r
+    *Result = TRUE;\r
+  } else {\r
+    *Result = FALSE;\r
+    if (OnigResult != ONIG_MISMATCH) {\r
+      onig_error_code_to_str (ErrorMessage, OnigResult);\r
+      DEBUG ((DEBUG_ERROR, "Regex match failed: %a\n", ErrorMessage));\r
+    }\r
+  }\r
+\r
+  //\r
+  // If successful, copy out the region (capture) information\r
+  //\r
+  if (*Result && Captures != NULL) {\r
+    *CapturesCount = Region->num_regs;\r
+    *Captures = AllocatePool (*CapturesCount * sizeof(**Captures));\r
+    if (*Captures != NULL) {\r
+      for (Index = 0; Index < *CapturesCount; ++Index) {\r
+        //\r
+        // Region beg/end values represent bytes, not characters\r
+        //\r
+        (*Captures)[Index].CapturePtr = (CHAR16*)((UINTN)String + Region->beg[Index]);\r
+        (*Captures)[Index].Length = (Region->end[Index] - Region->beg[Index]) / sizeof(CHAR16);\r
+      }\r
+    }\r
+  }\r
+\r
+  onig_region_free (Region, 1);\r
+  onig_free (OnigRegex);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Returns information about the regular expression syntax types supported\r
+  by the implementation.\r
+\r
+  This                     A pointer to the EFI_REGULAR_EXPRESSION_PROTOCOL\r
+                           instance.\r
+\r
+  RegExSyntaxTypeListSize  On input, the size in bytes of RegExSyntaxTypeList.\r
+                           On output with a return code of EFI_SUCCESS, the\r
+                           size in bytes of the data returned in\r
+                           RegExSyntaxTypeList. On output with a return code\r
+                           of EFI_BUFFER_TOO_SMALL, the size of\r
+                           RegExSyntaxTypeList required to obtain the list.\r
+\r
+  RegExSyntaxTypeList      A caller-allocated memory buffer filled by the\r
+                           driver with one EFI_REGEX_SYNTAX_TYPE element\r
+                           for each supported Regular expression syntax\r
+                           type. The list must not change across multiple\r
+                           calls to the same driver. The first syntax\r
+                           type in the list is the default type for the\r
+                           driver.\r
+\r
+  @retval EFI_SUCCESS            The regular expression syntax types list\r
+                                 was returned successfully.\r
+  @retval EFI_UNSUPPORTED        The service is not supported by this driver.\r
+  @retval EFI_DEVICE_ERROR       The list of syntax types could not be\r
+                                 retrieved due to a hardware or firmware error.\r
+  @retval EFI_BUFFER_TOO_SMALL   The buffer RegExSyntaxTypeList is too small\r
+                                 to hold the result.\r
+  @retval EFI_INVALID_PARAMETER  RegExSyntaxTypeListSize is NULL\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RegularExpressionGetInfo (\r
+  IN     EFI_REGULAR_EXPRESSION_PROTOCOL *This,\r
+  IN OUT UINTN                           *RegExSyntaxTypeListSize,\r
+  OUT    EFI_REGEX_SYNTAX_TYPE           *RegExSyntaxTypeList\r
+  )\r
+{\r
+  UINTN SyntaxSize;\r
+  UINTN Index;\r
+\r
+  if (This == NULL || RegExSyntaxTypeListSize == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (*RegExSyntaxTypeListSize != 0 && RegExSyntaxTypeList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  SyntaxSize = ARRAY_SIZE (mSupportedSyntaxes) * sizeof(**mSupportedSyntaxes);\r
+\r
+  if (*RegExSyntaxTypeListSize < SyntaxSize) {\r
+    *RegExSyntaxTypeListSize = SyntaxSize;\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  for (Index = 0; Index < ARRAY_SIZE (mSupportedSyntaxes); ++Index) {\r
+    CopyMem (&RegExSyntaxTypeList[Index], mSupportedSyntaxes[Index], sizeof(**mSupportedSyntaxes));\r
+  }\r
+  *RegExSyntaxTypeListSize = SyntaxSize;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Checks if the input string matches to the regular expression pattern.\r
+\r
+  This          A pointer to the EFI_REGULAR_EXPRESSION_PROTOCOL instance.\r
+                Type EFI_REGULAR_EXPRESSION_PROTOCOL is defined in Section\r
+                XYZ.\r
+\r
+  String        A pointer to a NULL terminated string to match against the\r
+                regular expression string specified by Pattern.\r
+\r
+  Pattern       A pointer to a NULL terminated string that represents the\r
+                regular expression.\r
+\r
+  SyntaxType    A pointer to the EFI_REGEX_SYNTAX_TYPE that identifies the\r
+                regular expression syntax type to use. May be NULL in which\r
+                case the function will use its default regular expression\r
+                syntax type.\r
+\r
+  Result        On return, points to TRUE if String fully matches against\r
+                the regular expression Pattern using the regular expression\r
+                SyntaxType. Otherwise, points to FALSE.\r
+\r
+  Captures      A Pointer to an array of EFI_REGEX_CAPTURE objects to receive\r
+                the captured groups in the event of a match. The full\r
+                sub-string match is put in Captures[0], and the results of N\r
+                capturing groups are put in Captures[1:N]. If Captures is\r
+                NULL, then this function doesn't allocate the memory for the\r
+                array and does not build up the elements. It only returns the\r
+                number of matching patterns in CapturesCount. If Captures is\r
+                not NULL, this function returns a pointer to an array and\r
+                builds up the elements in the array. CapturesCount is also\r
+                updated to the number of matching patterns found. It is the\r
+                caller's responsibility to free the memory pool in Captures\r
+                and in each CapturePtr in the array elements.\r
+\r
+  CapturesCount On output, CapturesCount is the number of matching patterns\r
+                found in String. Zero means no matching patterns were found\r
+                in the string.\r
+\r
+  @retval EFI_SUCCESS            The regular expression string matching\r
+                                 completed successfully.\r
+  @retval EFI_UNSUPPORTED        The regular expression syntax specified by\r
+                                 SyntaxType is not supported by this driver.\r
+  @retval EFI_DEVICE_ERROR       The regular expression string matching\r
+                                 failed due to a hardware or firmware error.\r
+  @retval EFI_INVALID_PARAMETER  String, Pattern, Result, or CapturesCountis\r
+                                 NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RegularExpressionMatch (\r
+  IN  EFI_REGULAR_EXPRESSION_PROTOCOL *This,\r
+  IN  CHAR16                          *String,\r
+  IN  CHAR16                          *Pattern,\r
+  IN  EFI_REGEX_SYNTAX_TYPE           *SyntaxType, OPTIONAL\r
+  OUT BOOLEAN                         *Result,\r
+  OUT EFI_REGEX_CAPTURE               **Captures, OPTIONAL\r
+  OUT UINTN                           *CapturesCount\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      Index;\r
+  BOOLEAN     Supported;\r
+\r
+  if (This == NULL || String == NULL || Pattern == NULL || Result == NULL || CapturesCount == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Figure out which syntax to use\r
+  //\r
+  if (SyntaxType == NULL) {\r
+    SyntaxType = mSupportedSyntaxes[0];\r
+  } else {\r
+    Supported = FALSE;\r
+    for (Index = 0; Index < ARRAY_SIZE (mSupportedSyntaxes); ++Index) {\r
+      if (CompareGuid (SyntaxType, mSupportedSyntaxes[Index])) {\r
+        Supported = TRUE;\r
+        break;\r
+      }\r
+    }\r
+    if (!Supported) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  }\r
+\r
+  Status = OnigurumaMatch (String, Pattern, SyntaxType, Result, Captures, CapturesCount);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Entry point for RegularExpressionDxe.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RegularExpressionDxeEntry (\r
+  IN  EFI_HANDLE        ImageHandle,\r
+  IN  EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &ImageHandle,\r
+                  &gEfiRegularExpressionProtocolGuid,\r
+                  &mProtocolInstance,\r
+                  NULL\r
+                  );\r
+\r
+  return Status;\r
+}\r