Step to UEFI (114)CHAR16大小写转换

最近编写程序,需要用到 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;
}

 

运行结果:

ultest

完整的代码下载

ULTest

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注