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