最近编写程序,需要用到 CHAR16 的大小写转换,忽然惊奇的发现远比CHAR8的转化复杂,没有可以直接使用的函数。研究了一番,猜测产生这样问题的原因是 CHAR16 是定义给 Unicode 使用的。而Unicode 需要支持多种语言格式,比方说:’a’的大写是’A’,‘一’的大写就是‘壹’了,所以处理上也是复杂的。
从 UEFI Spec 来看,标准的做法要求使用EFI_UNICODE_COLLATION_PROTOCOL 。对应的头文件在 \MdePkg\Include\Protocol\UnicodeCollation.h 中。有下面几个功能:
///
/// The EFI_UNICODE_COLLATION_PROTOCOL is used to perform case-insensitive
/// comparisons of strings.
///
struct _EFI_UNICODE_COLLATION_PROTOCOL {
EFI_UNICODE_COLLATION_STRICOLL StriColl;
EFI_UNICODE_COLLATION_METAIMATCH MetaiMatch;
EFI_UNICODE_COLLATION_STRLWR StrLwr;
EFI_UNICODE_COLLATION_STRUPR StrUpr;
//
// for supporting fat volumes
//
EFI_UNICODE_COLLATION_FATTOSTR FatToStr;
EFI_UNICODE_COLLATION_STRTOFAT StrToFat;
///
/// A Null-terminated ASCII string array that contains one or more language codes.
/// When this field is used for UnicodeCollation2, it is specified in RFC 4646 format.
/// When it is used for UnicodeCollation, it is specified in ISO 639-2 format.
///
CHAR8 *SupportedLanguages;
};
StriColl 进行大小写敏感的字符串比较
MetaiMatch 判断字符串是否匹配一个带有通配符的模版
StrLwr 字符串转为小写
StrUpr 字符串转为大写
FatToStr 将8.3格式的OEM字符集的FAT文件名转为字符串
StrToFat 将字符串转为OEM定义的字符集
*SupportedLanguages ASCII给出的语言的列表
上述只是简单的介绍,我也并没有仔细验证,更详细的请阅读UEFI Spec Protocols – String Services 章节。
除了,上面介绍的方法,如果你确定字符串中只有 ASCII , 那么还可以直接处理字符串中的 ASCII ,下面的实例演示了上面的2种做法:
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/ShellCEntryLib.h>
#include <Protocol/UnicodeCollation.h>
extern EFI_BOOT_SERVICES *gBS;
extern EFI_SYSTEM_TABLE *gST;
extern EFI_RUNTIME_SERVICES *gRT;
EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;
VOID
EFIAPI
lowercase (
IN OUT CHAR16 *Str
)
{
UINT32 i;
CHAR8 *p;
p=(CHAR8 *)Str;
for (i=0;i<StrSize(Str);i++) {
//Print(L"%d ",*p);
if ((*p>='A')&&(*p<='Z')) {
*p=*p+32;
}
p++;
}
}
int
EFIAPI
main (
IN int Argc,
IN CHAR16 **Argv
)
{
EFI_STATUS Status;
CHAR16 *s1=L"Www.Lab-z.Com 1243";
CHAR16 *s2=L"Www.Lab-z.Com 1243";
if (mUnicodeCollation == NULL) {
Status = gBS->LocateProtocol(
&gEfiUnicodeCollation2ProtocolGuid,
NULL,
(VOID**)&mUnicodeCollation);
if (EFI_ERROR(Status)) {
Print(L"Can't find UnicodeCollation2 Protocol!\n");
return EFI_SUCCESS;
}
}
mUnicodeCollation->StrUpr(
mUnicodeCollation,
s1);
Print(L"%s\n",s1);
lowercase (s2);
Print(L"%s\n",s2);
return EFI_SUCCESS;
}
运行结果:
完整的代码下载
