]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BasePrintLib/PrintLibInternal.c
1c42baecfcf1ea159771b3ce100dd6cb9cc05083
[mirror_edk2.git] / MdePkg / Library / BasePrintLib / PrintLibInternal.c
1 /** @file
2 Print Library internal worker functions.
3
4 Copyright (c) 2006 - 2008, Intel Corporation<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "PrintLibInternal.h"
16
17 #define WARNING_STATUS_NUMBER 4
18 #define ERROR_STATUS_NUMBER 24
19
20 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
21
22 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mStatusString[] = {
23 "Success", // RETURN_SUCCESS = 0
24 "Warning Unknown Glyph", // RETURN_WARN_UNKNOWN_GLYPH = 1
25 "Warning Delete Failure", // RETURN_WARN_DELETE_FAILURE = 2
26 "Warning Write Failure", // RETURN_WARN_WRITE_FAILURE = 3
27 "Warning Buffer Too Small", // RETURN_WARN_BUFFER_TOO_SMALL = 4
28 "Load Error", // RETURN_LOAD_ERROR = 1 | MAX_BIT
29 "Invalid Parameter", // RETURN_INVALID_PARAMETER = 2 | MAX_BIT
30 "Unsupported", // RETURN_UNSUPPORTED = 3 | MAX_BIT
31 "Bad Buffer Size", // RETURN_BAD_BUFFER_SIZE = 4 | MAX_BIT
32 "Buffer Too Small", // RETURN_BUFFER_TOO_SMALL, = 5 | MAX_BIT
33 "Not Ready", // RETURN_NOT_READY = 6 | MAX_BIT
34 "Device Error", // RETURN_DEVICE_ERROR = 7 | MAX_BIT
35 "Write Protected", // RETURN_WRITE_PROTECTED = 8 | MAX_BIT
36 "Out of Resources", // RETURN_OUT_OF_RESOURCES = 9 | MAX_BIT
37 "Volume Corrupt", // RETURN_VOLUME_CORRUPTED = 10 | MAX_BIT
38 "Volume Full", // RETURN_VOLUME_FULL = 11 | MAX_BIT
39 "No Media", // RETURN_NO_MEDIA = 12 | MAX_BIT
40 "Media changed", // RETURN_MEDIA_CHANGED = 13 | MAX_BIT
41 "Not Found", // RETURN_NOT_FOUND = 14 | MAX_BIT
42 "Access Denied", // RETURN_ACCESS_DENIED = 15 | MAX_BIT
43 "No Response", // RETURN_NO_RESPONSE = 16 | MAX_BIT
44 "No mapping", // RETURN_NO_MAPPING = 17 | MAX_BIT
45 "Time out", // RETURN_TIMEOUT = 18 | MAX_BIT
46 "Not started", // RETURN_NOT_STARTED = 19 | MAX_BIT
47 "Already started", // RETURN_ALREADY_STARTED = 20 | MAX_BIT
48 "Aborted", // RETURN_ABORTED = 21 | MAX_BIT
49 "ICMP Error", // RETURN_ICMP_ERROR = 22 | MAX_BIT
50 "TFTP Error", // RETURN_TFTP_ERROR = 23 | MAX_BIT
51 "Protocol Error" // RETURN_PROTOCOL_ERROR = 24 | MAX_BIT
52 };
53
54
55 /**
56 Internal function that places the character into the Buffer.
57
58 Internal function that places ASCII or Unicode character into the Buffer.
59
60 @param Buffer Buffer to place the Unicode or ASCII string.
61 @param EndBuffer The end of the input Buffer. No characters will be
62 placed after that.
63 @param Length Count of character to be placed into Buffer.
64 (Negative value indicates no buffer fill.)
65 @param Character Character to be placed into Buffer.
66 @param Increment Character increment in Buffer.
67
68 @return Buffer Buffer filled with the input Character.
69
70 **/
71 CHAR8 *
72 BasePrintLibFillBuffer (
73 OUT CHAR8 *Buffer,
74 IN CHAR8 *EndBuffer,
75 IN INTN Length,
76 IN UINTN Character,
77 IN INTN Increment
78 )
79 {
80 INTN Index;
81
82 for (Index = 0; Index < Length && Buffer < EndBuffer; Index++) {
83 *Buffer = (CHAR8) Character;
84 if (Increment != 1) {
85 *(Buffer + 1) = (CHAR8)(Character >> 8);
86 }
87 Buffer += Increment;
88 }
89
90 return Buffer;
91 }
92
93 /**
94 Internal function that convert a decimal number to a string in Buffer.
95
96 Print worker function that convert a decimal number to a string in Buffer.
97
98 @param Buffer Location to place the Unicode or ASCII string of Value.
99 @param Value Value to convert to a Decimal or Hexadecimal string in Buffer.
100 @param Radix Radix of the value
101
102 @return Number of characters printed.
103
104 **/
105 UINTN
106 BasePrintLibValueToString (
107 IN OUT CHAR8 *Buffer,
108 IN INT64 Value,
109 IN UINTN Radix
110 )
111 {
112 UINTN Digits;
113 UINT32 Remainder;
114
115 //
116 // Loop to convert one digit at a time in reverse order
117 //
118 *(Buffer++) = 0;
119 Digits = 0;
120 do {
121 Value = (INT64)DivU64x32Remainder ((UINT64)Value, (UINT32)Radix, &Remainder);
122 *(Buffer++) = mHexStr[Remainder];
123 Digits++;
124 } while (Value != 0);
125
126 //
127 // the length of Buffer string converted from Value
128 //
129 return Digits;
130 }
131
132 /**
133 Internal function that converts a decimal value to a Null-terminated string.
134
135 Converts the decimal number specified by Value to a Null-terminated
136 string specified by Buffer containing at most Width characters.
137 If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
138 The total number of characters placed in Buffer is returned.
139 If the conversion contains more than Width characters, then only the first
140 Width characters are returned, and the total number of characters
141 required to perform the conversion is returned.
142 Additional conversion parameters are specified in Flags.
143 The Flags bit LEFT_JUSTIFY is always ignored.
144 All conversions are left justified in Buffer.
145 If Width is 0, PREFIX_ZERO is ignored in Flags.
146 If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas
147 are inserted every 3rd digit starting from the right.
148 If Value is < 0, then the fist character in Buffer is a '-'.
149 If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,
150 then Buffer is padded with '0' characters so the combination of the optional '-'
151 sign character, '0' characters, digit characters for Value, and the Null-terminator
152 add up to Width characters.
153
154 If Buffer is NULL, then ASSERT().
155 If unsupported bits are set in Flags, then ASSERT().
156 If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()
157
158 @param Buffer Pointer to the output buffer for the produced Null-terminated
159 string.
160 @param Flags The bitmask of flags that specify left justification, zero pad,
161 and commas.
162 @param Value The 64-bit signed value to convert to a string.
163 @param Width The maximum number of characters to place in Buffer, not including
164 the Null-terminator.
165 @param Increment Character increment in Buffer.
166
167 @return Total number of characters required to perform the conversion.
168
169 **/
170 UINTN
171 BasePrintLibConvertValueToString (
172 IN OUT CHAR8 *Buffer,
173 IN UINTN Flags,
174 IN INT64 Value,
175 IN UINTN Width,
176 IN UINTN Increment
177 )
178 {
179 CHAR8 *OriginalBuffer;
180 CHAR8 *EndBuffer;
181 CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];
182 UINTN Count;
183 UINTN Digits;
184 UINTN Index;
185 UINTN Radix;
186
187 //
188 // Make sure Buffer is not NULL and Width < MAXIMUM
189 //
190 ASSERT (Buffer != NULL);
191 ASSERT (Width < MAXIMUM_VALUE_CHARACTERS);
192 //
193 // Make sure Flags can only contain supported bits.
194 //
195 ASSERT ((Flags & ~(LEFT_JUSTIFY | COMMA_TYPE | PREFIX_ZERO | RADIX_HEX)) == 0);
196
197 //
198 // If both COMMA_TYPE and HEX_RADIX are set, then ASSERT ()
199 //
200 ASSERT (((Flags & COMMA_TYPE) != 0 && (Flags & RADIX_HEX) != 0) == FALSE);
201
202 OriginalBuffer = Buffer;
203
204 //
205 // Width is 0 or COMMA_TYPE is set, PREFIX_ZERO is ignored.
206 //
207 if (Width == 0 || (Flags & COMMA_TYPE) != 0) {
208 Flags &= (~PREFIX_ZERO);
209 }
210 //
211 // If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
212 //
213 if (Width == 0) {
214 Width = MAXIMUM_VALUE_CHARACTERS - 1;
215 }
216 //
217 // Set the tag for the end of the input Buffer.
218 //
219 EndBuffer = Buffer + Width * Increment;
220
221 //
222 // Convert decimal negative
223 //
224 if ((Value < 0) && ((Flags & RADIX_HEX) == 0)) {
225 Value = -Value;
226 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, '-', Increment);
227 Width--;
228 }
229
230 //
231 // Count the length of the value string.
232 //
233 Radix = ((Flags & RADIX_HEX) == 0)? 10 : 16;
234 Count = BasePrintLibValueToString (ValueBuffer, Value, Radix);
235
236 //
237 // Append Zero
238 //
239 if ((Flags & PREFIX_ZERO) != 0) {
240 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Count, '0', Increment);
241 }
242
243 //
244 // Print Comma type for every 3 characters
245 //
246 Digits = Count % 3;
247 if (Digits != 0) {
248 Digits = 3 - Digits;
249 }
250 for (Index = 0; Index < Count; Index++) {
251 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ValueBuffer[Count - Index], Increment);
252 if ((Flags & COMMA_TYPE) != 0) {
253 Digits++;
254 if (Digits == 3) {
255 Digits = 0;
256 if ((Index + 1) < Count) {
257 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', Increment);
258 }
259 }
260 }
261 }
262
263 //
264 // Print Null-terminator
265 //
266 BasePrintLibFillBuffer (Buffer, EndBuffer + Increment, 1, 0, Increment);
267
268 return ((Buffer - OriginalBuffer) / Increment);
269 }
270
271 /**
272 Worker function that produces a Null-terminated string in an output buffer
273 based on a Null-terminated format string and a VA_LIST argument list.
274
275 VSPrint function to process format and place the results in Buffer. Since a
276 VA_LIST is used this rountine allows the nesting of Vararg routines. Thus
277 this is the main print working routine.
278
279 @param Buffer Character buffer to print the results of the parsing
280 of Format into.
281 @param BufferSize Maximum number of characters to put into buffer.
282 @param Flags Intial flags value.
283 Can only have FORMAT_UNICODE and OUTPUT_UNICODE set.
284 @param Format Null-terminated format string.
285 @param Marker Vararg list consumed by processing Format.
286
287 @return Number of characters printed not including the Null-terminator.
288
289 **/
290 UINTN
291 BasePrintLibVSPrint (
292 OUT CHAR8 *Buffer,
293 IN UINTN BufferSize,
294 IN UINTN Flags,
295 IN CONST CHAR8 *Format,
296 IN VA_LIST Marker
297 )
298 {
299 CHAR8 *OriginalBuffer;
300 CHAR8 *EndBuffer;
301 CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];
302 UINTN BytesPerOutputCharacter;
303 UINTN BytesPerFormatCharacter;
304 UINTN FormatMask;
305 UINTN FormatCharacter;
306 UINTN Width;
307 UINTN Precision;
308 INT64 Value;
309 CONST CHAR8 *ArgumentString;
310 UINTN Character;
311 GUID *TmpGuid;
312 TIME *TmpTime;
313 UINTN Count;
314 UINTN ArgumentMask;
315 INTN BytesPerArgumentCharacter;
316 UINTN ArgumentCharacter;
317 BOOLEAN Done;
318 UINTN Index;
319 CHAR8 Prefix;
320 BOOLEAN ZeroPad;
321 BOOLEAN Comma;
322 UINTN Digits;
323 UINTN Radix;
324 RETURN_STATUS Status;
325
326 if (BufferSize == 0) {
327 return 0;
328 }
329 ASSERT (Buffer != NULL);
330
331 if ((Flags & OUTPUT_UNICODE) != 0) {
332 BytesPerOutputCharacter = 2;
333 } else {
334 BytesPerOutputCharacter = 1;
335 }
336
337 //
338 // Reserve space for the Null terminator.
339 //
340 BufferSize--;
341 OriginalBuffer = Buffer;
342 //
343 // Set the tag for the end of the input Buffer.
344 //
345 EndBuffer = Buffer + BufferSize * BytesPerOutputCharacter;
346
347 if ((Flags & FORMAT_UNICODE) != 0) {
348 //
349 // Make sure format string cannot contain more than PcdMaximumUnicodeStringLength
350 // Unicode characters if PcdMaximumUnicodeStringLength is not zero.
351 //
352 ASSERT (StrSize ((CHAR16 *) Format) != 0);
353 BytesPerFormatCharacter = 2;
354 FormatMask = 0xffff;
355 } else {
356 //
357 // Make sure format string cannot contain more than PcdMaximumAsciiStringLength
358 // Ascii characters if PcdMaximumAsciiStringLength is not zero.
359 //
360 ASSERT (AsciiStrSize (Format) != 0);
361 BytesPerFormatCharacter = 1;
362 FormatMask = 0xff;
363 }
364
365
366
367 //
368 // Get the first character from the format string
369 //
370 FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
371
372 //
373 // Loop until the end of the format string is reached or the output buffer is full
374 //
375 while (FormatCharacter != 0 && Buffer < EndBuffer) {
376 //
377 // Clear all the flag bits except those that may have been passed in
378 //
379 Flags &= (OUTPUT_UNICODE | FORMAT_UNICODE);
380
381 //
382 // Set the default width to zero, and the default precision to 1
383 //
384 Width = 0;
385 Precision = 1;
386 Prefix = 0;
387 Comma = FALSE;
388 ZeroPad = FALSE;
389 Count = 0;
390 Digits = 0;
391
392 switch (FormatCharacter) {
393 case '%':
394 //
395 // Parse Flags and Width
396 //
397 for (Done = FALSE; !Done; ) {
398 Format += BytesPerFormatCharacter;
399 FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
400 switch (FormatCharacter) {
401 case '.':
402 Flags |= PRECISION;
403 break;
404 case '-':
405 Flags |= LEFT_JUSTIFY;
406 break;
407 case '+':
408 Flags |= PREFIX_SIGN;
409 break;
410 case ' ':
411 Flags |= PREFIX_BLANK;
412 break;
413 case ',':
414 Flags |= COMMA_TYPE;
415 break;
416 case 'L':
417 case 'l':
418 Flags |= LONG_TYPE;
419 break;
420 case '*':
421 if ((Flags & PRECISION) == 0) {
422 Flags |= PAD_TO_WIDTH;
423 Width = VA_ARG (Marker, UINTN);
424 } else {
425 Precision = VA_ARG (Marker, UINTN);
426 }
427 break;
428 case '0':
429 if ((Flags & PRECISION) == 0) {
430 Flags |= PREFIX_ZERO;
431 }
432 case '1':
433 case '2':
434 case '3':
435 case '4':
436 case '5':
437 case '6':
438 case '7':
439 case '8':
440 case '9':
441 for (Count = 0; ((FormatCharacter >= '0') && (FormatCharacter <= '9')); ){
442 Count = (Count * 10) + FormatCharacter - '0';
443 Format += BytesPerFormatCharacter;
444 FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
445 }
446 Format -= BytesPerFormatCharacter;
447 if ((Flags & PRECISION) == 0) {
448 Flags |= PAD_TO_WIDTH;
449 Width = Count;
450 } else {
451 Precision = Count;
452 }
453 break;
454
455 case '\0':
456 //
457 // Make no output if Format string terminates unexpectedly when
458 // looking up for flag, width, precision and type.
459 //
460 Format -= BytesPerFormatCharacter;
461 Precision = 0;
462 //
463 // break skipped on purpose.
464 //
465 default:
466 Done = TRUE;
467 break;
468 }
469 }
470
471 //
472 // Handle each argument type
473 //
474 switch (FormatCharacter) {
475 case 'p':
476 //
477 // Flag space, +, 0, L & l are invalid for type p.
478 //
479 Flags &= ~(PREFIX_BLANK | PREFIX_SIGN | PREFIX_ZERO | LONG_TYPE);
480 if (sizeof (VOID *) > 4) {
481 Flags |= LONG_TYPE;
482 }
483 case 'X':
484 Flags |= PREFIX_ZERO;
485 //
486 // break skipped on purpose
487 //
488 case 'x':
489 Flags |= RADIX_HEX;
490 //
491 // break skipped on purpose
492 //
493 case 'd':
494 if ((Flags & LONG_TYPE) == 0) {
495 Value = (VA_ARG (Marker, int));
496 } else {
497 Value = VA_ARG (Marker, INT64);
498 }
499 if ((Flags & PREFIX_BLANK) != 0) {
500 Prefix = ' ';
501 }
502 if ((Flags & PREFIX_SIGN) != 0) {
503 Prefix = '+';
504 }
505 if ((Flags & COMMA_TYPE) != 0) {
506 Comma = TRUE;
507 }
508 if ((Flags & RADIX_HEX) == 0) {
509 Radix = 10;
510 if (Comma) {
511 Flags &= (~PREFIX_ZERO);
512 Precision = 1;
513 }
514 if (Value < 0) {
515 Flags |= PREFIX_SIGN;
516 Prefix = '-';
517 Value = -Value;
518 }
519 } else {
520 Radix = 16;
521 Comma = FALSE;
522 if ((Flags & LONG_TYPE) == 0 && Value < 0) {
523 Value = (unsigned int)Value;
524 }
525 }
526 //
527 // Convert Value to a reversed string
528 //
529 Count = BasePrintLibValueToString (ValueBuffer, Value, Radix);
530 if (Value == 0 && Precision == 0) {
531 Count = 0;
532 }
533 ArgumentString = (CHAR8 *)ValueBuffer + Count;
534
535 Digits = Count % 3;
536 if (Digits != 0) {
537 Digits = 3 - Digits;
538 }
539 if (Comma && Count != 0) {
540 Count += ((Count - 1) / 3);
541 }
542 if (Prefix != 0) {
543 Count++;
544 Precision++;
545 }
546 Flags |= ARGUMENT_REVERSED;
547 ZeroPad = TRUE;
548 if ((Flags & PREFIX_ZERO) != 0) {
549 if ((Flags & LEFT_JUSTIFY) == 0) {
550 if ((Flags & PAD_TO_WIDTH) != 0) {
551 if ((Flags & PRECISION) == 0) {
552 Precision = Width;
553 }
554 }
555 }
556 }
557 break;
558
559 case 's':
560 case 'S':
561 Flags |= ARGUMENT_UNICODE;
562 //
563 // break skipped on purpose
564 //
565 case 'a':
566 ArgumentString = (CHAR8 *)VA_ARG (Marker, CHAR8 *);
567 if (ArgumentString == NULL) {
568 Flags &= (~ARGUMENT_UNICODE);
569 ArgumentString = "<null string>";
570 }
571 //
572 // Set the default precision for string to be zero if not specified.
573 //
574 if ((Flags & PRECISION) == 0) {
575 Precision = 0;
576 }
577 break;
578
579 case 'c':
580 Character = VA_ARG (Marker, UINTN) & 0xffff;
581 ArgumentString = (CHAR8 *)&Character;
582 Flags |= ARGUMENT_UNICODE;
583 break;
584
585 case 'g':
586 TmpGuid = VA_ARG (Marker, GUID *);
587 if (TmpGuid == NULL) {
588 ArgumentString = "<null guid>";
589 } else {
590 BasePrintLibSPrint (
591 ValueBuffer,
592 MAXIMUM_VALUE_CHARACTERS,
593 0,
594 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
595 TmpGuid->Data1,
596 TmpGuid->Data2,
597 TmpGuid->Data3,
598 TmpGuid->Data4[0],
599 TmpGuid->Data4[1],
600 TmpGuid->Data4[2],
601 TmpGuid->Data4[3],
602 TmpGuid->Data4[4],
603 TmpGuid->Data4[5],
604 TmpGuid->Data4[6],
605 TmpGuid->Data4[7]
606 );
607 ArgumentString = ValueBuffer;
608 }
609 break;
610
611 case 't':
612 TmpTime = VA_ARG (Marker, TIME *);
613 if (TmpTime == NULL) {
614 ArgumentString = "<null time>";
615 } else {
616 BasePrintLibSPrint (
617 ValueBuffer,
618 MAXIMUM_VALUE_CHARACTERS,
619 0,
620 "%02d/%02d/%04d %02d:%02d",
621 TmpTime->Month,
622 TmpTime->Day,
623 TmpTime->Year,
624 TmpTime->Hour,
625 TmpTime->Minute
626 );
627 ArgumentString = ValueBuffer;
628 }
629 break;
630
631 case 'r':
632 Status = VA_ARG (Marker, RETURN_STATUS);
633 ArgumentString = ValueBuffer;
634 if (RETURN_ERROR (Status)) {
635 //
636 // Clear error bit
637 //
638 Index = Status & ~MAX_BIT;
639 if (Index > 0 && Index <= ERROR_STATUS_NUMBER) {
640 ArgumentString = mStatusString [Index + WARNING_STATUS_NUMBER];
641 }
642 } else {
643 Index = Status;
644 if (Index <= WARNING_STATUS_NUMBER) {
645 ArgumentString = mStatusString [Index];
646 }
647 }
648 if (ArgumentString == ValueBuffer) {
649 BasePrintLibSPrint ((CHAR8 *) ValueBuffer, MAXIMUM_VALUE_CHARACTERS, 0, "%08X", Status);
650 }
651 break;
652
653 case '\n':
654 ArgumentString = "\n\r";
655 break;
656
657 case '%':
658 default:
659 //
660 // if the type is '%' or unknown, then print it to the screen
661 //
662 ArgumentString = (CHAR8 *)&FormatCharacter;
663 Flags |= ARGUMENT_UNICODE;
664 break;
665 }
666 break;
667
668 case '\n':
669 ArgumentString = "\n\r";
670 break;
671
672 default:
673 ArgumentString = (CHAR8 *)&FormatCharacter;
674 Flags |= ARGUMENT_UNICODE;
675 break;
676 }
677
678 //
679 // Retrieve the ArgumentString attriubutes
680 //
681 if ((Flags & ARGUMENT_UNICODE) != 0) {
682 ArgumentMask = 0xffff;
683 BytesPerArgumentCharacter = 2;
684 } else {
685 ArgumentMask = 0xff;
686 BytesPerArgumentCharacter = 1;
687 }
688 if ((Flags & ARGUMENT_REVERSED) != 0) {
689 BytesPerArgumentCharacter = -BytesPerArgumentCharacter;
690 } else {
691 //
692 // Compute the number of characters in ArgumentString and store it in Count
693 // ArgumentString is either null-terminated, or it contains Precision characters
694 //
695 for (Count = 0; Count < Precision || ((Flags & PRECISION) == 0); Count++) {
696 ArgumentCharacter = ((ArgumentString[Count * BytesPerArgumentCharacter] & 0xff) | ((ArgumentString[Count * BytesPerArgumentCharacter + 1]) << 8)) & ArgumentMask;
697 if (ArgumentCharacter == 0) {
698 break;
699 }
700 }
701 }
702
703 if (Precision < Count) {
704 Precision = Count;
705 }
706
707 //
708 // Pad before the string
709 //
710 if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH)) {
711 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);
712 }
713
714 if (ZeroPad) {
715 if (Prefix != 0) {
716 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);
717 }
718 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, '0', BytesPerOutputCharacter);
719 } else {
720 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, ' ', BytesPerOutputCharacter);
721 if (Prefix != 0) {
722 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);
723 }
724 }
725
726 //
727 // Output the Prefix character if it is present
728 //
729 Index = 0;
730 if (Prefix != 0) {
731 Index++;
732 }
733
734 //
735 // Copy the string into the output buffer performing the required type conversions
736 //
737 while (Index < Count) {
738 ArgumentCharacter = ((*ArgumentString & 0xff) | (*(ArgumentString + 1) << 8)) & ArgumentMask;
739
740 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ArgumentCharacter, BytesPerOutputCharacter);
741 ArgumentString += BytesPerArgumentCharacter;
742 Index++;
743 if (Comma) {
744 Digits++;
745 if (Digits == 3) {
746 Digits = 0;
747 Index++;
748 if (Index < Count) {
749 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', BytesPerOutputCharacter);
750 }
751 }
752 }
753 }
754
755 //
756 // Pad after the string
757 //
758 if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH | LEFT_JUSTIFY)) {
759 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);
760 }
761
762 //
763 // Get the next character from the format string
764 //
765 Format += BytesPerFormatCharacter;
766
767 //
768 // Get the next character from the format string
769 //
770 FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
771 }
772
773 //
774 // Null terminate the Unicode or ASCII string
775 //
776 BasePrintLibFillBuffer (Buffer, EndBuffer + BytesPerOutputCharacter, 1, 0, BytesPerOutputCharacter);
777 //
778 // Make sure output buffer cannot contain more than PcdMaximumUnicodeStringLength
779 // Unicode characters if PcdMaximumUnicodeStringLength is not zero.
780 //
781 ASSERT ((((Flags & OUTPUT_UNICODE) == 0)) || (StrSize ((CHAR16 *) OriginalBuffer) != 0));
782 //
783 // Make sure output buffer cannot contain more than PcdMaximumAsciiStringLength
784 // ASCII characters if PcdMaximumAsciiStringLength is not zero.
785 //
786 ASSERT ((((Flags & OUTPUT_UNICODE) != 0)) || (AsciiStrSize (OriginalBuffer) != 0));
787
788 return ((Buffer - OriginalBuffer) / BytesPerOutputCharacter);
789 }
790
791 /**
792 Worker function that produces a Null-terminated string in an output buffer
793 based on a Null-terminated format string and variable argument list.
794
795 VSPrint function to process format and place the results in Buffer. Since a
796 VA_LIST is used this rountine allows the nesting of Vararg routines. Thus
797 this is the main print working routine
798
799 @param StartOfBuffer Character buffer to print the results of the parsing
800 of Format into.
801 @param BufferSize Maximum number of characters to put into buffer.
802 Zero means no limit.
803 @param Flags Intial flags value.
804 Can only have FORMAT_UNICODE and OUTPUT_UNICODE set
805 @param FormatString Null-terminated format string.
806 @param ... The variable argument list.
807
808 @return Number of characters printed.
809
810 **/
811 UINTN
812 BasePrintLibSPrint (
813 OUT CHAR8 *StartOfBuffer,
814 IN UINTN BufferSize,
815 IN UINTN Flags,
816 IN CONST CHAR8 *FormatString,
817 ...
818 )
819 {
820 VA_LIST Marker;
821
822 VA_START (Marker, FormatString);
823 return BasePrintLibVSPrint (StartOfBuffer, BufferSize, Flags, FormatString, Marker);
824 }