diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /EDK/Foundation/Library/EfiCommonLib/String.c | |
download | zprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz |
Diffstat (limited to 'EDK/Foundation/Library/EfiCommonLib/String.c')
-rw-r--r-- | EDK/Foundation/Library/EfiCommonLib/String.c | 802 |
1 files changed, 802 insertions, 0 deletions
diff --git a/EDK/Foundation/Library/EfiCommonLib/String.c b/EDK/Foundation/Library/EfiCommonLib/String.c new file mode 100644 index 0000000..435bc66 --- /dev/null +++ b/EDK/Foundation/Library/EfiCommonLib/String.c @@ -0,0 +1,802 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. 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 interger 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 interger 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 |= 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; + } + } + 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; + } + } + if (*StrCharSet == '\0') { + return Src; + } else { + return NULL; + } +} + |