mirror of https://github.com/acidanthera/audk.git
807 lines
16 KiB
C
807 lines
16 KiB
C
/*++
|
|
|
|
Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
|
|
This program and the accompanying materials
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
Module Name:
|
|
|
|
String.c
|
|
|
|
Abstract:
|
|
|
|
Unicode string primatives
|
|
|
|
--*/
|
|
|
|
#include "Tiano.h"
|
|
#include "EfiDriverLib.h"
|
|
#include "EfiCommonLib.h"
|
|
|
|
VOID
|
|
EfiStrCpy (
|
|
IN CHAR16 *Destination,
|
|
IN CHAR16 *Source
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Copy the Unicode string Source to Destination.
|
|
|
|
Arguments:
|
|
Destination - Location to copy string
|
|
Source - String to copy
|
|
|
|
Returns:
|
|
NONE
|
|
|
|
--*/
|
|
{
|
|
while (*Source) {
|
|
*(Destination++) = *(Source++);
|
|
}
|
|
*Destination = 0;
|
|
}
|
|
|
|
VOID
|
|
EfiStrnCpy (
|
|
OUT CHAR16 *Dst,
|
|
IN CHAR16 *Src,
|
|
IN UINTN Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Copy a string from source to destination
|
|
|
|
Arguments:
|
|
Dst Destination string
|
|
Src Source string
|
|
Length Length of destination string
|
|
|
|
Returns:
|
|
|
|
--*/
|
|
{
|
|
UINTN Index;
|
|
UINTN SrcLen;
|
|
|
|
SrcLen = EfiStrLen (Src);
|
|
|
|
Index = 0;
|
|
while (Index < Length && Index < SrcLen) {
|
|
Dst[Index] = Src[Index];
|
|
Index++;
|
|
}
|
|
for (Index = SrcLen; Index < Length; Index++) {
|
|
Dst[Index] = 0;
|
|
}
|
|
}
|
|
|
|
UINTN
|
|
EfiStrLen (
|
|
IN CHAR16 *String
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Return the number of Unicode characters in String. This is not the same as
|
|
the length of the string in bytes.
|
|
|
|
Arguments:
|
|
String - String to process
|
|
|
|
Returns:
|
|
Number of Unicode characters in String
|
|
|
|
--*/
|
|
{
|
|
UINTN Length;
|
|
|
|
for (Length=0; *String; String++, Length++);
|
|
return Length;
|
|
}
|
|
|
|
|
|
UINTN
|
|
EfiStrSize (
|
|
IN CHAR16 *String
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Return the number bytes in the Unicode String. This is not the same as
|
|
the length of the string in characters. The string size includes the NULL
|
|
|
|
Arguments:
|
|
String - String to process
|
|
|
|
Returns:
|
|
Number of bytes in String
|
|
|
|
--*/
|
|
{
|
|
return ((EfiStrLen (String) + 1) * sizeof (CHAR16));
|
|
}
|
|
|
|
|
|
INTN
|
|
EfiStrCmp (
|
|
IN CHAR16 *String,
|
|
IN CHAR16 *String2
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Compare the Unicode string pointed by String to the string pointed by String2.
|
|
|
|
Arguments:
|
|
String - String to process
|
|
|
|
String2 - The other string to process
|
|
|
|
Returns:
|
|
Return a positive integer if String is lexicall greater than String2; Zero if
|
|
the two strings are identical; and a negative integer if String is lexically
|
|
less than String2.
|
|
|
|
--*/
|
|
{
|
|
while (*String) {
|
|
if (*String != *String2) {
|
|
break;
|
|
}
|
|
|
|
String += 1;
|
|
String2 += 1;
|
|
}
|
|
|
|
return *String - *String2;
|
|
}
|
|
|
|
INTN
|
|
EfiStrnCmp (
|
|
IN CHAR16 *String,
|
|
IN CHAR16 *String2,
|
|
IN UINTN Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function compares the Unicode string String to the Unicode
|
|
string String2 for len characters. If the first len characters
|
|
of String is identical to the first len characters of String2,
|
|
then 0 is returned. If substring of String sorts lexicographically
|
|
after String2, the function returns a number greater than 0. If
|
|
substring of String sorts lexicographically before String2, the
|
|
function returns a number less than 0.
|
|
|
|
Arguments:
|
|
String - Compare to String2
|
|
String2 - Compare to String
|
|
Length - Number of Unicode characters to compare
|
|
|
|
Returns:
|
|
0 - The substring of String and String2 is identical.
|
|
> 0 - The substring of String sorts lexicographically after String2
|
|
< 0 - The substring of String sorts lexicographically before String2
|
|
|
|
--*/
|
|
{
|
|
while (*String && Length != 0) {
|
|
if (*String != *String2) {
|
|
break;
|
|
}
|
|
String += 1;
|
|
String2 += 1;
|
|
Length -= 1;
|
|
}
|
|
return Length > 0 ? *String - *String2 : 0;
|
|
}
|
|
|
|
VOID
|
|
EfiStrCat (
|
|
IN CHAR16 *Destination,
|
|
IN CHAR16 *Source
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Concatinate Source on the end of Destination
|
|
|
|
Arguments:
|
|
Destination - String to added to the end of.
|
|
Source - String to concatinate.
|
|
|
|
Returns:
|
|
NONE
|
|
|
|
--*/
|
|
{
|
|
EfiStrCpy (Destination + EfiStrLen (Destination), Source);
|
|
}
|
|
|
|
VOID
|
|
EfiStrnCat (
|
|
IN CHAR16 *Dest,
|
|
IN CHAR16 *Src,
|
|
IN UINTN Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Concatinate Source on the end of Destination
|
|
|
|
Arguments:
|
|
Dst Destination string
|
|
Src Source string
|
|
Length Length of destination string
|
|
|
|
Returns:
|
|
|
|
--*/
|
|
{
|
|
EfiStrnCpy (Dest + EfiStrLen (Dest), Src, Length);
|
|
}
|
|
|
|
UINTN
|
|
EfiAsciiStrLen (
|
|
IN CHAR8 *String
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Return the number of Ascii characters in String. This is not the same as
|
|
the length of the string in bytes.
|
|
|
|
Arguments:
|
|
String - String to process
|
|
|
|
Returns:
|
|
Number of Ascii characters in String
|
|
|
|
--*/
|
|
{
|
|
UINTN Length;
|
|
|
|
for (Length=0; *String; String++, Length++);
|
|
return Length;
|
|
}
|
|
|
|
|
|
CHAR8 *
|
|
EfiAsciiStrCpy (
|
|
IN CHAR8 *Destination,
|
|
IN CHAR8 *Source
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Copy the Ascii string Source to Destination.
|
|
|
|
Arguments:
|
|
Destination - Location to copy string
|
|
Source - String to copy
|
|
|
|
Returns:
|
|
Pointer just pass the end of Destination
|
|
|
|
--*/
|
|
{
|
|
while (*Source) {
|
|
*(Destination++) = *(Source++);
|
|
}
|
|
*Destination = 0;
|
|
return Destination + 1;
|
|
}
|
|
|
|
VOID
|
|
EfiAsciiStrnCpy (
|
|
OUT CHAR8 *Dst,
|
|
IN CHAR8 *Src,
|
|
IN UINTN Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Copy the Ascii string from source to destination
|
|
|
|
Arguments:
|
|
Dst Destination string
|
|
Src Source string
|
|
Length Length of destination string
|
|
|
|
Returns:
|
|
|
|
--*/
|
|
{
|
|
UINTN Index;
|
|
UINTN SrcLen;
|
|
|
|
SrcLen = EfiAsciiStrLen (Src);
|
|
|
|
Index = 0;
|
|
while (Index < Length && Index < SrcLen) {
|
|
Dst[Index] = Src[Index];
|
|
Index++;
|
|
}
|
|
for (Index = SrcLen; Index < Length; Index++) {
|
|
Dst[Index] = 0;
|
|
}
|
|
}
|
|
|
|
UINTN
|
|
EfiAsciiStrSize (
|
|
IN CHAR8 *String
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Return the number bytes in the Ascii String. This is not the same as
|
|
the length of the string in characters. The string size includes the NULL
|
|
|
|
Arguments:
|
|
String - String to process
|
|
|
|
Returns:
|
|
Number of bytes in String
|
|
|
|
--*/
|
|
{
|
|
return (EfiAsciiStrLen (String) + 1);
|
|
}
|
|
|
|
|
|
INTN
|
|
EfiAsciiStrCmp (
|
|
IN CHAR8 *String,
|
|
IN CHAR8 *String2
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Compare the Ascii string pointed by String to the string pointed by String2.
|
|
|
|
Arguments:
|
|
String - String to process
|
|
|
|
String2 - The other string to process
|
|
|
|
Returns:
|
|
Return a positive integer if String is lexicall greater than String2; Zero if
|
|
the two strings are identical; and a negative integer if String is lexically
|
|
less than String2.
|
|
--*/
|
|
{
|
|
while (*String) {
|
|
if (*String != *String2) {
|
|
break;
|
|
}
|
|
|
|
String += 1;
|
|
String2 += 1;
|
|
}
|
|
|
|
return *String - *String2;
|
|
}
|
|
|
|
INTN
|
|
EfiAsciiStrnCmp (
|
|
IN CHAR8 *String,
|
|
IN CHAR8 *String2,
|
|
IN UINTN Length
|
|
)
|
|
{
|
|
if (Length == 0) {
|
|
return 0;
|
|
}
|
|
|
|
while ((*String != '\0') &&
|
|
(*String == *String2) &&
|
|
(Length > 1)) {
|
|
String++;
|
|
String2++;
|
|
Length--;
|
|
}
|
|
return *String - *String2;
|
|
}
|
|
|
|
VOID
|
|
EfiAsciiStrCat (
|
|
IN CHAR8 *Destination,
|
|
IN CHAR8 *Source
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Concatinate Source on the end of Destination
|
|
|
|
Arguments:
|
|
Destination - String to added to the end of.
|
|
Source - String to concatinate.
|
|
|
|
Returns:
|
|
NONE
|
|
|
|
--*/
|
|
{
|
|
EfiAsciiStrCpy (Destination + EfiAsciiStrLen (Destination), Source);
|
|
}
|
|
|
|
VOID
|
|
EfiAsciiStrnCat (
|
|
IN CHAR8 *Destination,
|
|
IN CHAR8 *Source,
|
|
IN UINTN Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Concatinate Source on the end of Destination
|
|
|
|
Arguments:
|
|
Destination - String to added to the end of.
|
|
Source - String to concatinate.
|
|
|
|
Returns:
|
|
NONE
|
|
|
|
--*/
|
|
{
|
|
EfiAsciiStrnCpy (Destination + EfiAsciiStrLen (Destination), Source, Length);
|
|
}
|
|
|
|
BOOLEAN
|
|
IsHexDigit (
|
|
OUT UINT8 *Digit,
|
|
IN CHAR16 Char
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Determines if a Unicode character is a hexadecimal digit.
|
|
The test is case insensitive.
|
|
|
|
Arguments:
|
|
Digit - Pointer to byte that receives the value of the hex character.
|
|
Char - Unicode character to test.
|
|
|
|
Returns:
|
|
TRUE - If the character is a hexadecimal digit.
|
|
FALSE - Otherwise.
|
|
|
|
--*/
|
|
{
|
|
if ((Char >= L'0') && (Char <= L'9')) {
|
|
*Digit = (UINT8) (Char - L'0');
|
|
return TRUE;
|
|
}
|
|
|
|
if ((Char >= L'A') && (Char <= L'F')) {
|
|
*Digit = (UINT8) (Char - L'A' + 0x0A);
|
|
return TRUE;
|
|
}
|
|
|
|
if ((Char >= L'a') && (Char <= L'f')) {
|
|
*Digit = (UINT8) (Char - L'a' + 0x0A);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
CHAR16
|
|
NibbleToHexChar (
|
|
IN UINT8 Nibble
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Converts the low nibble of a byte to hex unicode character.
|
|
|
|
Arguments:
|
|
Nibble - lower nibble of a byte.
|
|
|
|
Returns:
|
|
Hex unicode character.
|
|
|
|
--*/
|
|
{
|
|
Nibble &= 0x0F;
|
|
if (Nibble <= 0x9) {
|
|
return (CHAR16)(Nibble + L'0');
|
|
}
|
|
|
|
return (CHAR16)(Nibble - 0xA + L'A');
|
|
}
|
|
|
|
EFI_STATUS
|
|
HexStringToBuf (
|
|
IN OUT UINT8 *Buf,
|
|
IN OUT UINTN *Len,
|
|
IN CHAR16 *Str,
|
|
OUT UINTN *ConvertedStrLen OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Converts Unicode string to binary buffer.
|
|
The conversion may be partial.
|
|
The first character in the string that is not hex digit stops the conversion.
|
|
At a minimum, any blob of data could be represented as a hex string.
|
|
|
|
Arguments:
|
|
Buf - Pointer to buffer that receives the data.
|
|
Len - Length in bytes of the buffer to hold converted data.
|
|
If routine return with EFI_SUCCESS, containing length of converted data.
|
|
If routine return with EFI_BUFFER_TOO_SMALL, containg length of buffer desired.
|
|
Str - String to be converted from.
|
|
ConvertedStrLen - Length of the Hex String consumed.
|
|
|
|
Returns:
|
|
EFI_SUCCESS: Routine Success.
|
|
EFI_BUFFER_TOO_SMALL: The buffer is too small to hold converted data.
|
|
EFI_
|
|
|
|
--*/
|
|
{
|
|
UINTN HexCnt;
|
|
UINTN Idx;
|
|
UINTN BufferLength;
|
|
UINT8 Digit;
|
|
UINT8 Byte;
|
|
|
|
//
|
|
// Find out how many hex characters the string has.
|
|
//
|
|
for (Idx = 0, HexCnt = 0; IsHexDigit (&Digit, Str[Idx]); Idx++, HexCnt++);
|
|
|
|
if (HexCnt == 0) {
|
|
*Len = 0;
|
|
return EFI_SUCCESS;
|
|
}
|
|
//
|
|
// Two Unicode characters make up 1 buffer byte. Round up.
|
|
//
|
|
BufferLength = (HexCnt + 1) / 2;
|
|
|
|
//
|
|
// Test if buffer is passed enough.
|
|
//
|
|
if (BufferLength > (*Len)) {
|
|
*Len = BufferLength;
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
*Len = BufferLength;
|
|
|
|
for (Idx = 0; Idx < HexCnt; Idx++) {
|
|
|
|
IsHexDigit (&Digit, Str[HexCnt - 1 - Idx]);
|
|
|
|
//
|
|
// For odd charaters, write the lower nibble for each buffer byte,
|
|
// and for even characters, the upper nibble.
|
|
//
|
|
if ((Idx & 1) == 0) {
|
|
Byte = Digit;
|
|
} else {
|
|
Byte = Buf[Idx / 2];
|
|
Byte &= 0x0F;
|
|
Byte = (UINT8)(Byte | (Digit << 4));
|
|
}
|
|
|
|
Buf[Idx / 2] = Byte;
|
|
}
|
|
|
|
if (ConvertedStrLen != NULL) {
|
|
*ConvertedStrLen = HexCnt;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
BufToHexString (
|
|
IN OUT CHAR16 *Str,
|
|
IN OUT UINTN *HexStringBufferLength,
|
|
IN UINT8 *Buf,
|
|
IN UINTN Len
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Converts binary buffer to Unicode string.
|
|
At a minimum, any blob of data could be represented as a hex string.
|
|
|
|
Arguments:
|
|
Str - Pointer to the string.
|
|
HexStringBufferLength - Length in bytes of buffer to hold the hex string. Includes tailing '\0' character.
|
|
If routine return with EFI_SUCCESS, containing length of hex string buffer.
|
|
If routine return with EFI_BUFFER_TOO_SMALL, containg length of hex string buffer desired.
|
|
Buf - Buffer to be converted from.
|
|
Len - Length in bytes of the buffer to be converted.
|
|
|
|
Returns:
|
|
EFI_SUCCESS: Routine success.
|
|
EFI_BUFFER_TOO_SMALL: The hex string buffer is too small.
|
|
|
|
--*/
|
|
{
|
|
UINTN Idx;
|
|
UINT8 Byte;
|
|
UINTN StrLen;
|
|
|
|
//
|
|
// Make sure string is either passed or allocate enough.
|
|
// It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer.
|
|
// Plus the Unicode termination character.
|
|
//
|
|
StrLen = Len * 2;
|
|
if (StrLen > ((*HexStringBufferLength) - 1)) {
|
|
*HexStringBufferLength = StrLen + 1;
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
*HexStringBufferLength = StrLen + 1;
|
|
//
|
|
// Ends the string.
|
|
//
|
|
Str[StrLen] = L'\0';
|
|
|
|
for (Idx = 0; Idx < Len; Idx++) {
|
|
|
|
Byte = Buf[Idx];
|
|
Str[StrLen - 1 - Idx * 2] = NibbleToHexChar (Byte);
|
|
Str[StrLen - 2 - Idx * 2] = NibbleToHexChar ((UINT8)(Byte >> 4));
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
EfiStrTrim (
|
|
IN OUT CHAR16 *str,
|
|
IN CHAR16 CharC
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Removes (trims) specified leading and trailing characters from a string.
|
|
|
|
Arguments:
|
|
|
|
str - Pointer to the null-terminated string to be trimmed. On return,
|
|
str will hold the trimmed string.
|
|
CharC - Character will be trimmed from str.
|
|
|
|
Returns:
|
|
|
|
--*/
|
|
{
|
|
CHAR16 *p1;
|
|
CHAR16 *p2;
|
|
|
|
if (*str == 0) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Trim off the leading and trailing characters c
|
|
//
|
|
for (p1 = str; *p1 && *p1 == CharC; p1++) {
|
|
;
|
|
}
|
|
|
|
p2 = str;
|
|
if (p2 == p1) {
|
|
while (*p1) {
|
|
p2++;
|
|
p1++;
|
|
}
|
|
} else {
|
|
while (*p1) {
|
|
*p2 = *p1;
|
|
p1++;
|
|
p2++;
|
|
}
|
|
*p2 = 0;
|
|
}
|
|
|
|
|
|
for (p1 = str + EfiStrLen(str) - 1; p1 >= str && *p1 == CharC; p1--) {
|
|
;
|
|
}
|
|
if (p1 != str + EfiStrLen(str) - 1) {
|
|
*(p1 + 1) = 0;
|
|
}
|
|
}
|
|
CHAR16*
|
|
EfiStrStr (
|
|
IN CHAR16 *String,
|
|
IN CHAR16 *StrCharSet
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Find a substring.
|
|
|
|
Arguments:
|
|
|
|
String - Null-terminated string to search.
|
|
StrCharSet - Null-terminated string to search for.
|
|
|
|
Returns:
|
|
The address of the first occurrence of the matching substring if successful, or NULL otherwise.
|
|
--*/
|
|
{
|
|
CHAR16 *Src;
|
|
CHAR16 *Sub;
|
|
|
|
Src = String;
|
|
Sub = StrCharSet;
|
|
|
|
while ((*String != L'\0') && (*StrCharSet != L'\0')) {
|
|
if (*String++ != *StrCharSet) {
|
|
String = ++Src;
|
|
StrCharSet = Sub;
|
|
} else {
|
|
StrCharSet++;
|
|
}
|
|
}
|
|
if (*StrCharSet == L'\0') {
|
|
return Src;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
CHAR8*
|
|
EfiAsciiStrStr (
|
|
IN CHAR8 *String,
|
|
IN CHAR8 *StrCharSet
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Find a Ascii substring.
|
|
|
|
Arguments:
|
|
|
|
String - Null-terminated Ascii string to search.
|
|
StrCharSet - Null-terminated Ascii string to search for.
|
|
|
|
Returns:
|
|
The address of the first occurrence of the matching Ascii substring if successful, or NULL otherwise.
|
|
--*/
|
|
{
|
|
CHAR8 *Src;
|
|
CHAR8 *Sub;
|
|
|
|
Src = String;
|
|
Sub = StrCharSet;
|
|
|
|
while ((*String != '\0') && (*StrCharSet != '\0')) {
|
|
if (*String++ != *StrCharSet) {
|
|
String = ++Src;
|
|
StrCharSet = Sub;
|
|
} else {
|
|
StrCharSet++;
|
|
}
|
|
}
|
|
if (*StrCharSet == '\0') {
|
|
return Src;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|