]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BaseLib/String.c
MdePkg: Remove code wrapped by DISABLE_NEW_DEPRECATED_INTERFACES
[mirror_edk2.git] / MdePkg / Library / BaseLib / String.c
CommitLineData
e1f414b6 1/** @file\r
3868d06d 2 Unicode and ASCII string primitives.\r
e1f414b6 3\r
5dbfa01e 4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
9344f092 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
e1f414b6 6\r
e1f414b6 7**/\r
8\r
e1f414b6 9#include "BaseLibInternals.h"\r
10\r
e1f414b6 11\r
12/**\r
13 Returns the length of a Null-terminated Unicode string.\r
14\r
15 This function returns the number of Unicode characters in the Null-terminated\r
16 Unicode string specified by String.\r
17\r
18 If String is NULL, then ASSERT().\r
19 If String is not aligned on a 16-bit boundary, then ASSERT().\r
20 If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
dfbe9de9 21 PcdMaximumUnicodeStringLength Unicode characters, not including the\r
e1f414b6 22 Null-terminator, then ASSERT().\r
23\r
127010dd 24 @param String A pointer to a Null-terminated Unicode string.\r
e1f414b6 25\r
26 @return The length of String.\r
27\r
28**/\r
29UINTN\r
30EFIAPI\r
31StrLen (\r
32 IN CONST CHAR16 *String\r
33 )\r
34{\r
35 UINTN Length;\r
36\r
37 ASSERT (String != NULL);\r
24dcb5e5 38 ASSERT (((UINTN) String & BIT0) == 0);\r
e1f414b6 39\r
40 for (Length = 0; *String != L'\0'; String++, Length++) {\r
41 //\r
42 // If PcdMaximumUnicodeStringLength is not zero,\r
43 // length should not more than PcdMaximumUnicodeStringLength\r
44 //\r
45 if (PcdGet32 (PcdMaximumUnicodeStringLength) != 0) {\r
46 ASSERT (Length < PcdGet32 (PcdMaximumUnicodeStringLength));\r
47 }\r
48 }\r
49 return Length;\r
50}\r
51\r
52/**\r
53 Returns the size of a Null-terminated Unicode string in bytes, including the\r
54 Null terminator.\r
55\r
9095d37b 56 This function returns the size, in bytes, of the Null-terminated Unicode string\r
9aa049d9 57 specified by String.\r
e1f414b6 58\r
59 If String is NULL, then ASSERT().\r
60 If String is not aligned on a 16-bit boundary, then ASSERT().\r
61 If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
dfbe9de9 62 PcdMaximumUnicodeStringLength Unicode characters, not including the\r
e1f414b6 63 Null-terminator, then ASSERT().\r
64\r
127010dd 65 @param String A pointer to a Null-terminated Unicode string.\r
e1f414b6 66\r
9aa049d9 67 @return The size of String.\r
e1f414b6 68\r
69**/\r
70UINTN\r
71EFIAPI\r
72StrSize (\r
73 IN CONST CHAR16 *String\r
74 )\r
75{\r
76 return (StrLen (String) + 1) * sizeof (*String);\r
77}\r
78\r
79/**\r
80 Compares two Null-terminated Unicode strings, and returns the difference\r
81 between the first mismatched Unicode characters.\r
82\r
83 This function compares the Null-terminated Unicode string FirstString to the\r
84 Null-terminated Unicode string SecondString. If FirstString is identical to\r
85 SecondString, then 0 is returned. Otherwise, the value returned is the first\r
86 mismatched Unicode character in SecondString subtracted from the first\r
87 mismatched Unicode character in FirstString.\r
88\r
89 If FirstString is NULL, then ASSERT().\r
90 If FirstString is not aligned on a 16-bit boundary, then ASSERT().\r
91 If SecondString is NULL, then ASSERT().\r
92 If SecondString is not aligned on a 16-bit boundary, then ASSERT().\r
93 If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more\r
dfbe9de9 94 than PcdMaximumUnicodeStringLength Unicode characters, not including the\r
e1f414b6 95 Null-terminator, then ASSERT().\r
96 If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more\r
dfbe9de9 97 than PcdMaximumUnicodeStringLength Unicode characters, not including the\r
e1f414b6 98 Null-terminator, then ASSERT().\r
99\r
127010dd 100 @param FirstString A pointer to a Null-terminated Unicode string.\r
101 @param SecondString A pointer to a Null-terminated Unicode string.\r
e1f414b6 102\r
1106ffe1 103 @retval 0 FirstString is identical to SecondString.\r
9aa049d9 104 @return others FirstString is not identical to SecondString.\r
e1f414b6 105\r
106**/\r
107INTN\r
108EFIAPI\r
109StrCmp (\r
110 IN CONST CHAR16 *FirstString,\r
111 IN CONST CHAR16 *SecondString\r
112 )\r
113{\r
114 //\r
115 // ASSERT both strings are less long than PcdMaximumUnicodeStringLength\r
116 //\r
117 ASSERT (StrSize (FirstString) != 0);\r
118 ASSERT (StrSize (SecondString) != 0);\r
119\r
120 while ((*FirstString != L'\0') && (*FirstString == *SecondString)) {\r
121 FirstString++;\r
122 SecondString++;\r
123 }\r
124 return *FirstString - *SecondString;\r
125}\r
126\r
127/**\r
9aa049d9 128 Compares up to a specified length the contents of two Null-terminated Unicode strings,\r
129 and returns the difference between the first mismatched Unicode characters.\r
9095d37b 130\r
e1f414b6 131 This function compares the Null-terminated Unicode string FirstString to the\r
132 Null-terminated Unicode string SecondString. At most, Length Unicode\r
133 characters will be compared. If Length is 0, then 0 is returned. If\r
134 FirstString is identical to SecondString, then 0 is returned. Otherwise, the\r
135 value returned is the first mismatched Unicode character in SecondString\r
136 subtracted from the first mismatched Unicode character in FirstString.\r
137\r
138 If Length > 0 and FirstString is NULL, then ASSERT().\r
77f863ee 139 If Length > 0 and FirstString is not aligned on a 16-bit boundary, then ASSERT().\r
e1f414b6 140 If Length > 0 and SecondString is NULL, then ASSERT().\r
77f863ee 141 If Length > 0 and SecondString is not aligned on a 16-bit boundary, then ASSERT().\r
53e96610 142 If PcdMaximumUnicodeStringLength is not zero, and Length is greater than\r
143 PcdMaximumUnicodeStringLength, then ASSERT().\r
144 If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more than\r
145 PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,\r
146 then ASSERT().\r
147 If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more than\r
148 PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,\r
dfbe9de9 149 then ASSERT().\r
e1f414b6 150\r
127010dd 151 @param FirstString A pointer to a Null-terminated Unicode string.\r
152 @param SecondString A pointer to a Null-terminated Unicode string.\r
2fc59a00 153 @param Length The maximum number of Unicode characters to compare.\r
e1f414b6 154\r
1106ffe1 155 @retval 0 FirstString is identical to SecondString.\r
9aa049d9 156 @return others FirstString is not identical to SecondString.\r
e1f414b6 157\r
158**/\r
159INTN\r
160EFIAPI\r
161StrnCmp (\r
162 IN CONST CHAR16 *FirstString,\r
163 IN CONST CHAR16 *SecondString,\r
164 IN UINTN Length\r
165 )\r
166{\r
2bfb6009 167 if (Length == 0) {\r
e1f414b6 168 return 0;\r
169 }\r
170\r
171 //\r
172 // ASSERT both strings are less long than PcdMaximumUnicodeStringLength.\r
173 // Length tests are performed inside StrLen().\r
174 //\r
175 ASSERT (StrSize (FirstString) != 0);\r
176 ASSERT (StrSize (SecondString) != 0);\r
177\r
dfbe9de9 178 if (PcdGet32 (PcdMaximumUnicodeStringLength) != 0) {\r
179 ASSERT (Length <= PcdGet32 (PcdMaximumUnicodeStringLength));\r
180 }\r
181\r
e1f414b6 182 while ((*FirstString != L'\0') &&\r
753a18f9 183 (*SecondString != L'\0') &&\r
e1f414b6 184 (*FirstString == *SecondString) &&\r
185 (Length > 1)) {\r
186 FirstString++;\r
187 SecondString++;\r
188 Length--;\r
189 }\r
190\r
191 return *FirstString - *SecondString;\r
192}\r
193\r
e1f414b6 194\r
195/**\r
9aa049d9 196 Returns the first occurrence of a Null-terminated Unicode sub-string\r
e1f414b6 197 in a Null-terminated Unicode string.\r
198\r
9aa049d9 199 This function scans the contents of the Null-terminated Unicode string\r
200 specified by String and returns the first occurrence of SearchString.\r
201 If SearchString is not found in String, then NULL is returned. If\r
202 the length of SearchString is zero, then String is\r
e1f414b6 203 returned.\r
9aa049d9 204\r
e1f414b6 205 If String is NULL, then ASSERT().\r
206 If String is not aligned on a 16-bit boundary, then ASSERT().\r
207 If SearchString is NULL, then ASSERT().\r
208 If SearchString is not aligned on a 16-bit boundary, then ASSERT().\r
209\r
9aa049d9 210 If PcdMaximumUnicodeStringLength is not zero, and SearchString\r
211 or String contains more than PcdMaximumUnicodeStringLength Unicode\r
dfbe9de9 212 characters, not including the Null-terminator, then ASSERT().\r
e1f414b6 213\r
127010dd 214 @param String A pointer to a Null-terminated Unicode string.\r
215 @param SearchString A pointer to a Null-terminated Unicode string to search for.\r
e1f414b6 216\r
9aa049d9 217 @retval NULL If the SearchString does not appear in String.\r
218 @return others If there is a match.\r
e1f414b6 219\r
220**/\r
221CHAR16 *\r
222EFIAPI\r
223StrStr (\r
2fc60b70 224 IN CONST CHAR16 *String,\r
225 IN CONST CHAR16 *SearchString\r
e1f414b6 226 )\r
227{\r
228 CONST CHAR16 *FirstMatch;\r
229 CONST CHAR16 *SearchStringTmp;\r
230\r
e1f414b6 231 //\r
4df26661 232 // ASSERT both strings are less long than PcdMaximumUnicodeStringLength.\r
233 // Length tests are performed inside StrLen().\r
e1f414b6 234 //\r
4df26661 235 ASSERT (StrSize (String) != 0);\r
236 ASSERT (StrSize (SearchString) != 0);\r
e1f414b6 237\r
62e71e2f 238 if (*SearchString == L'\0') {\r
faeb3214 239 return (CHAR16 *) String;\r
62e71e2f 240 }\r
241\r
242 while (*String != L'\0') {\r
e1f414b6 243 SearchStringTmp = SearchString;\r
244 FirstMatch = String;\r
9095d37b
LG
245\r
246 while ((*String == *SearchStringTmp)\r
62e71e2f 247 && (*String != L'\0')) {\r
e1f414b6 248 String++;\r
249 SearchStringTmp++;\r
9095d37b
LG
250 }\r
251\r
62e71e2f 252 if (*SearchStringTmp == L'\0') {\r
e1f414b6 253 return (CHAR16 *) FirstMatch;\r
254 }\r
255\r
62e71e2f 256 if (*String == L'\0') {\r
257 return NULL;\r
e1f414b6 258 }\r
62e71e2f 259\r
260 String = FirstMatch + 1;\r
e1f414b6 261 }\r
262\r
263 return NULL;\r
264}\r
265\r
266/**\r
267 Check if a Unicode character is a decimal character.\r
268\r
9095d37b 269 This internal function checks if a Unicode character is a\r
e1f414b6 270 decimal character. The valid decimal character is from\r
271 L'0' to L'9'.\r
272\r
e1f414b6 273 @param Char The character to check against.\r
274\r
275 @retval TRUE If the Char is a decmial character.\r
24dcb5e5 276 @retval FALSE If the Char is not a decmial character.\r
e1f414b6 277\r
278**/\r
e1f414b6 279BOOLEAN\r
42eedea9 280EFIAPI\r
e1f414b6 281InternalIsDecimalDigitCharacter (\r
282 IN CHAR16 Char\r
283 )\r
284{\r
285 return (BOOLEAN) (Char >= L'0' && Char <= L'9');\r
286}\r
287\r
288/**\r
9095d37b 289 Convert a Unicode character to upper case only if\r
e1f414b6 290 it maps to a valid small-case ASCII character.\r
291\r
292 This internal function only deal with Unicode character\r
24dcb5e5 293 which maps to a valid small-case ASCII character, i.e.\r
e1f414b6 294 L'a' to L'z'. For other Unicode character, the input character\r
295 is returned directly.\r
296\r
e1f414b6 297 @param Char The character to convert.\r
298\r
299 @retval LowerCharacter If the Char is with range L'a' to L'z'.\r
300 @retval Unchanged Otherwise.\r
301\r
302**/\r
e1f414b6 303CHAR16\r
42eedea9 304EFIAPI\r
5dbfa01e 305CharToUpper (\r
e1f414b6 306 IN CHAR16 Char\r
307 )\r
308{\r
309 if (Char >= L'a' && Char <= L'z') {\r
310 return (CHAR16) (Char - (L'a' - L'A'));\r
311 }\r
312\r
313 return Char;\r
314}\r
315\r
316/**\r
317 Convert a Unicode character to numerical value.\r
318\r
319 This internal function only deal with Unicode character\r
320 which maps to a valid hexadecimal ASII character, i.e.\r
9095d37b 321 L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other\r
e1f414b6 322 Unicode character, the value returned does not make sense.\r
323\r
324 @param Char The character to convert.\r
325\r
24dcb5e5 326 @return The numerical value converted.\r
e1f414b6 327\r
328**/\r
e1f414b6 329UINTN\r
42eedea9 330EFIAPI\r
e1f414b6 331InternalHexCharToUintn (\r
332 IN CHAR16 Char\r
333 )\r
334{\r
335 if (InternalIsDecimalDigitCharacter (Char)) {\r
336 return Char - L'0';\r
337 }\r
338\r
5dbfa01e 339 return (10 + CharToUpper (Char) - L'A');\r
e1f414b6 340}\r
341\r
342/**\r
343 Check if a Unicode character is a hexadecimal character.\r
344\r
9095d37b
LG
345 This internal function checks if a Unicode character is a\r
346 decimal character. The valid hexadecimal character is\r
e1f414b6 347 L'0' to L'9', L'a' to L'f', or L'A' to L'F'.\r
348\r
349\r
350 @param Char The character to check against.\r
351\r
352 @retval TRUE If the Char is a hexadecmial character.\r
24dcb5e5 353 @retval FALSE If the Char is not a hexadecmial character.\r
e1f414b6 354\r
355**/\r
e1f414b6 356BOOLEAN\r
42eedea9 357EFIAPI\r
e1f414b6 358InternalIsHexaDecimalDigitCharacter (\r
359 IN CHAR16 Char\r
360 )\r
361{\r
362\r
363 return (BOOLEAN) (InternalIsDecimalDigitCharacter (Char) ||\r
364 (Char >= L'A' && Char <= L'F') ||\r
365 (Char >= L'a' && Char <= L'f'));\r
366}\r
367\r
368/**\r
9aa049d9 369 Convert a Null-terminated Unicode decimal string to a value of\r
e1f414b6 370 type UINTN.\r
371\r
9aa049d9 372 This function returns a value of type UINTN by interpreting the contents\r
373 of the Unicode string specified by String as a decimal number. The format\r
e1f414b6 374 of the input Unicode string String is:\r
9aa049d9 375\r
2fe241a2 376 [spaces] [decimal digits].\r
9aa049d9 377\r
378 The valid decimal digit character is in the range [0-9]. The\r
379 function will ignore the pad space, which includes spaces or\r
380 tab characters, before [decimal digits]. The running zero in the\r
381 beginning of [decimal digits] will be ignored. Then, the function\r
382 stops at the first character that is a not a valid decimal character\r
383 or a Null-terminator, whichever one comes first.\r
384\r
e1f414b6 385 If String is NULL, then ASSERT().\r
9aa049d9 386 If String is not aligned in a 16-bit boundary, then ASSERT().\r
e1f414b6 387 If String has only pad spaces, then 0 is returned.\r
9aa049d9 388 If String has no pad spaces or valid decimal digits,\r
e1f414b6 389 then 0 is returned.\r
9aa049d9 390 If the number represented by String overflows according\r
ea2e0921 391 to the range defined by UINTN, then MAX_UINTN is returned.\r
9aa049d9 392\r
393 If PcdMaximumUnicodeStringLength is not zero, and String contains\r
dfbe9de9 394 more than PcdMaximumUnicodeStringLength Unicode characters, not including\r
e1f414b6 395 the Null-terminator, then ASSERT().\r
396\r
127010dd 397 @param String A pointer to a Null-terminated Unicode string.\r
e1f414b6 398\r
9aa049d9 399 @retval Value translated from String.\r
e1f414b6 400\r
401**/\r
402UINTN\r
403EFIAPI\r
404StrDecimalToUintn (\r
2fc60b70 405 IN CONST CHAR16 *String\r
e1f414b6 406 )\r
407{\r
408 UINTN Result;\r
e1f414b6 409\r
ea2e0921 410 StrDecimalToUintnS (String, (CHAR16 **) NULL, &Result);\r
e1f414b6 411 return Result;\r
412}\r
413\r
414\r
415/**\r
9aa049d9 416 Convert a Null-terminated Unicode decimal string to a value of\r
e1f414b6 417 type UINT64.\r
418\r
9aa049d9 419 This function returns a value of type UINT64 by interpreting the contents\r
420 of the Unicode string specified by String as a decimal number. The format\r
e1f414b6 421 of the input Unicode string String is:\r
9aa049d9 422\r
2fe241a2 423 [spaces] [decimal digits].\r
9aa049d9 424\r
425 The valid decimal digit character is in the range [0-9]. The\r
426 function will ignore the pad space, which includes spaces or\r
427 tab characters, before [decimal digits]. The running zero in the\r
428 beginning of [decimal digits] will be ignored. Then, the function\r
429 stops at the first character that is a not a valid decimal character\r
430 or a Null-terminator, whichever one comes first.\r
431\r
e1f414b6 432 If String is NULL, then ASSERT().\r
9aa049d9 433 If String is not aligned in a 16-bit boundary, then ASSERT().\r
e1f414b6 434 If String has only pad spaces, then 0 is returned.\r
9aa049d9 435 If String has no pad spaces or valid decimal digits,\r
e1f414b6 436 then 0 is returned.\r
9aa049d9 437 If the number represented by String overflows according\r
ea2e0921 438 to the range defined by UINT64, then MAX_UINT64 is returned.\r
9aa049d9 439\r
440 If PcdMaximumUnicodeStringLength is not zero, and String contains\r
dfbe9de9 441 more than PcdMaximumUnicodeStringLength Unicode characters, not including\r
e1f414b6 442 the Null-terminator, then ASSERT().\r
443\r
127010dd 444 @param String A pointer to a Null-terminated Unicode string.\r
e1f414b6 445\r
9aa049d9 446 @retval Value translated from String.\r
e1f414b6 447\r
448**/\r
449UINT64\r
450EFIAPI\r
451StrDecimalToUint64 (\r
2fc60b70 452 IN CONST CHAR16 *String\r
e1f414b6 453 )\r
454{\r
455 UINT64 Result;\r
9095d37b 456\r
ea2e0921 457 StrDecimalToUint64S (String, (CHAR16 **) NULL, &Result);\r
e1f414b6 458 return Result;\r
459}\r
460\r
461/**\r
462 Convert a Null-terminated Unicode hexadecimal string to a value of type UINTN.\r
463\r
9aa049d9 464 This function returns a value of type UINTN by interpreting the contents\r
465 of the Unicode string specified by String as a hexadecimal number.\r
e1f414b6 466 The format of the input Unicode string String is:\r
9aa049d9 467\r
468 [spaces][zeros][x][hexadecimal digits].\r
469\r
470 The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
471 The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.\r
472 If "x" appears in the input string, it must be prefixed with at least one 0.\r
473 The function will ignore the pad space, which includes spaces or tab characters,\r
474 before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or\r
475 [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the\r
476 first valid hexadecimal digit. Then, the function stops at the first character that is\r
e1f414b6 477 a not a valid hexadecimal character or NULL, whichever one comes first.\r
478\r
479 If String is NULL, then ASSERT().\r
480 If String is not aligned in a 16-bit boundary, then ASSERT().\r
481 If String has only pad spaces, then zero is returned.\r
9aa049d9 482 If String has no leading pad spaces, leading zeros or valid hexadecimal digits,\r
e1f414b6 483 then zero is returned.\r
9aa049d9 484 If the number represented by String overflows according to the range defined by\r
ea2e0921 485 UINTN, then MAX_UINTN is returned.\r
e1f414b6 486\r
9aa049d9 487 If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
dfbe9de9 488 PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,\r
e1f414b6 489 then ASSERT().\r
490\r
127010dd 491 @param String A pointer to a Null-terminated Unicode string.\r
e1f414b6 492\r
9aa049d9 493 @retval Value translated from String.\r
e1f414b6 494\r
495**/\r
496UINTN\r
497EFIAPI\r
498StrHexToUintn (\r
2fc60b70 499 IN CONST CHAR16 *String\r
e1f414b6 500 )\r
501{\r
502 UINTN Result;\r
503\r
ea2e0921 504 StrHexToUintnS (String, (CHAR16 **) NULL, &Result);\r
e1f414b6 505 return Result;\r
506}\r
507\r
508\r
509/**\r
510 Convert a Null-terminated Unicode hexadecimal string to a value of type UINT64.\r
511\r
9aa049d9 512 This function returns a value of type UINT64 by interpreting the contents\r
513 of the Unicode string specified by String as a hexadecimal number.\r
514 The format of the input Unicode string String is\r
515\r
516 [spaces][zeros][x][hexadecimal digits].\r
517\r
518 The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
519 The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.\r
520 If "x" appears in the input string, it must be prefixed with at least one 0.\r
521 The function will ignore the pad space, which includes spaces or tab characters,\r
522 before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or\r
523 [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the\r
524 first valid hexadecimal digit. Then, the function stops at the first character that is\r
e1f414b6 525 a not a valid hexadecimal character or NULL, whichever one comes first.\r
526\r
527 If String is NULL, then ASSERT().\r
528 If String is not aligned in a 16-bit boundary, then ASSERT().\r
529 If String has only pad spaces, then zero is returned.\r
9aa049d9 530 If String has no leading pad spaces, leading zeros or valid hexadecimal digits,\r
e1f414b6 531 then zero is returned.\r
9aa049d9 532 If the number represented by String overflows according to the range defined by\r
ea2e0921 533 UINT64, then MAX_UINT64 is returned.\r
e1f414b6 534\r
9aa049d9 535 If PcdMaximumUnicodeStringLength is not zero, and String contains more than\r
dfbe9de9 536 PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,\r
e1f414b6 537 then ASSERT().\r
538\r
127010dd 539 @param String A pointer to a Null-terminated Unicode string.\r
e1f414b6 540\r
9aa049d9 541 @retval Value translated from String.\r
e1f414b6 542\r
2fc60b70 543**/\r
e1f414b6 544UINT64\r
545EFIAPI\r
546StrHexToUint64 (\r
2fc60b70 547 IN CONST CHAR16 *String\r
e1f414b6 548 )\r
549{\r
550 UINT64 Result;\r
551\r
ea2e0921 552 StrHexToUint64S (String, (CHAR16 **) NULL, &Result);\r
e1f414b6 553 return Result;\r
554}\r
555\r
556/**\r
557 Check if a ASCII character is a decimal character.\r
558\r
9095d37b 559 This internal function checks if a Unicode character is a\r
e1f414b6 560 decimal character. The valid decimal character is from\r
561 '0' to '9'.\r
562\r
563 @param Char The character to check against.\r
564\r
565 @retval TRUE If the Char is a decmial character.\r
24dcb5e5 566 @retval FALSE If the Char is not a decmial character.\r
e1f414b6 567\r
568**/\r
e1f414b6 569BOOLEAN\r
42eedea9 570EFIAPI\r
e1f414b6 571InternalAsciiIsDecimalDigitCharacter (\r
572 IN CHAR8 Char\r
573 )\r
574{\r
575 return (BOOLEAN) (Char >= '0' && Char <= '9');\r
576}\r
577\r
578/**\r
579 Check if a ASCII character is a hexadecimal character.\r
580\r
9095d37b
LG
581 This internal function checks if a ASCII character is a\r
582 decimal character. The valid hexadecimal character is\r
e1f414b6 583 L'0' to L'9', L'a' to L'f', or L'A' to L'F'.\r
584\r
585\r
586 @param Char The character to check against.\r
587\r
588 @retval TRUE If the Char is a hexadecmial character.\r
24dcb5e5 589 @retval FALSE If the Char is not a hexadecmial character.\r
e1f414b6 590\r
591**/\r
e1f414b6 592BOOLEAN\r
42eedea9 593EFIAPI\r
e1f414b6 594InternalAsciiIsHexaDecimalDigitCharacter (\r
595 IN CHAR8 Char\r
596 )\r
597{\r
598\r
599 return (BOOLEAN) (InternalAsciiIsDecimalDigitCharacter (Char) ||\r
600 (Char >= 'A' && Char <= 'F') ||\r
601 (Char >= 'a' && Char <= 'f'));\r
602}\r
603\r
e1f414b6 604\r
605/**\r
606 Returns the length of a Null-terminated ASCII string.\r
607\r
608 This function returns the number of ASCII characters in the Null-terminated\r
609 ASCII string specified by String.\r
610\r
9aa049d9 611 If Length > 0 and Destination is NULL, then ASSERT().\r
612 If Length > 0 and Source is NULL, then ASSERT().\r
e1f414b6 613 If PcdMaximumAsciiStringLength is not zero and String contains more than\r
dfbe9de9 614 PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,\r
e1f414b6 615 then ASSERT().\r
616\r
127010dd 617 @param String A pointer to a Null-terminated ASCII string.\r
e1f414b6 618\r
619 @return The length of String.\r
620\r
621**/\r
622UINTN\r
623EFIAPI\r
624AsciiStrLen (\r
625 IN CONST CHAR8 *String\r
626 )\r
627{\r
628 UINTN Length;\r
629\r
630 ASSERT (String != NULL);\r
631\r
632 for (Length = 0; *String != '\0'; String++, Length++) {\r
633 //\r
634 // If PcdMaximumUnicodeStringLength is not zero,\r
635 // length should not more than PcdMaximumUnicodeStringLength\r
636 //\r
637 if (PcdGet32 (PcdMaximumAsciiStringLength) != 0) {\r
638 ASSERT (Length < PcdGet32 (PcdMaximumAsciiStringLength));\r
639 }\r
640 }\r
641 return Length;\r
642}\r
643\r
644/**\r
645 Returns the size of a Null-terminated ASCII string in bytes, including the\r
646 Null terminator.\r
647\r
648 This function returns the size, in bytes, of the Null-terminated ASCII string\r
649 specified by String.\r
650\r
651 If String is NULL, then ASSERT().\r
652 If PcdMaximumAsciiStringLength is not zero and String contains more than\r
dfbe9de9 653 PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,\r
e1f414b6 654 then ASSERT().\r
655\r
127010dd 656 @param String A pointer to a Null-terminated ASCII string.\r
e1f414b6 657\r
658 @return The size of String.\r
659\r
660**/\r
661UINTN\r
662EFIAPI\r
663AsciiStrSize (\r
664 IN CONST CHAR8 *String\r
665 )\r
666{\r
667 return (AsciiStrLen (String) + 1) * sizeof (*String);\r
668}\r
669\r
670/**\r
671 Compares two Null-terminated ASCII strings, and returns the difference\r
672 between the first mismatched ASCII characters.\r
673\r
674 This function compares the Null-terminated ASCII string FirstString to the\r
675 Null-terminated ASCII string SecondString. If FirstString is identical to\r
676 SecondString, then 0 is returned. Otherwise, the value returned is the first\r
677 mismatched ASCII character in SecondString subtracted from the first\r
678 mismatched ASCII character in FirstString.\r
679\r
680 If FirstString is NULL, then ASSERT().\r
681 If SecondString is NULL, then ASSERT().\r
682 If PcdMaximumAsciiStringLength is not zero and FirstString contains more than\r
dfbe9de9 683 PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,\r
e1f414b6 684 then ASSERT().\r
685 If PcdMaximumAsciiStringLength is not zero and SecondString contains more\r
dfbe9de9 686 than PcdMaximumAsciiStringLength ASCII characters, not including the\r
e1f414b6 687 Null-terminator, then ASSERT().\r
688\r
127010dd 689 @param FirstString A pointer to a Null-terminated ASCII string.\r
690 @param SecondString A pointer to a Null-terminated ASCII string.\r
e1f414b6 691\r
9aa049d9 692 @retval ==0 FirstString is identical to SecondString.\r
693 @retval !=0 FirstString is not identical to SecondString.\r
e1f414b6 694\r
695**/\r
696INTN\r
697EFIAPI\r
698AsciiStrCmp (\r
699 IN CONST CHAR8 *FirstString,\r
700 IN CONST CHAR8 *SecondString\r
701 )\r
702{\r
703 //\r
704 // ASSERT both strings are less long than PcdMaximumAsciiStringLength\r
705 //\r
706 ASSERT (AsciiStrSize (FirstString));\r
707 ASSERT (AsciiStrSize (SecondString));\r
708\r
709 while ((*FirstString != '\0') && (*FirstString == *SecondString)) {\r
710 FirstString++;\r
711 SecondString++;\r
712 }\r
713\r
714 return *FirstString - *SecondString;\r
715}\r
716\r
717/**\r
24dcb5e5 718 Converts a lowercase Ascii character to upper one.\r
e1f414b6 719\r
720 If Chr is lowercase Ascii character, then converts it to upper one.\r
721\r
722 If Value >= 0xA0, then ASSERT().\r
723 If (Value & 0x0F) >= 0x0A, then ASSERT().\r
724\r
42eedea9 725 @param Chr one Ascii character\r
e1f414b6 726\r
9095d37b 727 @return The uppercase value of Ascii character\r
e1f414b6 728\r
729**/\r
e1f414b6 730CHAR8\r
42eedea9 731EFIAPI\r
5dbfa01e 732AsciiCharToUpper (\r
e1f414b6 733 IN CHAR8 Chr\r
734 )\r
735{\r
736 return (UINT8) ((Chr >= 'a' && Chr <= 'z') ? Chr - ('a' - 'A') : Chr);\r
737}\r
738\r
739/**\r
740 Convert a ASCII character to numerical value.\r
741\r
742 This internal function only deal with Unicode character\r
743 which maps to a valid hexadecimal ASII character, i.e.\r
9095d37b 744 '0' to '9', 'a' to 'f' or 'A' to 'F'. For other\r
e1f414b6 745 ASCII character, the value returned does not make sense.\r
746\r
747 @param Char The character to convert.\r
748\r
24dcb5e5 749 @return The numerical value converted.\r
e1f414b6 750\r
751**/\r
e1f414b6 752UINTN\r
42eedea9 753EFIAPI\r
e1f414b6 754InternalAsciiHexCharToUintn (\r
755 IN CHAR8 Char\r
756 )\r
757{\r
758 if (InternalIsDecimalDigitCharacter (Char)) {\r
759 return Char - '0';\r
760 }\r
761\r
5dbfa01e 762 return (10 + AsciiCharToUpper (Char) - 'A');\r
e1f414b6 763}\r
764\r
765\r
766/**\r
767 Performs a case insensitive comparison of two Null-terminated ASCII strings,\r
768 and returns the difference between the first mismatched ASCII characters.\r
769\r
770 This function performs a case insensitive comparison of the Null-terminated\r
771 ASCII string FirstString to the Null-terminated ASCII string SecondString. If\r
772 FirstString is identical to SecondString, then 0 is returned. Otherwise, the\r
773 value returned is the first mismatched lower case ASCII character in\r
774 SecondString subtracted from the first mismatched lower case ASCII character\r
775 in FirstString.\r
776\r
777 If FirstString is NULL, then ASSERT().\r
778 If SecondString is NULL, then ASSERT().\r
779 If PcdMaximumAsciiStringLength is not zero and FirstString contains more than\r
dfbe9de9 780 PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,\r
e1f414b6 781 then ASSERT().\r
782 If PcdMaximumAsciiStringLength is not zero and SecondString contains more\r
dfbe9de9 783 than PcdMaximumAsciiStringLength ASCII characters, not including the\r
e1f414b6 784 Null-terminator, then ASSERT().\r
785\r
127010dd 786 @param FirstString A pointer to a Null-terminated ASCII string.\r
787 @param SecondString A pointer to a Null-terminated ASCII string.\r
e1f414b6 788\r
9aa049d9 789 @retval ==0 FirstString is identical to SecondString using case insensitive\r
1106ffe1 790 comparisons.\r
9aa049d9 791 @retval !=0 FirstString is not identical to SecondString using case\r
792 insensitive comparisons.\r
e1f414b6 793\r
794**/\r
795INTN\r
796EFIAPI\r
797AsciiStriCmp (\r
798 IN CONST CHAR8 *FirstString,\r
799 IN CONST CHAR8 *SecondString\r
800 )\r
801{\r
802 CHAR8 UpperFirstString;\r
803 CHAR8 UpperSecondString;\r
804\r
805 //\r
806 // ASSERT both strings are less long than PcdMaximumAsciiStringLength\r
807 //\r
808 ASSERT (AsciiStrSize (FirstString));\r
809 ASSERT (AsciiStrSize (SecondString));\r
810\r
5dbfa01e
MT
811 UpperFirstString = AsciiCharToUpper (*FirstString);\r
812 UpperSecondString = AsciiCharToUpper (*SecondString);\r
c1f032cd 813 while ((*FirstString != '\0') && (*SecondString != '\0') && (UpperFirstString == UpperSecondString)) {\r
e1f414b6 814 FirstString++;\r
815 SecondString++;\r
5dbfa01e
MT
816 UpperFirstString = AsciiCharToUpper (*FirstString);\r
817 UpperSecondString = AsciiCharToUpper (*SecondString);\r
e1f414b6 818 }\r
819\r
820 return UpperFirstString - UpperSecondString;\r
821}\r
822\r
823/**\r
824 Compares two Null-terminated ASCII strings with maximum lengths, and returns\r
825 the difference between the first mismatched ASCII characters.\r
826\r
827 This function compares the Null-terminated ASCII string FirstString to the\r
828 Null-terminated ASCII string SecondString. At most, Length ASCII characters\r
829 will be compared. If Length is 0, then 0 is returned. If FirstString is\r
830 identical to SecondString, then 0 is returned. Otherwise, the value returned\r
831 is the first mismatched ASCII character in SecondString subtracted from the\r
832 first mismatched ASCII character in FirstString.\r
833\r
9aa049d9 834 If Length > 0 and FirstString is NULL, then ASSERT().\r
835 If Length > 0 and SecondString is NULL, then ASSERT().\r
9095d37b 836 If PcdMaximumAsciiStringLength is not zero, and Length is greater than\r
53e96610 837 PcdMaximumAsciiStringLength, then ASSERT().\r
838 If PcdMaximumAsciiStringLength is not zero, and FirstString contains more than\r
dfbe9de9 839 PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,\r
e1f414b6 840 then ASSERT().\r
53e96610 841 If PcdMaximumAsciiStringLength is not zero, and SecondString contains more than\r
dfbe9de9 842 PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,\r
53e96610 843 then ASSERT().\r
e1f414b6 844\r
127010dd 845 @param FirstString A pointer to a Null-terminated ASCII string.\r
846 @param SecondString A pointer to a Null-terminated ASCII string.\r
2fc59a00 847 @param Length The maximum number of ASCII characters for compare.\r
9095d37b 848\r
9aa049d9 849 @retval ==0 FirstString is identical to SecondString.\r
850 @retval !=0 FirstString is not identical to SecondString.\r
e1f414b6 851\r
852**/\r
853INTN\r
854EFIAPI\r
855AsciiStrnCmp (\r
856 IN CONST CHAR8 *FirstString,\r
857 IN CONST CHAR8 *SecondString,\r
858 IN UINTN Length\r
859 )\r
860{\r
2bfb6009 861 if (Length == 0) {\r
e1f414b6 862 return 0;\r
863 }\r
864\r
865 //\r
866 // ASSERT both strings are less long than PcdMaximumAsciiStringLength\r
867 //\r
868 ASSERT (AsciiStrSize (FirstString));\r
869 ASSERT (AsciiStrSize (SecondString));\r
870\r
dfbe9de9 871 if (PcdGet32 (PcdMaximumAsciiStringLength) != 0) {\r
872 ASSERT (Length <= PcdGet32 (PcdMaximumAsciiStringLength));\r
873 }\r
874\r
e1f414b6 875 while ((*FirstString != '\0') &&\r
753a18f9 876 (*SecondString != '\0') &&\r
e1f414b6 877 (*FirstString == *SecondString) &&\r
878 (Length > 1)) {\r
879 FirstString++;\r
880 SecondString++;\r
881 Length--;\r
882 }\r
883 return *FirstString - *SecondString;\r
884}\r
885\r
e1f414b6 886\r
887/**\r
9aa049d9 888 Returns the first occurrence of a Null-terminated ASCII sub-string\r
e1f414b6 889 in a Null-terminated ASCII string.\r
890\r
9aa049d9 891 This function scans the contents of the ASCII string specified by String\r
892 and returns the first occurrence of SearchString. If SearchString is not\r
893 found in String, then NULL is returned. If the length of SearchString is zero,\r
e1f414b6 894 then String is returned.\r
9aa049d9 895\r
e1f414b6 896 If String is NULL, then ASSERT().\r
897 If SearchString is NULL, then ASSERT().\r
898\r
9aa049d9 899 If PcdMaximumAsciiStringLength is not zero, and SearchString or\r
900 String contains more than PcdMaximumAsciiStringLength Unicode characters\r
e1f414b6 901 not including the Null-terminator, then ASSERT().\r
902\r
127010dd 903 @param String A pointer to a Null-terminated ASCII string.\r
904 @param SearchString A pointer to a Null-terminated ASCII string to search for.\r
e1f414b6 905\r
906 @retval NULL If the SearchString does not appear in String.\r
9aa049d9 907 @retval others If there is a match return the first occurrence of SearchingString.\r
908 If the length of SearchString is zero,return String.\r
e1f414b6 909\r
910**/\r
911CHAR8 *\r
912EFIAPI\r
913AsciiStrStr (\r
2fc60b70 914 IN CONST CHAR8 *String,\r
915 IN CONST CHAR8 *SearchString\r
e1f414b6 916 )\r
917{\r
918 CONST CHAR8 *FirstMatch;\r
919 CONST CHAR8 *SearchStringTmp;\r
920\r
e1f414b6 921 //\r
4df26661 922 // ASSERT both strings are less long than PcdMaximumAsciiStringLength\r
e1f414b6 923 //\r
4df26661 924 ASSERT (AsciiStrSize (String) != 0);\r
925 ASSERT (AsciiStrSize (SearchString) != 0);\r
e1f414b6 926\r
62e71e2f 927 if (*SearchString == '\0') {\r
faeb3214 928 return (CHAR8 *) String;\r
62e71e2f 929 }\r
930\r
e1f414b6 931 while (*String != '\0') {\r
932 SearchStringTmp = SearchString;\r
933 FirstMatch = String;\r
9095d37b
LG
934\r
935 while ((*String == *SearchStringTmp)\r
e1f414b6 936 && (*String != '\0')) {\r
937 String++;\r
938 SearchStringTmp++;\r
9095d37b
LG
939 }\r
940\r
e1f414b6 941 if (*SearchStringTmp == '\0') {\r
942 return (CHAR8 *) FirstMatch;\r
943 }\r
944\r
62e71e2f 945 if (*String == '\0') {\r
946 return NULL;\r
e1f414b6 947 }\r
948\r
62e71e2f 949 String = FirstMatch + 1;\r
e1f414b6 950 }\r
951\r
952 return NULL;\r
953}\r
954\r
955/**\r
9aa049d9 956 Convert a Null-terminated ASCII decimal string to a value of type\r
e1f414b6 957 UINTN.\r
958\r
9aa049d9 959 This function returns a value of type UINTN by interpreting the contents\r
960 of the ASCII string String as a decimal number. The format of the input\r
e1f414b6 961 ASCII string String is:\r
9aa049d9 962\r
e1f414b6 963 [spaces] [decimal digits].\r
9aa049d9 964\r
965 The valid decimal digit character is in the range [0-9]. The function will\r
966 ignore the pad space, which includes spaces or tab characters, before the digits.\r
967 The running zero in the beginning of [decimal digits] will be ignored. Then, the\r
968 function stops at the first character that is a not a valid decimal character or\r
e1f414b6 969 Null-terminator, whichever on comes first.\r
9aa049d9 970\r
e1f414b6 971 If String has only pad spaces, then 0 is returned.\r
972 If String has no pad spaces or valid decimal digits, then 0 is returned.\r
9aa049d9 973 If the number represented by String overflows according to the range defined by\r
ea2e0921 974 UINTN, then MAX_UINTN is returned.\r
e1f414b6 975 If String is NULL, then ASSERT().\r
9aa049d9 976 If PcdMaximumAsciiStringLength is not zero, and String contains more than\r
977 PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator,\r
e1f414b6 978 then ASSERT().\r
979\r
127010dd 980 @param String A pointer to a Null-terminated ASCII string.\r
e1f414b6 981\r
9aa049d9 982 @retval Value translated from String.\r
e1f414b6 983\r
984**/\r
985UINTN\r
986EFIAPI\r
987AsciiStrDecimalToUintn (\r
4df26661 988 IN CONST CHAR8 *String\r
e1f414b6 989 )\r
990{\r
991 UINTN Result;\r
9095d37b 992\r
ea2e0921 993 AsciiStrDecimalToUintnS (String, (CHAR8 **) NULL, &Result);\r
e1f414b6 994 return Result;\r
995}\r
996\r
997\r
998/**\r
9aa049d9 999 Convert a Null-terminated ASCII decimal string to a value of type\r
e1f414b6 1000 UINT64.\r
1001\r
9aa049d9 1002 This function returns a value of type UINT64 by interpreting the contents\r
1003 of the ASCII string String as a decimal number. The format of the input\r
e1f414b6 1004 ASCII string String is:\r
9aa049d9 1005\r
e1f414b6 1006 [spaces] [decimal digits].\r
9aa049d9 1007\r
1008 The valid decimal digit character is in the range [0-9]. The function will\r
1009 ignore the pad space, which includes spaces or tab characters, before the digits.\r
1010 The running zero in the beginning of [decimal digits] will be ignored. Then, the\r
1011 function stops at the first character that is a not a valid decimal character or\r
e1f414b6 1012 Null-terminator, whichever on comes first.\r
9aa049d9 1013\r
e1f414b6 1014 If String has only pad spaces, then 0 is returned.\r
1015 If String has no pad spaces or valid decimal digits, then 0 is returned.\r
9aa049d9 1016 If the number represented by String overflows according to the range defined by\r
ea2e0921 1017 UINT64, then MAX_UINT64 is returned.\r
e1f414b6 1018 If String is NULL, then ASSERT().\r
9aa049d9 1019 If PcdMaximumAsciiStringLength is not zero, and String contains more than\r
1020 PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator,\r
e1f414b6 1021 then ASSERT().\r
1022\r
127010dd 1023 @param String A pointer to a Null-terminated ASCII string.\r
e1f414b6 1024\r
9aa049d9 1025 @retval Value translated from String.\r
e1f414b6 1026\r
1027**/\r
1028UINT64\r
1029EFIAPI\r
1030AsciiStrDecimalToUint64 (\r
2fc60b70 1031 IN CONST CHAR8 *String\r
e1f414b6 1032 )\r
1033{\r
1034 UINT64 Result;\r
9095d37b 1035\r
ea2e0921 1036 AsciiStrDecimalToUint64S (String, (CHAR8 **) NULL, &Result);\r
e1f414b6 1037 return Result;\r
1038}\r
1039\r
1040/**\r
1041 Convert a Null-terminated ASCII hexadecimal string to a value of type UINTN.\r
1042\r
9aa049d9 1043 This function returns a value of type UINTN by interpreting the contents of\r
1044 the ASCII string String as a hexadecimal number. The format of the input ASCII\r
e1f414b6 1045 string String is:\r
9aa049d9 1046\r
e1f414b6 1047 [spaces][zeros][x][hexadecimal digits].\r
9aa049d9 1048\r
1049 The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
1050 The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If "x"\r
1051 appears in the input string, it must be prefixed with at least one 0. The function\r
1052 will ignore the pad space, which includes spaces or tab characters, before [zeros],\r
1053 [x] or [hexadecimal digits]. The running zero before [x] or [hexadecimal digits]\r
1054 will be ignored. Then, the decoding starts after [x] or the first valid hexadecimal\r
1055 digit. Then, the function stops at the first character that is a not a valid\r
e1f414b6 1056 hexadecimal character or Null-terminator, whichever on comes first.\r
9aa049d9 1057\r
e1f414b6 1058 If String has only pad spaces, then 0 is returned.\r
1059 If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then\r
1060 0 is returned.\r
1061\r
9aa049d9 1062 If the number represented by String overflows according to the range defined by UINTN,\r
ea2e0921 1063 then MAX_UINTN is returned.\r
e1f414b6 1064 If String is NULL, then ASSERT().\r
9aa049d9 1065 If PcdMaximumAsciiStringLength is not zero,\r
1066 and String contains more than PcdMaximumAsciiStringLength ASCII characters not including\r
e1f414b6 1067 the Null-terminator, then ASSERT().\r
1068\r
127010dd 1069 @param String A pointer to a Null-terminated ASCII string.\r
e1f414b6 1070\r
9aa049d9 1071 @retval Value translated from String.\r
e1f414b6 1072\r
1073**/\r
1074UINTN\r
1075EFIAPI\r
1076AsciiStrHexToUintn (\r
2fc60b70 1077 IN CONST CHAR8 *String\r
e1f414b6 1078 )\r
1079{\r
1080 UINTN Result;\r
1081\r
ea2e0921 1082 AsciiStrHexToUintnS (String, (CHAR8 **) NULL, &Result);\r
e1f414b6 1083 return Result;\r
1084}\r
1085\r
1086\r
1087/**\r
1088 Convert a Null-terminated ASCII hexadecimal string to a value of type UINT64.\r
1089\r
9aa049d9 1090 This function returns a value of type UINT64 by interpreting the contents of\r
1091 the ASCII string String as a hexadecimal number. The format of the input ASCII\r
e1f414b6 1092 string String is:\r
9aa049d9 1093\r
e1f414b6 1094 [spaces][zeros][x][hexadecimal digits].\r
9aa049d9 1095\r
1096 The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
1097 The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If "x"\r
1098 appears in the input string, it must be prefixed with at least one 0. The function\r
1099 will ignore the pad space, which includes spaces or tab characters, before [zeros],\r
1100 [x] or [hexadecimal digits]. The running zero before [x] or [hexadecimal digits]\r
1101 will be ignored. Then, the decoding starts after [x] or the first valid hexadecimal\r
1102 digit. Then, the function stops at the first character that is a not a valid\r
e1f414b6 1103 hexadecimal character or Null-terminator, whichever on comes first.\r
9aa049d9 1104\r
e1f414b6 1105 If String has only pad spaces, then 0 is returned.\r
1106 If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then\r
1107 0 is returned.\r
1108\r
9aa049d9 1109 If the number represented by String overflows according to the range defined by UINT64,\r
ea2e0921 1110 then MAX_UINT64 is returned.\r
e1f414b6 1111 If String is NULL, then ASSERT().\r
9aa049d9 1112 If PcdMaximumAsciiStringLength is not zero,\r
1113 and String contains more than PcdMaximumAsciiStringLength ASCII characters not including\r
e1f414b6 1114 the Null-terminator, then ASSERT().\r
1115\r
127010dd 1116 @param String A pointer to a Null-terminated ASCII string.\r
e1f414b6 1117\r
9aa049d9 1118 @retval Value translated from String.\r
e1f414b6 1119\r
1120**/\r
1121UINT64\r
1122EFIAPI\r
1123AsciiStrHexToUint64 (\r
2fc60b70 1124 IN CONST CHAR8 *String\r
e1f414b6 1125 )\r
1126{\r
1127 UINT64 Result;\r
1128\r
ea2e0921 1129 AsciiStrHexToUint64S (String, (CHAR8 **) NULL, &Result);\r
e1f414b6 1130 return Result;\r
1131}\r
1132\r
415aa2f1 1133\r
1f7af69d
MT
1134STATIC CHAR8 EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"\r
1135 "abcdefghijklmnopqrstuvwxyz"\r
1136 "0123456789+/";\r
1137\r
1f7af69d
MT
1138/**\r
1139 Convert binary data to a Base64 encoded ascii string based on RFC4648.\r
1140\r
1141 Produce a Null-terminated Ascii string in the output buffer specified by Destination and DestinationSize.\r
1142 The Ascii string is produced by converting the data string specified by Source and SourceLength.\r
1143\r
1144 @param Source Input UINT8 data\r
1145 @param SourceLength Number of UINT8 bytes of data\r
1146 @param Destination Pointer to output string buffer\r
1147 @param DestinationSize Size of ascii buffer. Set to 0 to get the size needed.\r
1148 Caller is responsible for passing in buffer of DestinationSize\r
1149\r
1150 @retval RETURN_SUCCESS When ascii buffer is filled in.\r
1151 @retval RETURN_INVALID_PARAMETER If Source is NULL or DestinationSize is NULL.\r
1152 @retval RETURN_INVALID_PARAMETER If SourceLength or DestinationSize is bigger than (MAX_ADDRESS - (UINTN)Destination).\r
1153 @retval RETURN_BUFFER_TOO_SMALL If SourceLength is 0 and DestinationSize is <1.\r
1154 @retval RETURN_BUFFER_TOO_SMALL If Destination is NULL or DestinationSize is smaller than required buffersize.\r
1155\r
1156**/\r
1157RETURN_STATUS\r
1158EFIAPI\r
1159Base64Encode (\r
1160 IN CONST UINT8 *Source,\r
1161 IN UINTN SourceLength,\r
1162 OUT CHAR8 *Destination OPTIONAL,\r
1163 IN OUT UINTN *DestinationSize\r
1164 )\r
1165{\r
1166\r
1167 UINTN RequiredSize;\r
1168 UINTN Left;\r
1169\r
1170 //\r
1171 // Check pointers, and SourceLength is valid\r
1172 //\r
1173 if ((Source == NULL) || (DestinationSize == NULL)) {\r
1174 return RETURN_INVALID_PARAMETER;\r
1175 }\r
1176\r
1177 //\r
1178 // Allow for RFC 4648 test vector 1\r
1179 //\r
1180 if (SourceLength == 0) {\r
1181 if (*DestinationSize < 1) {\r
1182 *DestinationSize = 1;\r
1183 return RETURN_BUFFER_TOO_SMALL;\r
1184 }\r
1185 *DestinationSize = 1;\r
1186 *Destination = '\0';\r
1187 return RETURN_SUCCESS;\r
1188 }\r
1189\r
1190 //\r
1191 // Check if SourceLength or DestinationSize is valid\r
1192 //\r
1193 if ((SourceLength >= (MAX_ADDRESS - (UINTN)Source)) || (*DestinationSize >= (MAX_ADDRESS - (UINTN)Destination))){\r
1194 return RETURN_INVALID_PARAMETER;\r
1195 }\r
1196\r
1197 //\r
1198 // 4 ascii per 3 bytes + NULL\r
1199 //\r
1200 RequiredSize = ((SourceLength + 2) / 3) * 4 + 1;\r
1201 if ((Destination == NULL) || *DestinationSize < RequiredSize) {\r
1202 *DestinationSize = RequiredSize;\r
1203 return RETURN_BUFFER_TOO_SMALL;\r
1204 }\r
1205\r
1206 Left = SourceLength;\r
1207\r
1208 //\r
1209 // Encode 24 bits (three bytes) into 4 ascii characters\r
1210 //\r
1211 while (Left >= 3) {\r
1212\r
1213 *Destination++ = EncodingTable[( Source[0] & 0xfc) >> 2 ];\r
1214 *Destination++ = EncodingTable[((Source[0] & 0x03) << 4) + ((Source[1] & 0xf0) >> 4)];\r
1215 *Destination++ = EncodingTable[((Source[1] & 0x0f) << 2) + ((Source[2] & 0xc0) >> 6)];\r
1216 *Destination++ = EncodingTable[( Source[2] & 0x3f)];\r
1217 Left -= 3;\r
1218 Source += 3;\r
1219 }\r
1220\r
1221 //\r
1222 // Handle the remainder, and add padding '=' characters as necessary.\r
1223 //\r
1224 switch (Left) {\r
1225 case 0:\r
1226\r
1227 //\r
1228 // No bytes Left, done.\r
1229 //\r
1230 break;\r
1231 case 1:\r
1232\r
1233 //\r
1234 // One more data byte, two pad characters\r
1235 //\r
1236 *Destination++ = EncodingTable[( Source[0] & 0xfc) >> 2];\r
1237 *Destination++ = EncodingTable[((Source[0] & 0x03) << 4)];\r
1238 *Destination++ = '=';\r
1239 *Destination++ = '=';\r
1240 break;\r
1241 case 2:\r
1242\r
1243 //\r
1244 // Two more data bytes, and one pad character\r
1245 //\r
1246 *Destination++ = EncodingTable[( Source[0] & 0xfc) >> 2];\r
1247 *Destination++ = EncodingTable[((Source[0] & 0x03) << 4) + ((Source[1] & 0xf0) >> 4)];\r
1248 *Destination++ = EncodingTable[((Source[1] & 0x0f) << 2)];\r
1249 *Destination++ = '=';\r
1250 break;\r
1251 }\r
1252 //\r
1253 // Add terminating NULL\r
1254 //\r
1255 *Destination = '\0';\r
1256 return RETURN_SUCCESS;\r
1257}\r
1258\r
1259/**\r
5d68fc67
LE
1260 Decode Base64 ASCII encoded data to 8-bit binary representation, based on\r
1261 RFC4648.\r
1262\r
1263 Decoding occurs according to "Table 1: The Base 64 Alphabet" in RFC4648.\r
1264\r
1265 Whitespace is ignored at all positions:\r
1266 - 0x09 ('\t') horizontal tab\r
1267 - 0x0A ('\n') new line\r
1268 - 0x0B ('\v') vertical tab\r
1269 - 0x0C ('\f') form feed\r
1270 - 0x0D ('\r') carriage return\r
1271 - 0x20 (' ') space\r
1272\r
1273 The minimum amount of required padding (with ASCII 0x3D, '=') is tolerated\r
1274 and enforced at the end of the Base64 ASCII encoded data, and only there.\r
1275\r
1276 Other characters outside of the encoding alphabet cause the function to\r
1277 reject the Base64 ASCII encoded data.\r
1278\r
1279 @param[in] Source Array of CHAR8 elements containing the Base64\r
1280 ASCII encoding. May be NULL if SourceSize is\r
1281 zero.\r
1282\r
1283 @param[in] SourceSize Number of CHAR8 elements in Source.\r
1284\r
1285 @param[out] Destination Array of UINT8 elements receiving the decoded\r
1286 8-bit binary representation. Allocated by the\r
1287 caller. May be NULL if DestinationSize is\r
1288 zero on input. If NULL, decoding is\r
1289 performed, but the 8-bit binary\r
1290 representation is not stored. If non-NULL and\r
1291 the function returns an error, the contents\r
1292 of Destination are indeterminate.\r
1293\r
1294 @param[in,out] DestinationSize On input, the number of UINT8 elements that\r
1295 the caller allocated for Destination. On\r
1296 output, if the function returns\r
1297 RETURN_SUCCESS or RETURN_BUFFER_TOO_SMALL,\r
1298 the number of UINT8 elements that are\r
1299 required for decoding the Base64 ASCII\r
1300 representation. If the function returns a\r
1301 value different from both RETURN_SUCCESS and\r
1302 RETURN_BUFFER_TOO_SMALL, then DestinationSize\r
1303 is indeterminate on output.\r
1304\r
1305 @retval RETURN_SUCCESS SourceSize CHAR8 elements at Source have\r
1306 been decoded to on-output DestinationSize\r
1307 UINT8 elements at Destination. Note that\r
1308 RETURN_SUCCESS covers the case when\r
1309 DestinationSize is zero on input, and\r
1310 Source decodes to zero bytes (due to\r
1311 containing at most ignored whitespace).\r
1312\r
1313 @retval RETURN_BUFFER_TOO_SMALL The input value of DestinationSize is not\r
1314 large enough for decoding SourceSize CHAR8\r
1315 elements at Source. The required number of\r
1316 UINT8 elements has been stored to\r
1317 DestinationSize.\r
1318\r
1319 @retval RETURN_INVALID_PARAMETER DestinationSize is NULL.\r
1320\r
1321 @retval RETURN_INVALID_PARAMETER Source is NULL, but SourceSize is not zero.\r
1322\r
1323 @retval RETURN_INVALID_PARAMETER Destination is NULL, but DestinationSize is\r
1324 not zero on input.\r
1325\r
1326 @retval RETURN_INVALID_PARAMETER Source is non-NULL, and (Source +\r
1327 SourceSize) would wrap around MAX_ADDRESS.\r
1328\r
1329 @retval RETURN_INVALID_PARAMETER Destination is non-NULL, and (Destination +\r
1330 DestinationSize) would wrap around\r
1331 MAX_ADDRESS, as specified on input.\r
1332\r
1333 @retval RETURN_INVALID_PARAMETER None of Source and Destination are NULL,\r
1334 and CHAR8[SourceSize] at Source overlaps\r
1335 UINT8[DestinationSize] at Destination, as\r
1336 specified on input.\r
1337\r
1338 @retval RETURN_INVALID_PARAMETER Invalid CHAR8 element encountered in\r
1339 Source.\r
1340**/\r
1f7af69d
MT
1341RETURN_STATUS\r
1342EFIAPI\r
1343Base64Decode (\r
5d68fc67
LE
1344 IN CONST CHAR8 *Source OPTIONAL,\r
1345 IN UINTN SourceSize,\r
1346 OUT UINT8 *Destination OPTIONAL,\r
1347 IN OUT UINTN *DestinationSize\r
1f7af69d
MT
1348 )\r
1349{\r
35e242b6
LE
1350 BOOLEAN PaddingMode;\r
1351 UINTN SixBitGroupsConsumed;\r
1352 UINT32 Accumulator;\r
1353 UINTN OriginalDestinationSize;\r
1354 UINTN SourceIndex;\r
cce01f53
LE
1355 CHAR8 SourceChar;\r
1356 UINT32 Base64Value;\r
1357 UINT8 DestinationOctet;\r
35e242b6
LE
1358\r
1359 if (DestinationSize == NULL) {\r
1360 return RETURN_INVALID_PARAMETER;\r
1361 }\r
1362\r
1363 //\r
1364 // Check Source array validity.\r
1365 //\r
1366 if (Source == NULL) {\r
1367 if (SourceSize > 0) {\r
1368 //\r
1369 // At least one CHAR8 element at NULL Source.\r
1370 //\r
1371 return RETURN_INVALID_PARAMETER;\r
1372 }\r
1373 } else if (SourceSize > MAX_ADDRESS - (UINTN)Source) {\r
1374 //\r
1375 // Non-NULL Source, but it wraps around.\r
1376 //\r
1377 return RETURN_INVALID_PARAMETER;\r
1378 }\r
1379\r
1380 //\r
1381 // Check Destination array validity.\r
1382 //\r
1383 if (Destination == NULL) {\r
1384 if (*DestinationSize > 0) {\r
1385 //\r
1386 // At least one UINT8 element at NULL Destination.\r
1387 //\r
1388 return RETURN_INVALID_PARAMETER;\r
1389 }\r
1390 } else if (*DestinationSize > MAX_ADDRESS - (UINTN)Destination) {\r
1391 //\r
1392 // Non-NULL Destination, but it wraps around.\r
1393 //\r
1394 return RETURN_INVALID_PARAMETER;\r
1395 }\r
1396\r
1397 //\r
1398 // Check for overlap.\r
1399 //\r
1400 if (Source != NULL && Destination != NULL) {\r
1401 //\r
1402 // Both arrays have been provided, and we know from earlier that each array\r
1403 // is valid in itself.\r
1404 //\r
1405 if ((UINTN)Source + SourceSize <= (UINTN)Destination) {\r
1406 //\r
1407 // Source array precedes Destination array, OK.\r
1408 //\r
1409 } else if ((UINTN)Destination + *DestinationSize <= (UINTN)Source) {\r
1410 //\r
1411 // Destination array precedes Source array, OK.\r
1412 //\r
1413 } else {\r
1414 //\r
1415 // Overlap.\r
1416 //\r
1417 return RETURN_INVALID_PARAMETER;\r
1418 }\r
1419 }\r
1420\r
1421 //\r
1422 // Decoding loop setup.\r
1423 //\r
1424 PaddingMode = FALSE;\r
1425 SixBitGroupsConsumed = 0;\r
1426 Accumulator = 0;\r
1427 OriginalDestinationSize = *DestinationSize;\r
1428 *DestinationSize = 0;\r
1429\r
1430 //\r
1431 // Decoding loop.\r
1432 //\r
1433 for (SourceIndex = 0; SourceIndex < SourceSize; SourceIndex++) {\r
35e242b6
LE
1434 SourceChar = Source[SourceIndex];\r
1435\r
1436 //\r
1437 // Whitespace is ignored at all positions (regardless of padding mode).\r
1438 //\r
1439 if (SourceChar == '\t' || SourceChar == '\n' || SourceChar == '\v' ||\r
1440 SourceChar == '\f' || SourceChar == '\r' || SourceChar == ' ') {\r
1441 continue;\r
1442 }\r
1443\r
1444 //\r
1445 // If we're in padding mode, accept another padding character, as long as\r
1446 // that padding character completes the quantum. This completes case (2)\r
1447 // from RFC4648, Chapter 4. "Base 64 Encoding":\r
1448 //\r
1449 // (2) The final quantum of encoding input is exactly 8 bits; here, the\r
1450 // final unit of encoded output will be two characters followed by two\r
1451 // "=" padding characters.\r
1452 //\r
1453 if (PaddingMode) {\r
1454 if (SourceChar == '=' && SixBitGroupsConsumed == 3) {\r
1455 SixBitGroupsConsumed = 0;\r
1456 continue;\r
1457 }\r
1458 return RETURN_INVALID_PARAMETER;\r
1459 }\r
1460\r
1461 //\r
1462 // When not in padding mode, decode Base64Value based on RFC4648, "Table 1:\r
1463 // The Base 64 Alphabet".\r
1464 //\r
1465 if ('A' <= SourceChar && SourceChar <= 'Z') {\r
1466 Base64Value = SourceChar - 'A';\r
1467 } else if ('a' <= SourceChar && SourceChar <= 'z') {\r
1468 Base64Value = 26 + (SourceChar - 'a');\r
1469 } else if ('0' <= SourceChar && SourceChar <= '9') {\r
1470 Base64Value = 52 + (SourceChar - '0');\r
1471 } else if (SourceChar == '+') {\r
1472 Base64Value = 62;\r
1473 } else if (SourceChar == '/') {\r
1474 Base64Value = 63;\r
1475 } else if (SourceChar == '=') {\r
1476 //\r
1477 // Enter padding mode.\r
1478 //\r
1479 PaddingMode = TRUE;\r
1480\r
1481 if (SixBitGroupsConsumed == 2) {\r
1482 //\r
1483 // If we have consumed two 6-bit groups from the current quantum before\r
1484 // encountering the first padding character, then this is case (2) from\r
1485 // RFC4648, Chapter 4. "Base 64 Encoding". Bump SixBitGroupsConsumed,\r
1486 // and we'll enforce another padding character.\r
1487 //\r
1488 SixBitGroupsConsumed = 3;\r
1489 } else if (SixBitGroupsConsumed == 3) {\r
1490 //\r
1491 // If we have consumed three 6-bit groups from the current quantum\r
1492 // before encountering the first padding character, then this is case\r
1493 // (3) from RFC4648, Chapter 4. "Base 64 Encoding". The quantum is now\r
1494 // complete.\r
1495 //\r
1496 SixBitGroupsConsumed = 0;\r
1497 } else {\r
1498 //\r
1499 // Padding characters are not allowed at the first two positions of a\r
1500 // quantum.\r
1501 //\r
1502 return RETURN_INVALID_PARAMETER;\r
1503 }\r
1504\r
1505 //\r
1506 // Wherever in a quantum we enter padding mode, we enforce the padding\r
1507 // bits pending in the accumulator -- from the last 6-bit group just\r
1508 // preceding the padding character -- to be zero. Refer to RFC4648,\r
1509 // Chapter 3.5. "Canonical Encoding".\r
1510 //\r
1511 if (Accumulator != 0) {\r
1512 return RETURN_INVALID_PARAMETER;\r
1513 }\r
1514\r
1515 //\r
1516 // Advance to the next source character.\r
1517 //\r
1518 continue;\r
1519 } else {\r
1520 //\r
1521 // Other characters outside of the encoding alphabet are rejected.\r
1522 //\r
1523 return RETURN_INVALID_PARAMETER;\r
1524 }\r
1525\r
1526 //\r
1527 // Feed the bits of the current 6-bit group of the quantum to the\r
1528 // accumulator.\r
1529 //\r
1530 Accumulator = (Accumulator << 6) | Base64Value;\r
1531 SixBitGroupsConsumed++;\r
1532 switch (SixBitGroupsConsumed) {\r
1533 case 1:\r
1534 //\r
1535 // No octet to spill after consuming the first 6-bit group of the\r
1536 // quantum; advance to the next source character.\r
1537 //\r
1538 continue;\r
1539 case 2:\r
1540 //\r
1541 // 12 bits accumulated (6 pending + 6 new); prepare for spilling an\r
1542 // octet. 4 bits remain pending.\r
1543 //\r
1544 DestinationOctet = (UINT8)(Accumulator >> 4);\r
1545 Accumulator &= 0xF;\r
1546 break;\r
1547 case 3:\r
1548 //\r
1549 // 10 bits accumulated (4 pending + 6 new); prepare for spilling an\r
1550 // octet. 2 bits remain pending.\r
1551 //\r
1552 DestinationOctet = (UINT8)(Accumulator >> 2);\r
1553 Accumulator &= 0x3;\r
1554 break;\r
1555 default:\r
1556 ASSERT (SixBitGroupsConsumed == 4);\r
1557 //\r
1558 // 8 bits accumulated (2 pending + 6 new); prepare for spilling an octet.\r
1559 // The quantum is complete, 0 bits remain pending.\r
1560 //\r
1561 DestinationOctet = (UINT8)Accumulator;\r
1562 Accumulator = 0;\r
1563 SixBitGroupsConsumed = 0;\r
1564 break;\r
1565 }\r
1566\r
1567 //\r
1568 // Store the decoded octet if there's room left. Increment\r
1569 // (*DestinationSize) unconditionally.\r
1570 //\r
1571 if (*DestinationSize < OriginalDestinationSize) {\r
1572 ASSERT (Destination != NULL);\r
1573 Destination[*DestinationSize] = DestinationOctet;\r
1574 }\r
1575 (*DestinationSize)++;\r
1576\r
1577 //\r
1578 // Advance to the next source character.\r
1579 //\r
1580 }\r
1581\r
1582 //\r
1583 // If Source terminates mid-quantum, then Source is invalid.\r
1584 //\r
1585 if (SixBitGroupsConsumed != 0) {\r
1586 return RETURN_INVALID_PARAMETER;\r
1587 }\r
1588\r
1589 //\r
1590 // Done.\r
1591 //\r
1592 if (*DestinationSize <= OriginalDestinationSize) {\r
1593 return RETURN_SUCCESS;\r
1594 }\r
1595 return RETURN_BUFFER_TOO_SMALL;\r
1f7af69d
MT
1596}\r
1597\r
e1f414b6 1598/**\r
1599 Converts an 8-bit value to an 8-bit BCD value.\r
1600\r
1601 Converts the 8-bit value specified by Value to BCD. The BCD value is\r
1602 returned.\r
1603\r
1604 If Value >= 100, then ASSERT().\r
1605\r
1606 @param Value The 8-bit value to convert to BCD. Range 0..99.\r
1607\r
9aa049d9 1608 @return The BCD value.\r
e1f414b6 1609\r
1610**/\r
1611UINT8\r
1612EFIAPI\r
1613DecimalToBcd8 (\r
1614 IN UINT8 Value\r
1615 )\r
1616{\r
1617 ASSERT (Value < 100);\r
1618 return (UINT8) (((Value / 10) << 4) | (Value % 10));\r
1619}\r
1620\r
1621/**\r
1622 Converts an 8-bit BCD value to an 8-bit value.\r
1623\r
1624 Converts the 8-bit BCD value specified by Value to an 8-bit value. The 8-bit\r
1625 value is returned.\r
1626\r
1627 If Value >= 0xA0, then ASSERT().\r
1628 If (Value & 0x0F) >= 0x0A, then ASSERT().\r
1629\r
1630 @param Value The 8-bit BCD value to convert to an 8-bit value.\r
1631\r
9aa049d9 1632 @return The 8-bit value is returned.\r
e1f414b6 1633\r
1634**/\r
1635UINT8\r
1636EFIAPI\r
1637BcdToDecimal8 (\r
1638 IN UINT8 Value\r
1639 )\r
1640{\r
1641 ASSERT (Value < 0xa0);\r
1642 ASSERT ((Value & 0xf) < 0xa);\r
1643 return (UINT8) ((Value >> 4) * 10 + (Value & 0xf));\r
1644}\r