/** @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)); | |
} |