| /** @file | |
| Unicode and ASCII string primitives. | |
| Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include "BaseLibInternals.h" | |
| /** | |
| Returns the length of a Null-terminated Unicode string. | |
| This function returns the number of Unicode characters in the Null-terminated | |
| Unicode string specified by String. | |
| If String is NULL, then ASSERT(). | |
| If String is not aligned on a 16-bit boundary, then ASSERT(). | |
| If PcdMaximumUnicodeStringLength is not zero, and String contains more than | |
| PcdMaximumUnicodeStringLength Unicode characters, not including the | |
| Null-terminator, then ASSERT(). | |
| @param String A pointer to a Null-terminated Unicode string. | |
| @return The length of String. | |
| **/ | |
| UINTN | |
| EFIAPI | |
| StrLen ( | |
| IN CONST CHAR16 *String | |
| ) | |
| { | |
| UINTN Length; | |
| ASSERT (String != NULL); | |
| ASSERT (((UINTN)String & BIT0) == 0); | |
| for (Length = 0; *String != L'\0'; String++, Length++) { | |
| // | |
| // If PcdMaximumUnicodeStringLength is not zero, | |
| // length should not more than PcdMaximumUnicodeStringLength | |
| // | |
| if (PcdGet32 (PcdMaximumUnicodeStringLength) != 0) { | |
| ASSERT (Length < PcdGet32 (PcdMaximumUnicodeStringLength)); | |
| } | |
| } | |
| return Length; | |
| } | |
| /** | |
| Returns the size of a Null-terminated Unicode string in bytes, including the | |
| Null terminator. | |
| This function returns the size, in bytes, of the Null-terminated Unicode string | |
| specified by String. | |
| If String is NULL, then ASSERT(). | |
| If String is not aligned on a 16-bit boundary, then ASSERT(). | |
| If PcdMaximumUnicodeStringLength is not zero, and String contains more than | |
| PcdMaximumUnicodeStringLength Unicode characters, not including the | |
| Null-terminator, then ASSERT(). | |
| @param String A pointer to a Null-terminated Unicode string. | |
| @return The size of String. | |
| **/ | |
| UINTN | |
| EFIAPI | |
| StrSize ( | |
| IN CONST CHAR16 *String | |
| ) | |
| { | |
| return (StrLen (String) + 1) * sizeof (*String); | |
| } | |
| /** | |
| Compares two Null-terminated Unicode strings, and returns the difference | |
| between the first mismatched Unicode characters. | |
| This function compares the Null-terminated Unicode string FirstString to the | |
| Null-terminated Unicode string SecondString. If FirstString is identical to | |
| SecondString, then 0 is returned. Otherwise, the value returned is the first | |
| mismatched Unicode character in SecondString subtracted from the first | |
| mismatched Unicode character in FirstString. | |
| If FirstString is NULL, then ASSERT(). | |
| If FirstString is not aligned on a 16-bit boundary, then ASSERT(). | |
| If SecondString is NULL, then ASSERT(). | |
| If SecondString is not aligned on a 16-bit boundary, then ASSERT(). | |
| If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more | |
| than PcdMaximumUnicodeStringLength Unicode characters, not including the | |
| Null-terminator, then ASSERT(). | |
| If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more | |
| than PcdMaximumUnicodeStringLength Unicode characters, not including the | |
| Null-terminator, then ASSERT(). | |
| @param FirstString A pointer to a Null-terminated Unicode string. | |
| @param SecondString A pointer to a Null-terminated Unicode string. | |
| @retval 0 FirstString is identical to SecondString. | |
| @return others FirstString is not identical to SecondString. | |
| **/ | |
| INTN | |
| EFIAPI | |
| StrCmp ( | |
| IN CONST CHAR16 *FirstString, | |
| IN CONST CHAR16 *SecondString | |
| ) | |
| { | |
| // | |
| // ASSERT both strings are less long than PcdMaximumUnicodeStringLength | |
| // | |
| ASSERT (StrSize (FirstString) != 0); | |
| ASSERT (StrSize (SecondString) != 0); | |
| while ((*FirstString != L'\0') && (*FirstString == *SecondString)) { | |
| FirstString++; | |
| SecondString++; | |
| } | |
| return *FirstString - *SecondString; | |
| } | |
| /** | |
| Compares up to a specified length the contents of two Null-terminated Unicode strings, | |
| and returns the difference between the first mismatched Unicode characters. | |
| This function compares the Null-terminated Unicode string FirstString to the | |
| Null-terminated Unicode string SecondString. At most, Length Unicode | |
| characters will be compared. If Length is 0, then 0 is returned. If | |
| FirstString is identical to SecondString, then 0 is returned. Otherwise, the | |
| value returned is the first mismatched Unicode character in SecondString | |
| subtracted from the first mismatched Unicode character in FirstString. | |
| If Length > 0 and FirstString is NULL, then ASSERT(). | |
| If Length > 0 and FirstString is not aligned on a 16-bit boundary, then ASSERT(). | |
| If Length > 0 and SecondString is NULL, then ASSERT(). | |
| If Length > 0 and SecondString is not aligned on a 16-bit boundary, then ASSERT(). | |
| If PcdMaximumUnicodeStringLength is not zero, and Length is greater than | |
| PcdMaximumUnicodeStringLength, then ASSERT(). | |
| If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more than | |
| PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, | |
| then ASSERT(). | |
| If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more than | |
| PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, | |
| then ASSERT(). | |
| @param FirstString A pointer to a Null-terminated Unicode string. | |
| @param SecondString A pointer to a Null-terminated Unicode string. | |
| @param Length The maximum number of Unicode characters to compare. | |
| @retval 0 FirstString is identical to SecondString. | |
| @return others FirstString is not identical to SecondString. | |
| **/ | |
| INTN | |
| EFIAPI | |
| StrnCmp ( | |
| IN CONST CHAR16 *FirstString, | |
| IN CONST CHAR16 *SecondString, | |
| IN UINTN Length | |
| ) | |
| { | |
| if (Length == 0) { | |
| return 0; | |
| } | |
| // | |
| // ASSERT both strings are less long than PcdMaximumUnicodeStringLength. | |
| // Length tests are performed inside StrLen(). | |
| // | |
| ASSERT (StrSize (FirstString) != 0); | |
| ASSERT (StrSize (SecondString) != 0); | |
| if (PcdGet32 (PcdMaximumUnicodeStringLength) != 0) { | |
| ASSERT (Length <= PcdGet32 (PcdMaximumUnicodeStringLength)); | |
| } | |
| while ((*FirstString != L'\0') && | |
| (*SecondString != L'\0') && | |
| (*FirstString == *SecondString) && | |
| (Length > 1)) | |
| { | |
| FirstString++; | |
| SecondString++; | |
| Length--; | |
| } | |
| return *FirstString - *SecondString; | |
| } | |
| /** | |
| Returns the first occurrence of a Null-terminated Unicode sub-string | |
| in a Null-terminated Unicode string. | |
| This function scans the contents of the Null-terminated Unicode string | |
| specified by String and returns the first occurrence of SearchString. | |
| If SearchString is not found in String, then NULL is returned. If | |
| the length of SearchString is zero, then String is | |
| returned. | |
| If String is NULL, then ASSERT(). | |
| If String is not aligned on a 16-bit boundary, then ASSERT(). | |
| If SearchString is NULL, then ASSERT(). | |
| If SearchString is not aligned on a 16-bit boundary, then ASSERT(). | |
| If PcdMaximumUnicodeStringLength is not zero, and SearchString | |
| or String contains more than PcdMaximumUnicodeStringLength Unicode | |
| characters, not including the Null-terminator, then ASSERT(). | |
| @param String A pointer to a Null-terminated Unicode string. | |
| @param SearchString A pointer to a Null-terminated Unicode string to search for. | |
| @retval NULL If the SearchString does not appear in String. | |
| @return others If there is a match. | |
| **/ | |
| CHAR16 * | |
| EFIAPI | |
| StrStr ( | |
| IN CONST CHAR16 *String, | |
| IN CONST CHAR16 *SearchString | |
| ) | |
| { | |
| CONST CHAR16 *FirstMatch; | |
| CONST CHAR16 *SearchStringTmp; | |
| // | |
| // ASSERT both strings are less long than PcdMaximumUnicodeStringLength. | |
| // Length tests are performed inside StrLen(). | |
| // | |
| ASSERT (StrSize (String) != 0); | |
| ASSERT (StrSize (SearchString) != 0); | |
| if (*SearchString == L'\0') { | |
| return (CHAR16 *)String; | |
| } | |
| while (*String != L'\0') { | |
| SearchStringTmp = SearchString; | |
| FirstMatch = String; | |
| while ( (*String == *SearchStringTmp) | |
| && (*String != L'\0')) | |
| { | |
| String++; | |
| SearchStringTmp++; | |
| } | |
| if (*SearchStringTmp == L'\0') { | |
| return (CHAR16 *)FirstMatch; | |
| } | |
| if (*String == L'\0') { | |
| return NULL; | |
| } | |
| String = FirstMatch + 1; | |
| } | |
| return NULL; | |
| } | |
| /** | |
| Check if a Unicode character is a decimal character. | |
| This internal function checks if a Unicode character is a | |
| decimal character. The valid decimal character is from | |
| L'0' to L'9'. | |
| @param Char The character to check against. | |
| @retval TRUE If the Char is a decmial character. | |
| @retval FALSE If the Char is not a decmial character. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| InternalIsDecimalDigitCharacter ( | |
| IN CHAR16 Char | |
| ) | |
| { | |
| return (BOOLEAN)(Char >= L'0' && Char <= L'9'); | |
| } | |
| /** | |
| Convert a Unicode character to upper case only if | |
| it maps to a valid small-case ASCII character. | |
| This internal function only deal with Unicode character | |
| which maps to a valid small-case ASCII character, i.e. | |
| L'a' to L'z'. For other Unicode character, the input character | |
| is returned directly. | |
| @param Char The character to convert. | |
| @retval LowerCharacter If the Char is with range L'a' to L'z'. | |
| @retval Unchanged Otherwise. | |
| **/ | |
| CHAR16 | |
| EFIAPI | |
| CharToUpper ( | |
| IN CHAR16 Char | |
| ) | |
| { | |
| if ((Char >= L'a') && (Char <= L'z')) { | |
| return (CHAR16)(Char - (L'a' - L'A')); | |
| } | |
| return Char; | |
| } | |
| /** | |
| Convert a Unicode character to numerical value. | |
| This internal function only deal with Unicode character | |
| which maps to a valid hexadecimal ASII character, i.e. | |
| L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other | |
| Unicode character, the value returned does not make sense. | |
| @param Char The character to convert. | |
| @return The numerical value converted. | |
| **/ | |
| UINTN | |
| EFIAPI | |
| InternalHexCharToUintn ( | |
| IN CHAR16 Char | |
| ) | |
| { | |
| if (InternalIsDecimalDigitCharacter (Char)) { | |
| return Char - L'0'; | |
| } | |
| return (10 + CharToUpper (Char) - L'A'); | |
| } | |
| /** | |
| Check if a Unicode character is a hexadecimal character. | |
| This internal function checks if a Unicode character is a | |
| decimal character. The valid hexadecimal character is | |
| L'0' to L'9', L'a' to L'f', or L'A' to L'F'. | |
| @param Char The character to check against. | |
| @retval TRUE If the Char is a hexadecmial character. | |
| @retval FALSE If the Char is not a hexadecmial character. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| InternalIsHexaDecimalDigitCharacter ( | |
| IN CHAR16 Char | |
| ) | |
| { | |
| return (BOOLEAN)(InternalIsDecimalDigitCharacter (Char) || | |
| (Char >= L'A' && Char <= L'F') || | |
| (Char >= L'a' && Char <= L'f')); | |
| } | |
| /** | |
| Convert a Null-terminated Unicode decimal string to a value of | |
| type UINTN. | |
| This function returns a value of type UINTN by interpreting the contents | |
| of the Unicode string specified by String as a decimal number. The format | |
| of the input Unicode string String is: | |
| [spaces] [decimal digits]. | |
| The valid decimal digit character is in the range [0-9]. The | |
| function will ignore the pad space, which includes spaces or | |
| tab characters, before [decimal digits]. The running zero in the | |
| beginning of [decimal digits] will be ignored. Then, the function | |
| stops at the first character that is a not a valid decimal character | |
| or a Null-terminator, whichever one comes first. | |
| If String is NULL, then ASSERT(). | |
| If String is not aligned in a 16-bit boundary, then ASSERT(). | |
| If String has only pad spaces, then 0 is returned. | |
| If String has no pad spaces or valid decimal digits, | |
| then 0 is returned. | |
| If the number represented by String overflows according | |
| to the range defined by UINTN, then MAX_UINTN is returned. | |
| If PcdMaximumUnicodeStringLength is not zero, and String contains | |
| more than PcdMaximumUnicodeStringLength Unicode characters, not including | |
| the Null-terminator, then ASSERT(). | |
| @param String A pointer to a Null-terminated Unicode string. | |
| @retval Value translated from String. | |
| **/ | |
| UINTN | |
| EFIAPI | |
| StrDecimalToUintn ( | |
| IN CONST CHAR16 *String | |
| ) | |
| { | |
| UINTN Result; | |
| if (RETURN_ERROR (StrDecimalToUintnS (String, (CHAR16 **)NULL, &Result))) { | |
| return MAX_UINTN; | |
| } | |
| return Result; | |
| } | |
| /** | |
| Convert a Null-terminated Unicode decimal string to a value of | |
| type UINT64. | |
| This function returns a value of type UINT64 by interpreting the contents | |
| of the Unicode string specified by String as a decimal number. The format | |
| of the input Unicode string String is: | |
| [spaces] [decimal digits]. | |
| The valid decimal digit character is in the range [0-9]. The | |
| function will ignore the pad space, which includes spaces or | |
| tab characters, before [decimal digits]. The running zero in the | |
| beginning of [decimal digits] will be ignored. Then, the function | |
| stops at the first character that is a not a valid decimal character | |
| or a Null-terminator, whichever one comes first. | |
| If String is NULL, then ASSERT(). | |
| If String is not aligned in a 16-bit boundary, then ASSERT(). | |
| If String has only pad spaces, then 0 is returned. | |
| If String has no pad spaces or valid decimal digits, | |
| then 0 is returned. | |
| If the number represented by String overflows according | |
| to the range defined by UINT64, then MAX_UINT64 is returned. | |
| If PcdMaximumUnicodeStringLength is not zero, and String contains | |
| more than PcdMaximumUnicodeStringLength Unicode characters, not including | |
| the Null-terminator, then ASSERT(). | |
| @param String A pointer to a Null-terminated Unicode string. | |
| @retval Value translated from String. | |
| **/ | |
| UINT64 | |
| EFIAPI | |
| StrDecimalToUint64 ( | |
| IN CONST CHAR16 *String | |
| ) | |
| { | |
| UINT64 Result; | |
| if (RETURN_ERROR (StrDecimalToUint64S (String, (CHAR16 **)NULL, &Result))) { | |
| return MAX_UINT64; | |
| } | |
| return Result; | |
| } | |
| /** | |
| Convert a Null-terminated Unicode hexadecimal string to a value of type UINTN. | |
| This function returns a value of type UINTN by interpreting the contents | |
| of the Unicode string specified by String as a hexadecimal number. | |
| The format of the input Unicode string String is: | |
| [spaces][zeros][x][hexadecimal digits]. | |
| The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. | |
| The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. | |
| If "x" appears in the input string, it must be prefixed with at least one 0. | |
| The function will ignore the pad space, which includes spaces or tab characters, | |
| before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or | |
| [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the | |
| first valid hexadecimal digit. Then, the function stops at the first character that is | |
| a not a valid hexadecimal character or NULL, whichever one comes first. | |
| If String is NULL, then ASSERT(). | |
| If String is not aligned in a 16-bit boundary, then ASSERT(). | |
| If String has only pad spaces, then zero is returned. | |
| If String has no leading pad spaces, leading zeros or valid hexadecimal digits, | |
| then zero is returned. | |
| If the number represented by String overflows according to the range defined by | |
| UINTN, then MAX_UINTN is returned. | |
| If PcdMaximumUnicodeStringLength is not zero, and String contains more than | |
| PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, | |
| then ASSERT(). | |
| @param String A pointer to a Null-terminated Unicode string. | |
| @retval Value translated from String. | |
| **/ | |
| UINTN | |
| EFIAPI | |
| StrHexToUintn ( | |
| IN CONST CHAR16 *String | |
| ) | |
| { | |
| UINTN Result; | |
| if (RETURN_ERROR (StrHexToUintnS (String, (CHAR16 **)NULL, &Result))) { | |
| return MAX_UINTN; | |
| } | |
| return Result; | |
| } | |
| /** | |
| Convert a Null-terminated Unicode hexadecimal string to a value of type UINT64. | |
| This function returns a value of type UINT64 by interpreting the contents | |
| of the Unicode string specified by String as a hexadecimal number. | |
| The format of the input Unicode string String is | |
| [spaces][zeros][x][hexadecimal digits]. | |
| The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. | |
| The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. | |
| If "x" appears in the input string, it must be prefixed with at least one 0. | |
| The function will ignore the pad space, which includes spaces or tab characters, | |
| before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or | |
| [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the | |
| first valid hexadecimal digit. Then, the function stops at the first character that is | |
| a not a valid hexadecimal character or NULL, whichever one comes first. | |
| If String is NULL, then ASSERT(). | |
| If String is not aligned in a 16-bit boundary, then ASSERT(). | |
| If String has only pad spaces, then zero is returned. | |
| If String has no leading pad spaces, leading zeros or valid hexadecimal digits, | |
| then zero is returned. | |
| If the number represented by String overflows according to the range defined by | |
| UINT64, then MAX_UINT64 is returned. | |
| If PcdMaximumUnicodeStringLength is not zero, and String contains more than | |
| PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, | |
| then ASSERT(). | |
| @param String A pointer to a Null-terminated Unicode string. | |
| @retval Value translated from String. | |
| **/ | |
| UINT64 | |
| EFIAPI | |
| StrHexToUint64 ( | |
| IN CONST CHAR16 *String | |
| ) | |
| { | |
| UINT64 Result; | |
| if (RETURN_ERROR (StrHexToUint64S (String, (CHAR16 **)NULL, &Result))) { | |
| return MAX_UINT64; | |
| } | |
| return Result; | |
| } | |
| /** | |
| Check if a ASCII character is a decimal character. | |
| This internal function checks if a Unicode character is a | |
| decimal character. The valid decimal character is from | |
| '0' to '9'. | |
| @param Char The character to check against. | |
| @retval TRUE If the Char is a decmial character. | |
| @retval FALSE If the Char is not a decmial character. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| InternalAsciiIsDecimalDigitCharacter ( | |
| IN CHAR8 Char | |
| ) | |
| { | |
| return (BOOLEAN)(Char >= '0' && Char <= '9'); | |
| } | |
| /** | |
| Check if a ASCII character is a hexadecimal character. | |
| This internal function checks if a ASCII character is a | |
| decimal character. The valid hexadecimal character is | |
| L'0' to L'9', L'a' to L'f', or L'A' to L'F'. | |
| @param Char The character to check against. | |
| @retval TRUE If the Char is a hexadecmial character. | |
| @retval FALSE If the Char is not a hexadecmial character. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| InternalAsciiIsHexaDecimalDigitCharacter ( | |
| IN CHAR8 Char | |
| ) | |
| { | |
| return (BOOLEAN)(InternalAsciiIsDecimalDigitCharacter (Char) || | |
| (Char >= 'A' && Char <= 'F') || | |
| (Char >= 'a' && Char <= 'f')); | |
| } | |
| /** | |
| Returns the length of a Null-terminated ASCII string. | |
| This function returns the number of ASCII characters in the Null-terminated | |
| ASCII string specified by String. | |
| If Length > 0 and Destination is NULL, then ASSERT(). | |
| If Length > 0 and Source is NULL, then ASSERT(). | |
| If PcdMaximumAsciiStringLength is not zero and String contains more than | |
| PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, | |
| then ASSERT(). | |
| @param String A pointer to a Null-terminated ASCII string. | |
| @return The length of String. | |
| **/ | |
| UINTN | |
| EFIAPI | |
| AsciiStrLen ( | |
| IN CONST CHAR8 *String | |
| ) | |
| { | |
| UINTN Length; | |
| ASSERT (String != NULL); | |
| for (Length = 0; *String != '\0'; String++, Length++) { | |
| // | |
| // If PcdMaximumUnicodeStringLength is not zero, | |
| // length should not more than PcdMaximumUnicodeStringLength | |
| // | |
| if (PcdGet32 (PcdMaximumAsciiStringLength) != 0) { | |
| ASSERT (Length < PcdGet32 (PcdMaximumAsciiStringLength)); | |
| } | |
| } | |
| return Length; | |
| } | |
| /** | |
| Returns the size of a Null-terminated ASCII string in bytes, including the | |
| Null terminator. | |
| This function returns the size, in bytes, of the Null-terminated ASCII string | |
| specified by String. | |
| If String is NULL, then ASSERT(). | |
| If PcdMaximumAsciiStringLength is not zero and String contains more than | |
| PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, | |
| then ASSERT(). | |
| @param String A pointer to a Null-terminated ASCII string. | |
| @return The size of String. | |
| **/ | |
| UINTN | |
| EFIAPI | |
| AsciiStrSize ( | |
| IN CONST CHAR8 *String | |
| ) | |
| { | |
| return (AsciiStrLen (String) + 1) * sizeof (*String); | |
| } | |
| /** | |
| Compares two Null-terminated ASCII strings, and returns the difference | |
| between the first mismatched ASCII characters. | |
| This function compares the Null-terminated ASCII string FirstString to the | |
| Null-terminated ASCII string SecondString. If FirstString is identical to | |
| SecondString, then 0 is returned. Otherwise, the value returned is the first | |
| mismatched ASCII character in SecondString subtracted from the first | |
| mismatched ASCII character in FirstString. | |
| If FirstString is NULL, then ASSERT(). | |
| If SecondString is NULL, then ASSERT(). | |
| If PcdMaximumAsciiStringLength is not zero and FirstString contains more than | |
| PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, | |
| then ASSERT(). | |
| If PcdMaximumAsciiStringLength is not zero and SecondString contains more | |
| than PcdMaximumAsciiStringLength ASCII characters, not including the | |
| Null-terminator, then ASSERT(). | |
| @param FirstString A pointer to a Null-terminated ASCII string. | |
| @param SecondString A pointer to a Null-terminated ASCII string. | |
| @retval ==0 FirstString is identical to SecondString. | |
| @retval !=0 FirstString is not identical to SecondString. | |
| **/ | |
| INTN | |
| EFIAPI | |
| AsciiStrCmp ( | |
| IN CONST CHAR8 *FirstString, | |
| IN CONST CHAR8 *SecondString | |
| ) | |
| { | |
| // | |
| // ASSERT both strings are less long than PcdMaximumAsciiStringLength | |
| // | |
| ASSERT (AsciiStrSize (FirstString)); | |
| ASSERT (AsciiStrSize (SecondString)); | |
| while ((*FirstString != '\0') && (*FirstString == *SecondString)) { | |
| FirstString++; | |
| SecondString++; | |
| } | |
| return *FirstString - *SecondString; | |
| } | |
| /** | |
| Converts a lowercase Ascii character to upper one. | |
| If Chr is lowercase Ascii character, then converts it to upper one. | |
| If Value >= 0xA0, then ASSERT(). | |
| If (Value & 0x0F) >= 0x0A, then ASSERT(). | |
| @param Chr one Ascii character | |
| @return The uppercase value of Ascii character | |
| **/ | |
| CHAR8 | |
| EFIAPI | |
| AsciiCharToUpper ( | |
| IN CHAR8 Chr | |
| ) | |
| { | |
| return (UINT8)((Chr >= 'a' && Chr <= 'z') ? Chr - ('a' - 'A') : Chr); | |
| } | |
| /** | |
| Convert a ASCII character to numerical value. | |
| This internal function only deal with Unicode character | |
| which maps to a valid hexadecimal ASII character, i.e. | |
| '0' to '9', 'a' to 'f' or 'A' to 'F'. For other | |
| ASCII character, the value returned does not make sense. | |
| @param Char The character to convert. | |
| @return The numerical value converted. | |
| **/ | |
| UINTN | |
| EFIAPI | |
| InternalAsciiHexCharToUintn ( | |
| IN CHAR8 Char | |
| ) | |
| { | |
| if (InternalIsDecimalDigitCharacter (Char)) { | |
| return Char - '0'; | |
| } | |
| return (10 + AsciiCharToUpper (Char) - 'A'); | |
| } | |
| /** | |
| Performs a case insensitive comparison of two Null-terminated ASCII strings, | |
| and returns the difference between the first mismatched ASCII characters. | |
| This function performs a case insensitive comparison of the Null-terminated | |
| ASCII string FirstString to the Null-terminated ASCII string SecondString. If | |
| FirstString is identical to SecondString, then 0 is returned. Otherwise, the | |
| value returned is the first mismatched lower case ASCII character in | |
| SecondString subtracted from the first mismatched lower case ASCII character | |
| in FirstString. | |
| If FirstString is NULL, then ASSERT(). | |
| If SecondString is NULL, then ASSERT(). | |
| If PcdMaximumAsciiStringLength is not zero and FirstString contains more than | |
| PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, | |
| then ASSERT(). | |
| If PcdMaximumAsciiStringLength is not zero and SecondString contains more | |
| than PcdMaximumAsciiStringLength ASCII characters, not including the | |
| Null-terminator, then ASSERT(). | |
| @param FirstString A pointer to a Null-terminated ASCII string. | |
| @param SecondString A pointer to a Null-terminated ASCII string. | |
| @retval ==0 FirstString is identical to SecondString using case insensitive | |
| comparisons. | |
| @retval !=0 FirstString is not identical to SecondString using case | |
| insensitive comparisons. | |
| **/ | |
| INTN | |
| EFIAPI | |
| AsciiStriCmp ( | |
| IN CONST CHAR8 *FirstString, | |
| IN CONST CHAR8 *SecondString | |
| ) | |
| { | |
| CHAR8 UpperFirstString; | |
| CHAR8 UpperSecondString; | |
| // | |
| // ASSERT both strings are less long than PcdMaximumAsciiStringLength | |
| // | |
| ASSERT (AsciiStrSize (FirstString)); | |
| ASSERT (AsciiStrSize (SecondString)); | |
| UpperFirstString = AsciiCharToUpper (*FirstString); | |
| UpperSecondString = AsciiCharToUpper (*SecondString); | |
| while ((*FirstString != '\0') && (*SecondString != '\0') && (UpperFirstString == UpperSecondString)) { | |
| FirstString++; | |
| SecondString++; | |
| UpperFirstString = AsciiCharToUpper (*FirstString); | |
| UpperSecondString = AsciiCharToUpper (*SecondString); | |
| } | |
| return UpperFirstString - UpperSecondString; | |
| } | |
| /** | |
| Compares two Null-terminated ASCII strings with maximum lengths, and returns | |
| the difference between the first mismatched ASCII characters. | |
| This function compares the Null-terminated ASCII string FirstString to the | |
| Null-terminated ASCII string SecondString. At most, Length ASCII characters | |
| will be compared. If Length is 0, then 0 is returned. If FirstString is | |
| identical to SecondString, then 0 is returned. Otherwise, the value returned | |
| is the first mismatched ASCII character in SecondString subtracted from the | |
| first mismatched ASCII character in FirstString. | |
| If Length > 0 and FirstString is NULL, then ASSERT(). | |
| If Length > 0 and SecondString is NULL, then ASSERT(). | |
| If PcdMaximumAsciiStringLength is not zero, and Length is greater than | |
| PcdMaximumAsciiStringLength, then ASSERT(). | |
| If PcdMaximumAsciiStringLength is not zero, and FirstString contains more than | |
| PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, | |
| then ASSERT(). | |
| If PcdMaximumAsciiStringLength is not zero, and SecondString contains more than | |
| PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, | |
| then ASSERT(). | |
| @param FirstString A pointer to a Null-terminated ASCII string. | |
| @param SecondString A pointer to a Null-terminated ASCII string. | |
| @param Length The maximum number of ASCII characters for compare. | |
| @retval ==0 FirstString is identical to SecondString. | |
| @retval !=0 FirstString is not identical to SecondString. | |
| **/ | |
| INTN | |
| EFIAPI | |
| AsciiStrnCmp ( | |
| IN CONST CHAR8 *FirstString, | |
| IN CONST CHAR8 *SecondString, | |
| IN UINTN Length | |
| ) | |
| { | |
| if (Length == 0) { | |
| return 0; | |
| } | |
| // | |
| // ASSERT both strings are less long than PcdMaximumAsciiStringLength | |
| // | |
| ASSERT (AsciiStrSize (FirstString)); | |
| ASSERT (AsciiStrSize (SecondString)); | |
| if (PcdGet32 (PcdMaximumAsciiStringLength) != 0) { | |
| ASSERT (Length <= PcdGet32 (PcdMaximumAsciiStringLength)); | |
| } | |
| while ((*FirstString != '\0') && | |
| (*SecondString != '\0') && | |
| (*FirstString == *SecondString) && | |
| (Length > 1)) | |
| { | |
| FirstString++; | |
| SecondString++; | |
| Length--; | |
| } | |
| return *FirstString - *SecondString; | |
| } | |
| /** | |
| Returns the first occurrence of a Null-terminated ASCII sub-string | |
| in a Null-terminated ASCII string. | |
| This function scans the contents of the ASCII string specified by String | |
| and returns the first occurrence of SearchString. If SearchString is not | |
| found in String, then NULL is returned. If the length of SearchString is zero, | |
| then String is returned. | |
| If String is NULL, then ASSERT(). | |
| If SearchString is NULL, then ASSERT(). | |
| If PcdMaximumAsciiStringLength is not zero, and SearchString or | |
| String contains more than PcdMaximumAsciiStringLength Unicode characters | |
| not including the Null-terminator, then ASSERT(). | |
| @param String A pointer to a Null-terminated ASCII string. | |
| @param SearchString A pointer to a Null-terminated ASCII string to search for. | |
| @retval NULL If the SearchString does not appear in String. | |
| @retval others If there is a match return the first occurrence of SearchingString. | |
| If the length of SearchString is zero,return String. | |
| **/ | |
| CHAR8 * | |
| EFIAPI | |
| AsciiStrStr ( | |
| IN CONST CHAR8 *String, | |
| IN CONST CHAR8 *SearchString | |
| ) | |
| { | |
| CONST CHAR8 *FirstMatch; | |
| CONST CHAR8 *SearchStringTmp; | |
| // | |
| // ASSERT both strings are less long than PcdMaximumAsciiStringLength | |
| // | |
| ASSERT (AsciiStrSize (String) != 0); | |
| ASSERT (AsciiStrSize (SearchString) != 0); | |
| if (*SearchString == '\0') { | |
| return (CHAR8 *)String; | |
| } | |
| while (*String != '\0') { | |
| SearchStringTmp = SearchString; | |
| FirstMatch = String; | |
| while ( (*String == *SearchStringTmp) | |
| && (*String != '\0')) | |
| { | |
| String++; | |
| SearchStringTmp++; | |
| } | |
| if (*SearchStringTmp == '\0') { | |
| return (CHAR8 *)FirstMatch; | |
| } | |
| if (*String == '\0') { | |
| return NULL; | |
| } | |
| String = FirstMatch + 1; | |
| } | |
| return NULL; | |
| } | |
| /** | |
| Convert a Null-terminated ASCII decimal string to a value of type | |
| UINTN. | |
| This function returns a value of type UINTN by interpreting the contents | |
| of the ASCII string String as a decimal number. The format of the input | |
| ASCII string String is: | |
| [spaces] [decimal digits]. | |
| The valid decimal digit character is in the range [0-9]. The function will | |
| ignore the pad space, which includes spaces or tab characters, before the digits. | |
| The running zero in the beginning of [decimal digits] will be ignored. Then, the | |
| function stops at the first character that is a not a valid decimal character or | |
| Null-terminator, whichever on comes first. | |
| If String has only pad spaces, then 0 is returned. | |
| If String has no pad spaces or valid decimal digits, then 0 is returned. | |
| If the number represented by String overflows according to the range defined by | |
| UINTN, then MAX_UINTN is returned. | |
| If String is NULL, then ASSERT(). | |
| If PcdMaximumAsciiStringLength is not zero, and String contains more than | |
| PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, | |
| then ASSERT(). | |
| @param String A pointer to a Null-terminated ASCII string. | |
| @retval Value translated from String. | |
| **/ | |
| UINTN | |
| EFIAPI | |
| AsciiStrDecimalToUintn ( | |
| IN CONST CHAR8 *String | |
| ) | |
| { | |
| UINTN Result; | |
| if (RETURN_ERROR (AsciiStrDecimalToUintnS (String, (CHAR8 **)NULL, &Result))) { | |
| return MAX_UINTN; | |
| } | |
| return Result; | |
| } | |
| /** | |
| Convert a Null-terminated ASCII decimal string to a value of type | |
| UINT64. | |
| This function returns a value of type UINT64 by interpreting the contents | |
| of the ASCII string String as a decimal number. The format of the input | |
| ASCII string String is: | |
| [spaces] [decimal digits]. | |
| The valid decimal digit character is in the range [0-9]. The function will | |
| ignore the pad space, which includes spaces or tab characters, before the digits. | |
| The running zero in the beginning of [decimal digits] will be ignored. Then, the | |
| function stops at the first character that is a not a valid decimal character or | |
| Null-terminator, whichever on comes first. | |
| If String has only pad spaces, then 0 is returned. | |
| If String has no pad spaces or valid decimal digits, then 0 is returned. | |
| If the number represented by String overflows according to the range defined by | |
| UINT64, then MAX_UINT64 is returned. | |
| If String is NULL, then ASSERT(). | |
| If PcdMaximumAsciiStringLength is not zero, and String contains more than | |
| PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, | |
| then ASSERT(). | |
| @param String A pointer to a Null-terminated ASCII string. | |
| @retval Value translated from String. | |
| **/ | |
| UINT64 | |
| EFIAPI | |
| AsciiStrDecimalToUint64 ( | |
| IN CONST CHAR8 *String | |
| ) | |
| { | |
| UINT64 Result; | |
| if (RETURN_ERROR (AsciiStrDecimalToUint64S (String, (CHAR8 **)NULL, &Result))) { | |
| return MAX_UINT64; | |
| } | |
| return Result; | |
| } | |
| /** | |
| Convert a Null-terminated ASCII hexadecimal string to a value of type UINTN. | |
| This function returns a value of type UINTN by interpreting the contents of | |
| the ASCII string String as a hexadecimal number. The format of the input ASCII | |
| string String is: | |
| [spaces][zeros][x][hexadecimal digits]. | |
| The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. | |
| The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If "x" | |
| appears in the input string, it must be prefixed with at least one 0. The function | |
| will ignore the pad space, which includes spaces or tab characters, before [zeros], | |
| [x] or [hexadecimal digits]. The running zero before [x] or [hexadecimal digits] | |
| will be ignored. Then, the decoding starts after [x] or the first valid hexadecimal | |
| digit. Then, the function stops at the first character that is a not a valid | |
| hexadecimal character or Null-terminator, whichever on comes first. | |
| If String has only pad spaces, then 0 is returned. | |
| If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then | |
| 0 is returned. | |
| If the number represented by String overflows according to the range defined by UINTN, | |
| then MAX_UINTN is returned. | |
| If String is NULL, then ASSERT(). | |
| If PcdMaximumAsciiStringLength is not zero, | |
| and String contains more than PcdMaximumAsciiStringLength ASCII characters not including | |
| the Null-terminator, then ASSERT(). | |
| @param String A pointer to a Null-terminated ASCII string. | |
| @retval Value translated from String. | |
| **/ | |
| UINTN | |
| EFIAPI | |
| AsciiStrHexToUintn ( | |
| IN CONST CHAR8 *String | |
| ) | |
| { | |
| UINTN Result; | |
| if (RETURN_ERROR (AsciiStrHexToUintnS (String, (CHAR8 **)NULL, &Result))) { | |
| return MAX_UINTN; | |
| } | |
| return Result; | |
| } | |
| /** | |
| Convert a Null-terminated ASCII hexadecimal string to a value of type UINT64. | |
| This function returns a value of type UINT64 by interpreting the contents of | |
| the ASCII string String as a hexadecimal number. The format of the input ASCII | |
| string String is: | |
| [spaces][zeros][x][hexadecimal digits]. | |
| The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. | |
| The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If "x" | |
| appears in the input string, it must be prefixed with at least one 0. The function | |
| will ignore the pad space, which includes spaces or tab characters, before [zeros], | |
| [x] or [hexadecimal digits]. The running zero before [x] or [hexadecimal digits] | |
| will be ignored. Then, the decoding starts after [x] or the first valid hexadecimal | |
| digit. Then, the function stops at the first character that is a not a valid | |
| hexadecimal character or Null-terminator, whichever on comes first. | |
| If String has only pad spaces, then 0 is returned. | |
| If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then | |
| 0 is returned. | |
| If the number represented by String overflows according to the range defined by UINT64, | |
| then MAX_UINT64 is returned. | |
| If String is NULL, then ASSERT(). | |
| If PcdMaximumAsciiStringLength is not zero, | |
| and String contains more than PcdMaximumAsciiStringLength ASCII characters not including | |
| the Null-terminator, then ASSERT(). | |
| @param String A pointer to a Null-terminated ASCII string. | |
| @retval Value translated from String. | |
| **/ | |
| UINT64 | |
| EFIAPI | |
| AsciiStrHexToUint64 ( | |
| IN CONST CHAR8 *String | |
| ) | |
| { | |
| UINT64 Result; | |
| if (RETURN_ERROR (AsciiStrHexToUint64S (String, (CHAR8 **)NULL, &Result))) { | |
| return MAX_UINT64; | |
| } | |
| return Result; | |
| } | |
| STATIC CHAR8 EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
| "abcdefghijklmnopqrstuvwxyz" | |
| "0123456789+/"; | |
| /** | |
| Convert binary data to a Base64 encoded ascii string based on RFC4648. | |
| Produce a Null-terminated Ascii string in the output buffer specified by Destination and DestinationSize. | |
| The Ascii string is produced by converting the data string specified by Source and SourceLength. | |
| @param Source Input UINT8 data | |
| @param SourceLength Number of UINT8 bytes of data | |
| @param Destination Pointer to output string buffer | |
| @param DestinationSize Size of ascii buffer. Set to 0 to get the size needed. | |
| Caller is responsible for passing in buffer of DestinationSize | |
| @retval RETURN_SUCCESS When ascii buffer is filled in. | |
| @retval RETURN_INVALID_PARAMETER If Source is NULL or DestinationSize is NULL. | |
| @retval RETURN_INVALID_PARAMETER If SourceLength or DestinationSize is bigger than (MAX_ADDRESS - (UINTN)Destination). | |
| @retval RETURN_BUFFER_TOO_SMALL If SourceLength is 0 and DestinationSize is <1. | |
| @retval RETURN_BUFFER_TOO_SMALL If Destination is NULL or DestinationSize is smaller than required buffersize. | |
| **/ | |
| RETURN_STATUS | |
| EFIAPI | |
| Base64Encode ( | |
| IN CONST UINT8 *Source, | |
| IN UINTN SourceLength, | |
| OUT CHAR8 *Destination OPTIONAL, | |
| IN OUT UINTN *DestinationSize | |
| ) | |
| { | |
| UINTN RequiredSize; | |
| UINTN Left; | |
| // | |
| // Check pointers, and SourceLength is valid | |
| // | |
| if ((Source == NULL) || (DestinationSize == NULL)) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| // | |
| // Allow for RFC 4648 test vector 1 | |
| // | |
| if (SourceLength == 0) { | |
| if (*DestinationSize < 1) { | |
| *DestinationSize = 1; | |
| return RETURN_BUFFER_TOO_SMALL; | |
| } | |
| *DestinationSize = 1; | |
| *Destination = '\0'; | |
| return RETURN_SUCCESS; | |
| } | |
| // | |
| // Check if SourceLength or DestinationSize is valid | |
| // | |
| if ((SourceLength >= (MAX_ADDRESS - (UINTN)Source)) || (*DestinationSize >= (MAX_ADDRESS - (UINTN)Destination))) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| // | |
| // 4 ascii per 3 bytes + NULL | |
| // | |
| RequiredSize = ((SourceLength + 2) / 3) * 4 + 1; | |
| if ((Destination == NULL) || (*DestinationSize < RequiredSize)) { | |
| *DestinationSize = RequiredSize; | |
| return RETURN_BUFFER_TOO_SMALL; | |
| } | |
| Left = SourceLength; | |
| // | |
| // Encode 24 bits (three bytes) into 4 ascii characters | |
| // | |
| while (Left >= 3) { | |
| *Destination++ = EncodingTable[(Source[0] & 0xfc) >> 2]; | |
| *Destination++ = EncodingTable[((Source[0] & 0x03) << 4) + ((Source[1] & 0xf0) >> 4)]; | |
| *Destination++ = EncodingTable[((Source[1] & 0x0f) << 2) + ((Source[2] & 0xc0) >> 6)]; | |
| *Destination++ = EncodingTable[(Source[2] & 0x3f)]; | |
| Left -= 3; | |
| Source += 3; | |
| } | |
| // | |
| // Handle the remainder, and add padding '=' characters as necessary. | |
| // | |
| switch (Left) { | |
| case 0: | |
| // | |
| // No bytes Left, done. | |
| // | |
| break; | |
| case 1: | |
| // | |
| // One more data byte, two pad characters | |
| // | |
| *Destination++ = EncodingTable[(Source[0] & 0xfc) >> 2]; | |
| *Destination++ = EncodingTable[((Source[0] & 0x03) << 4)]; | |
| *Destination++ = '='; | |
| *Destination++ = '='; | |
| break; | |
| case 2: | |
| // | |
| // Two more data bytes, and one pad character | |
| // | |
| *Destination++ = EncodingTable[(Source[0] & 0xfc) >> 2]; | |
| *Destination++ = EncodingTable[((Source[0] & 0x03) << 4) + ((Source[1] & 0xf0) >> 4)]; | |
| *Destination++ = EncodingTable[((Source[1] & 0x0f) << 2)]; | |
| *Destination++ = '='; | |
| break; | |
| } | |
| // | |
| // Add terminating NULL | |
| // | |
| *Destination = '\0'; | |
| return RETURN_SUCCESS; | |
| } | |
| /** | |
| Decode Base64 ASCII encoded data to 8-bit binary representation, based on | |
| RFC4648. | |
| Decoding occurs according to "Table 1: The Base 64 Alphabet" in RFC4648. | |
| Whitespace is ignored at all positions: | |
| - 0x09 ('\t') horizontal tab | |
| - 0x0A ('\n') new line | |
| - 0x0B ('\v') vertical tab | |
| - 0x0C ('\f') form feed | |
| - 0x0D ('\r') carriage return | |
| - 0x20 (' ') space | |
| The minimum amount of required padding (with ASCII 0x3D, '=') is tolerated | |
| and enforced at the end of the Base64 ASCII encoded data, and only there. | |
| Other characters outside of the encoding alphabet cause the function to | |
| reject the Base64 ASCII encoded data. | |
| @param[in] Source Array of CHAR8 elements containing the Base64 | |
| ASCII encoding. May be NULL if SourceSize is | |
| zero. | |
| @param[in] SourceSize Number of CHAR8 elements in Source. | |
| @param[out] Destination Array of UINT8 elements receiving the decoded | |
| 8-bit binary representation. Allocated by the | |
| caller. May be NULL if DestinationSize is | |
| zero on input. If NULL, decoding is | |
| performed, but the 8-bit binary | |
| representation is not stored. If non-NULL and | |
| the function returns an error, the contents | |
| of Destination are indeterminate. | |
| @param[in,out] DestinationSize On input, the number of UINT8 elements that | |
| the caller allocated for Destination. On | |
| output, if the function returns | |
| RETURN_SUCCESS or RETURN_BUFFER_TOO_SMALL, | |
| the number of UINT8 elements that are | |
| required for decoding the Base64 ASCII | |
| representation. If the function returns a | |
| value different from both RETURN_SUCCESS and | |
| RETURN_BUFFER_TOO_SMALL, then DestinationSize | |
| is indeterminate on output. | |
| @retval RETURN_SUCCESS SourceSize CHAR8 elements at Source have | |
| been decoded to on-output DestinationSize | |
| UINT8 elements at Destination. Note that | |
| RETURN_SUCCESS covers the case when | |
| DestinationSize is zero on input, and | |
| Source decodes to zero bytes (due to | |
| containing at most ignored whitespace). | |
| @retval RETURN_BUFFER_TOO_SMALL The input value of DestinationSize is not | |
| large enough for decoding SourceSize CHAR8 | |
| elements at Source. The required number of | |
| UINT8 elements has been stored to | |
| DestinationSize. | |
| @retval RETURN_INVALID_PARAMETER DestinationSize is NULL. | |
| @retval RETURN_INVALID_PARAMETER Source is NULL, but SourceSize is not zero. | |
| @retval RETURN_INVALID_PARAMETER Destination is NULL, but DestinationSize is | |
| not zero on input. | |
| @retval RETURN_INVALID_PARAMETER Source is non-NULL, and (Source + | |
| SourceSize) would wrap around MAX_ADDRESS. | |
| @retval RETURN_INVALID_PARAMETER Destination is non-NULL, and (Destination + | |
| DestinationSize) would wrap around | |
| MAX_ADDRESS, as specified on input. | |
| @retval RETURN_INVALID_PARAMETER None of Source and Destination are NULL, | |
| and CHAR8[SourceSize] at Source overlaps | |
| UINT8[DestinationSize] at Destination, as | |
| specified on input. | |
| @retval RETURN_INVALID_PARAMETER Invalid CHAR8 element encountered in | |
| Source. | |
| **/ | |
| RETURN_STATUS | |
| EFIAPI | |
| Base64Decode ( | |
| IN CONST CHAR8 *Source OPTIONAL, | |
| IN UINTN SourceSize, | |
| OUT UINT8 *Destination OPTIONAL, | |
| IN OUT UINTN *DestinationSize | |
| ) | |
| { | |
| BOOLEAN PaddingMode; | |
| UINTN SixBitGroupsConsumed; | |
| UINT32 Accumulator; | |
| UINTN OriginalDestinationSize; | |
| UINTN SourceIndex; | |
| CHAR8 SourceChar; | |
| UINT32 Base64Value; | |
| UINT8 DestinationOctet; | |
| if (DestinationSize == NULL) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| // | |
| // Check Source array validity. | |
| // | |
| if (Source == NULL) { | |
| if (SourceSize > 0) { | |
| // | |
| // At least one CHAR8 element at NULL Source. | |
| // | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| } else if (SourceSize > MAX_ADDRESS - (UINTN)Source) { | |
| // | |
| // Non-NULL Source, but it wraps around. | |
| // | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| // | |
| // Check Destination array validity. | |
| // | |
| if (Destination == NULL) { | |
| if (*DestinationSize > 0) { | |
| // | |
| // At least one UINT8 element at NULL Destination. | |
| // | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| } else if (*DestinationSize > MAX_ADDRESS - (UINTN)Destination) { | |
| // | |
| // Non-NULL Destination, but it wraps around. | |
| // | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| // | |
| // Check for overlap. | |
| // | |
| if ((Source != NULL) && (Destination != NULL)) { | |
| // | |
| // Both arrays have been provided, and we know from earlier that each array | |
| // is valid in itself. | |
| // | |
| if ((UINTN)Source + SourceSize <= (UINTN)Destination) { | |
| // | |
| // Source array precedes Destination array, OK. | |
| // | |
| } else if ((UINTN)Destination + *DestinationSize <= (UINTN)Source) { | |
| // | |
| // Destination array precedes Source array, OK. | |
| // | |
| } else { | |
| // | |
| // Overlap. | |
| // | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| } | |
| // | |
| // Decoding loop setup. | |
| // | |
| PaddingMode = FALSE; | |
| SixBitGroupsConsumed = 0; | |
| Accumulator = 0; | |
| OriginalDestinationSize = *DestinationSize; | |
| *DestinationSize = 0; | |
| // | |
| // Decoding loop. | |
| // | |
| for (SourceIndex = 0; SourceIndex < SourceSize; SourceIndex++) { | |
| SourceChar = Source[SourceIndex]; | |
| // | |
| // Whitespace is ignored at all positions (regardless of padding mode). | |
| // | |
| if ((SourceChar == '\t') || (SourceChar == '\n') || (SourceChar == '\v') || | |
| (SourceChar == '\f') || (SourceChar == '\r') || (SourceChar == ' ')) | |
| { | |
| continue; | |
| } | |
| // | |
| // If we're in padding mode, accept another padding character, as long as | |
| // that padding character completes the quantum. This completes case (2) | |
| // from RFC4648, Chapter 4. "Base 64 Encoding": | |
| // | |
| // (2) The final quantum of encoding input is exactly 8 bits; here, the | |
| // final unit of encoded output will be two characters followed by two | |
| // "=" padding characters. | |
| // | |
| if (PaddingMode) { | |
| if ((SourceChar == '=') && (SixBitGroupsConsumed == 3)) { | |
| SixBitGroupsConsumed = 0; | |
| continue; | |
| } | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| // | |
| // When not in padding mode, decode Base64Value based on RFC4648, "Table 1: | |
| // The Base 64 Alphabet". | |
| // | |
| if (('A' <= SourceChar) && (SourceChar <= 'Z')) { | |
| Base64Value = SourceChar - 'A'; | |
| } else if (('a' <= SourceChar) && (SourceChar <= 'z')) { | |
| Base64Value = 26 + (SourceChar - 'a'); | |
| } else if (('0' <= SourceChar) && (SourceChar <= '9')) { | |
| Base64Value = 52 + (SourceChar - '0'); | |
| } else if (SourceChar == '+') { | |
| Base64Value = 62; | |
| } else if (SourceChar == '/') { | |
| Base64Value = 63; | |
| } else if (SourceChar == '=') { | |
| // | |
| // Enter padding mode. | |
| // | |
| PaddingMode = TRUE; | |
| if (SixBitGroupsConsumed == 2) { | |
| // | |
| // If we have consumed two 6-bit groups from the current quantum before | |
| // encountering the first padding character, then this is case (2) from | |
| // RFC4648, Chapter 4. "Base 64 Encoding". Bump SixBitGroupsConsumed, | |
| // and we'll enforce another padding character. | |
| // | |
| SixBitGroupsConsumed = 3; | |
| } else if (SixBitGroupsConsumed == 3) { | |
| // | |
| // If we have consumed three 6-bit groups from the current quantum | |
| // before encountering the first padding character, then this is case | |
| // (3) from RFC4648, Chapter 4. "Base 64 Encoding". The quantum is now | |
| // complete. | |
| // | |
| SixBitGroupsConsumed = 0; | |
| } else { | |
| // | |
| // Padding characters are not allowed at the first two positions of a | |
| // quantum. | |
| // | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| // | |
| // Wherever in a quantum we enter padding mode, we enforce the padding | |
| // bits pending in the accumulator -- from the last 6-bit group just | |
| // preceding the padding character -- to be zero. Refer to RFC4648, | |
| // Chapter 3.5. "Canonical Encoding". | |
| // | |
| if (Accumulator != 0) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| // | |
| // Advance to the next source character. | |
| // | |
| continue; | |
| } else { | |
| // | |
| // Other characters outside of the encoding alphabet are rejected. | |
| // | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| // | |
| // Feed the bits of the current 6-bit group of the quantum to the | |
| // accumulator. | |
| // | |
| Accumulator = (Accumulator << 6) | Base64Value; | |
| SixBitGroupsConsumed++; | |
| switch (SixBitGroupsConsumed) { | |
| case 1: | |
| // | |
| // No octet to spill after consuming the first 6-bit group of the | |
| // quantum; advance to the next source character. | |
| // | |
| continue; | |
| case 2: | |
| // | |
| // 12 bits accumulated (6 pending + 6 new); prepare for spilling an | |
| // octet. 4 bits remain pending. | |
| // | |
| DestinationOctet = (UINT8)(Accumulator >> 4); | |
| Accumulator &= 0xF; | |
| break; | |
| case 3: | |
| // | |
| // 10 bits accumulated (4 pending + 6 new); prepare for spilling an | |
| // octet. 2 bits remain pending. | |
| // | |
| DestinationOctet = (UINT8)(Accumulator >> 2); | |
| Accumulator &= 0x3; | |
| break; | |
| default: | |
| ASSERT (SixBitGroupsConsumed == 4); | |
| // | |
| // 8 bits accumulated (2 pending + 6 new); prepare for spilling an octet. | |
| // The quantum is complete, 0 bits remain pending. | |
| // | |
| DestinationOctet = (UINT8)Accumulator; | |
| Accumulator = 0; | |
| SixBitGroupsConsumed = 0; | |
| break; | |
| } | |
| // | |
| // Store the decoded octet if there's room left. Increment | |
| // (*DestinationSize) unconditionally. | |
| // | |
| if (*DestinationSize < OriginalDestinationSize) { | |
| ASSERT (Destination != NULL); | |
| Destination[*DestinationSize] = DestinationOctet; | |
| } | |
| (*DestinationSize)++; | |
| // | |
| // Advance to the next source character. | |
| // | |
| } | |
| // | |
| // If Source terminates mid-quantum, then Source is invalid. | |
| // | |
| if (SixBitGroupsConsumed != 0) { | |
| return RETURN_INVALID_PARAMETER; | |
| } | |
| // | |
| // Done. | |
| // | |
| if (*DestinationSize <= OriginalDestinationSize) { | |
| return RETURN_SUCCESS; | |
| } | |
| return RETURN_BUFFER_TOO_SMALL; | |
| } | |
| /** | |
| Converts an 8-bit value to an 8-bit BCD value. | |
| Converts the 8-bit value specified by Value to BCD. The BCD value is | |
| returned. | |
| If Value >= 100, then ASSERT(). | |
| @param Value The 8-bit value to convert to BCD. Range 0..99. | |
| @return The BCD value. | |
| **/ | |
| UINT8 | |
| EFIAPI | |
| DecimalToBcd8 ( | |
| IN UINT8 Value | |
| ) | |
| { | |
| ASSERT (Value < 100); | |
| return (UINT8)(((Value / 10) << 4) | (Value % 10)); | |
| } | |
| /** | |
| Converts an 8-bit BCD value to an 8-bit value. | |
| Converts the 8-bit BCD value specified by Value to an 8-bit value. The 8-bit | |
| value is returned. | |
| If Value >= 0xA0, then ASSERT(). | |
| If (Value & 0x0F) >= 0x0A, then ASSERT(). | |
| @param Value The 8-bit BCD value to convert to an 8-bit value. | |
| @return The 8-bit value is returned. | |
| **/ | |
| UINT8 | |
| EFIAPI | |
| BcdToDecimal8 ( | |
| IN UINT8 Value | |
| ) | |
| { | |
| ASSERT (Value < 0xa0); | |
| ASSERT ((Value & 0xf) < 0xa); | |
| return (UINT8)((Value >> 4) * 10 + (Value & 0xf)); | |
| } |