]> git.proxmox.com Git - mirror_edk2.git/blob - RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c
0696341bc035cb70da5ec61068dfcb4ec07b0b3e
[mirror_edk2.git] / RedfishPkg / PrivateLibrary / RedfishCrtLib / RedfishCrtLib.c
1 /** @file
2 CRT wrapper functions for system call,the string operation functions
3 are remodeled after edk2-libc.
4
5 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
6 (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10 **/
11 #include <Uefi.h>
12 #include <Library/RedfishCrtLib.h>
13 #include <Library/MemoryAllocationLib.h>
14 #include <Library/SortLib.h>
15 #include <Library/UefiRuntimeServicesTableLib.h>
16
17 int errno = 0;
18
19 /**
20 Determine if a particular character is an alphanumeric character
21 @return Returns 1 if c is an alphanumeric character, otherwise returns 0.
22 **/
23 int isalnum (int c)
24 {
25 //
26 // <alnum> ::= [0-9] | [a-z] | [A-Z]
27 //
28 return ((('0' <= (c)) && ((c) <= '9')) ||
29 (('a' <= (c)) && ((c) <= 'z')) ||
30 (('A' <= (c)) && ((c) <= 'Z')));
31 }
32
33 /**
34 Determine if a particular character is a digital character
35
36 @return Returns 1 if c is an digital character, otherwise returns 0.
37 **/
38 int isdchar (int c)
39 {
40 //
41 // [0-9] | [e +-.]
42 //
43 return ((('0' <= (c)) && ((c) <= '9')) ||
44 (c == 'e') || (c == 'E') ||
45 (c == '+') || (c == '-') ||
46 (c == '.'));
47 }
48
49 /**
50 Determine if a particular character is a space character
51
52 @return Returns 1 if c is a space character
53 **/
54 int isspace (int c)
55 {
56 //
57 // <space> ::= [ ]
58 //
59 return ((c) == ' ') || ((c) == '\t') || ((c) == '\r') || ((c) == '\n') || ((c) == '\v') || ((c) == '\f');
60 }
61
62 /**
63 Allocates memory blocks
64 */
65 void *malloc (size_t size)
66 {
67 return AllocatePool ((UINTN) size);
68 }
69
70 /**
71 De-allocates or frees a memory block
72 */
73 void free (void *ptr)
74 {
75 //
76 // In Standard C, free() handles a null pointer argument transparently. This
77 // is not true of FreePool() below, so protect it.
78 //
79 if (ptr != NULL) {
80 FreePool (ptr);
81 }
82 }
83
84 /**
85 NetBSD Compatibility Function strdup creates a duplicate copy of a string.
86
87 @return Returns the pointer to duplicated string.
88 **/
89 char * strdup(const char *str)
90 {
91 size_t len;
92 char *copy;
93
94 len = strlen(str) + 1;
95 if ((copy = malloc(len)) == NULL)
96 return (NULL);
97 memcpy(copy, str, len);
98 return (copy);
99 }
100
101 /** The toupper function converts a lowercase letter to a corresponding
102 uppercase letter.
103
104 @param[in] c The character to be converted.
105
106 @return If the argument is a character for which islower is true and
107 there are one or more corresponding characters, as specified by
108 the current locale, for which isupper is true, the toupper
109 function returns one of the corresponding characters (always the
110 same one for any given locale); otherwise, the argument is
111 returned unchanged.
112 **/
113 int
114 toupper(
115 IN int c
116 )
117 {
118 if ( (c >= 'a') && (c <= 'z') ) {
119 c = c - ('a' - 'A');
120 }
121 return c;
122 }
123
124 /**
125 Digit to a value.
126
127 @return Returns the value of digit.
128 **/
129 int
130 Digit2Val( int c)
131 {
132 if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) { /* If c is one of [A-Za-z]... */
133 c = toupper(c) - 7; // Adjust so 'A' is ('9' + 1)
134 }
135 return c - '0'; // Value returned is between 0 and 35, inclusive.
136 }
137
138
139 /** The strtoll function converts the initial portion of the string pointed to
140 by nptr to long long int representation.
141
142 See the description for strtol for more information.
143
144 @return The strtoll function returns the converted value, if any. If no
145 conversion could be performed, zero is returned. If the correct
146 value is outside the range of representable values, LLONG_MIN or
147 LLONG_MAX is returned (according to the sign of the value, if any),
148 and the value of the macro ERANGE is stored in errno.
149 **/
150 long long
151 strtoll(const char * nptr, char ** endptr, int base)
152 {
153 const char *pEnd;
154 long long Result = 0;
155 long long Previous;
156 int temp;
157 BOOLEAN Negative = FALSE;
158
159 pEnd = nptr;
160
161 if((base < 0) || (base == 1) || (base > 36)) {
162 if(endptr != NULL) {
163 *endptr = NULL;
164 }
165 return 0;
166 }
167 // Skip leading spaces.
168 while(isspace(*nptr)) ++nptr;
169
170 // Process Subject sequence: optional sign followed by digits.
171 if(*nptr == '+') {
172 Negative = FALSE;
173 ++nptr;
174 }
175 else if(*nptr == '-') {
176 Negative = TRUE;
177 ++nptr;
178 }
179
180 if(*nptr == '0') { /* Might be Octal or Hex */
181 if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
182 if((base == 0) || (base == 16)) {
183 nptr += 2; /* Skip the "0X" */
184 base = 16; /* In case base was 0 */
185 }
186 }
187 else { /* Looks like Octal */
188 if((base == 0) || (base == 8)) {
189 ++nptr; /* Skip the leading "0" */
190 base = 8; /* In case base was 0 */
191 }
192 }
193 }
194 if(base == 0) { /* If still zero then must be decimal */
195 base = 10;
196 }
197 if(*nptr == '0') {
198 for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
199 pEnd = nptr;
200 }
201
202 while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
203 Previous = Result;
204 Result = MultS64x64 (Result, base) + (long long int)temp;
205 if( Result <= Previous) { // Detect Overflow
206 if(Negative) {
207 Result = LLONG_MIN;
208 }
209 else {
210 Result = LLONG_MAX;
211 }
212 Negative = FALSE;
213 errno = ERANGE;
214 break;
215 }
216 pEnd = ++nptr;
217 }
218 if(Negative) {
219 Result = -Result;
220 }
221
222 // Save pointer to final sequence
223 if(endptr != NULL) {
224 *endptr = (char *)pEnd;
225 }
226 return Result;
227 }
228
229 /** The strtol, strtoll, strtoul, and strtoull functions convert the initial
230 portion of the string pointed to by nptr to long int, long long int,
231 unsigned long int, and unsigned long long int representation, respectively.
232 First, they decompose the input string into three parts: an initial,
233 possibly empty, sequence of white-space characters (as specified by the
234 isspace function), a subject sequence resembling an integer represented in
235 some radix determined by the value of base, and a final string of one or
236 more unrecognized characters, including the terminating null character of
237 the input string. Then, they attempt to convert the subject sequence to an
238 integer, and return the result.
239
240 If the value of base is zero, the expected form of the subject sequence is
241 that of an integer constant, optionally preceded
242 by a plus or minus sign, but not including an integer suffix. If the value
243 of base is between 2 and 36 (inclusive), the expected form of the subject
244 sequence is a sequence of letters and digits representing an integer with
245 the radix specified by base, optionally preceded by a plus or minus sign,
246 but not including an integer suffix. The letters from a (or A) through z
247 (or Z) are ascribed the values 10 through 35; only letters and digits whose
248 ascribed values are less than that of base are permitted. If the value of
249 base is 16, the characters 0x or 0X may optionally precede the sequence of
250 letters and digits, following the sign if present.
251
252 The subject sequence is defined as the longest initial subsequence of the
253 input string, starting with the first non-white-space character, that is of
254 the expected form. The subject sequence contains no characters if the input
255 string is empty or consists entirely of white space, or if the first
256 non-white-space character is other than a sign or a permissible letter or digit.
257
258 If the subject sequence has the expected form and the value of base is
259 zero, the sequence of characters starting with the first digit is
260 interpreted as an integer constant. If the subject sequence has the
261 expected form and the value of base is between 2 and 36, it is used as the
262 base for conversion, ascribing to each letter its value as given above. If
263 the subject sequence begins with a minus sign, the value resulting from the
264 conversion is negated (in the return type). A pointer to the final string
265 is stored in the object pointed to by endptr, provided that endptr is
266 not a null pointer.
267
268 In other than the "C" locale, additional locale-specific subject sequence
269 forms may be accepted.
270
271 If the subject sequence is empty or does not have the expected form, no
272 conversion is performed; the value of nptr is stored in the object pointed
273 to by endptr, provided that endptr is not a null pointer.
274
275 @return The strtol, strtoll, strtoul, and strtoull functions return the
276 converted value, if any. If no conversion could be performed, zero
277 is returned. If the correct value is outside the range of
278 representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX,
279 ULONG_MAX, or ULLONG_MAX is returned (according to the return type
280 and sign of the value, if any), and the value of the macro ERANGE
281 is stored in errno.
282 **/
283 long
284 strtol(const char * nptr, char ** endptr, int base)
285 {
286 const char *pEnd;
287 long Result = 0;
288 long Previous;
289 int temp;
290 BOOLEAN Negative = FALSE;
291
292 pEnd = nptr;
293
294 if((base < 0) || (base == 1) || (base > 36)) {
295 if(endptr != NULL) {
296 *endptr = NULL;
297 }
298 return 0;
299 }
300 // Skip leading spaces.
301 while(isspace(*nptr)) ++nptr;
302
303 // Process Subject sequence: optional sign followed by digits.
304 if(*nptr == '+') {
305 Negative = FALSE;
306 ++nptr;
307 }
308 else if(*nptr == '-') {
309 Negative = TRUE;
310 ++nptr;
311 }
312
313 if(*nptr == '0') { /* Might be Octal or Hex */
314 if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
315 if((base == 0) || (base == 16)) {
316 nptr += 2; /* Skip the "0X" */
317 base = 16; /* In case base was 0 */
318 }
319 }
320 else { /* Looks like Octal */
321 if((base == 0) || (base == 8)) {
322 ++nptr; /* Skip the leading "0" */
323 base = 8; /* In case base was 0 */
324 }
325 }
326 }
327 if(base == 0) { /* If still zero then must be decimal */
328 base = 10;
329 }
330 if(*nptr == '0') {
331 for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
332 pEnd = nptr;
333 }
334
335 while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
336 Previous = Result;
337 Result = (Result * base) + (long int)temp;
338 if( Result <= Previous) { // Detect Overflow
339 if(Negative) {
340 Result = LONG_MIN;
341 }
342 else {
343 Result = LONG_MAX;
344 }
345 Negative = FALSE;
346 errno = ERANGE;
347 break;
348 }
349 pEnd = ++nptr;
350 }
351 if(Negative) {
352 Result = -Result;
353 }
354
355 // Save pointer to final sequence
356 if(endptr != NULL) {
357 *endptr = (char *)pEnd;
358 }
359 return Result;
360 }
361
362 /** The strtoull function converts the initial portion of the string pointed to
363 by nptr to unsigned long long int representation.
364
365 See the description for strtol for more information.
366
367 @return The strtoull function returns the converted value, if any. If no
368 conversion could be performed, zero is returned. If the correct
369 value is outside the range of representable values, ULLONG_MAX is
370 returned and the value of the macro ERANGE is stored in errno.
371 **/
372 unsigned long long
373 strtoull(const char * nptr, char ** endptr, int base)
374 {
375 const char *pEnd;
376 unsigned long long Result = 0;
377 unsigned long long Previous;
378 int temp;
379
380 pEnd = nptr;
381
382 if((base < 0) || (base == 1) || (base > 36)) {
383 if(endptr != NULL) {
384 *endptr = NULL;
385 }
386 return 0;
387 }
388 // Skip leading spaces.
389 while(isspace(*nptr)) ++nptr;
390
391 // Process Subject sequence: optional + sign followed by digits.
392 if(*nptr == '+') {
393 ++nptr;
394 }
395
396 if(*nptr == '0') { /* Might be Octal or Hex */
397 if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
398 if((base == 0) || (base == 16)) {
399 nptr += 2; /* Skip the "0X" */
400 base = 16; /* In case base was 0 */
401 }
402 }
403 else { /* Looks like Octal */
404 if((base == 0) || (base == 8)) {
405 ++nptr; /* Skip the leading "0" */
406 base = 8; /* In case base was 0 */
407 }
408 }
409 }
410 if(base == 0) { /* If still zero then must be decimal */
411 base = 10;
412 }
413 if(*nptr == '0') {
414 for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
415 pEnd = nptr;
416 }
417
418 while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
419 Previous = Result;
420 Result = DivU64x32 (Result, base) + (unsigned long long)temp;
421 if( Result < Previous) { // If we overflowed
422 Result = ULLONG_MAX;
423 errno = ERANGE;
424 break;
425 }
426 pEnd = ++nptr;
427 }
428
429 // Save pointer to final sequence
430 if(endptr != NULL) {
431 *endptr = (char *)pEnd;
432 }
433 return Result;
434 }
435
436 /**
437 edk2 Jansson port does not support doubles, simply return 0.
438
439 These conversion functions convert the initial portion of the string
440 pointed to by nptr to double, float, and long double representation,
441 respectively.
442
443 The strtod(), strtof(), and strtold() functions return the converted
444 value, if any.
445
446 If endptr is not NULL, a pointer to the character after the last charac-
447 ter used in the conversion is stored in the location referenced by
448 endptr.
449
450 If no conversion is performed, zero is returned and the value of nptr is
451 stored in the location referenced by endptr.
452
453 If the correct value would cause overflow, plus or minus HUGE_VAL,
454 HUGE_VALF, or HUGE_VALL is returned (according to the sign and type of
455 the return value), and ERANGE is stored in errno. If the correct value
456 would cause underflow, zero is returned and ERANGE is stored in errno.
457
458 @return Return 0.
459 **/
460 double
461 strtod (const char * __restrict nptr, char ** __restrict endptr) {
462
463 DEBUG((DEBUG_INFO, "We don't supprot double type on edk2 yet!"));
464 ASSERT(FALSE);
465 return (double)0;
466 }
467
468 /**
469 Allocate and zero-initialize array.
470 **/
471 void *
472 calloc(size_t Num, size_t Size)
473 {
474 void *RetVal;
475 size_t NumSize;
476
477 NumSize = Num * Size;
478 RetVal = NULL;
479 if (NumSize != 0) {
480 RetVal = malloc(NumSize);
481 if( RetVal != NULL) {
482 (VOID)ZeroMem( RetVal, NumSize);
483 }
484 }
485 DEBUG((DEBUG_POOL, "0x%p = calloc(%d, %d)\n", RetVal, Num, Size));
486
487 return RetVal;
488 }
489
490 //
491 // The arrays give the cumulative number of days up to the first of the
492 // month number used as the index (1 -> 12) for regular and leap years.
493 // The value at index 13 is for the whole year.
494 //
495 UINTN CumulativeDays[2][14] = {
496 {
497 0,
498 0,
499 31,
500 31 + 28,
501 31 + 28 + 31,
502 31 + 28 + 31 + 30,
503 31 + 28 + 31 + 30 + 31,
504 31 + 28 + 31 + 30 + 31 + 30,
505 31 + 28 + 31 + 30 + 31 + 30 + 31,
506 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
507 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
508 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
509 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
510 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
511 },
512 {
513 0,
514 0,
515 31,
516 31 + 29,
517 31 + 29 + 31,
518 31 + 29 + 31 + 30,
519 31 + 29 + 31 + 30 + 31,
520 31 + 29 + 31 + 30 + 31 + 30,
521 31 + 29 + 31 + 30 + 31 + 30 + 31,
522 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
523 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
524 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
525 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
526 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
527 }
528 };
529
530 #define IsLeap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
531 #define SECSPERMIN (60)
532 #define SECSPERHOUR (60 * 60)
533 #define SECSPERDAY (24 * SECSPERHOUR)
534
535 /**
536 Get the system time as seconds elapsed since midnight, January 1, 1970.
537 **/
538 time_t time (time_t *timer)
539 {
540 EFI_TIME Time;
541 time_t CalTime;
542 UINTN Year;
543
544 //
545 // Get the current time and date information
546 //
547 gRT->GetTime (&Time, NULL);
548
549 //
550 // Years Handling
551 // UTime should now be set to 00:00:00 on Jan 1 of the current year.
552 //
553 for (Year = 1970, CalTime = 0; Year != Time.Year; Year++) {
554 CalTime = CalTime + (time_t)(CumulativeDays[IsLeap(Year)][13] * SECSPERDAY);
555 }
556
557 //
558 // Add in number of seconds for current Month, Day, Hour, Minute, Seconds, and TimeZone adjustment
559 //
560 CalTime = CalTime +
561 (time_t)((Time.TimeZone != EFI_UNSPECIFIED_TIMEZONE) ? (Time.TimeZone * 60) : 0) +
562 (time_t)(CumulativeDays[IsLeap(Time.Year)][Time.Month] * SECSPERDAY) +
563 (time_t)(((Time.Day > 0) ? Time.Day - 1 : 0) * SECSPERDAY) +
564 (time_t)(Time.Hour * SECSPERHOUR) +
565 (time_t)(Time.Minute * 60) +
566 (time_t)Time.Second;
567
568 if (timer != NULL) {
569 *timer = CalTime;
570 }
571
572 return CalTime;
573 }
574
575 /**
576 Performs a quick sort
577 **/
578 void qsort (void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
579 {
580
581 ASSERT (base != NULL);
582 ASSERT (compare != NULL);
583
584 PerformQuickSort (base, (UINTN)num, (UINTN)width, (SORT_COMPARE)compare);
585 return;
586 }
587
588 /**
589 Get character from stream, we don't support file operastion on edk2 JSON library.
590
591 @return Returns the character currently pointed by the internal file position indicator of the specified stream
592
593 **/
594 int fgetc(FILE * _File){
595 return 0;
596 }
597 /**
598 This function check if this is the formating string specifier.
599
600 @param[in] FormatString A Null-terminated ASCII format string.
601 @param[in,out] CurrentPosition The starting position at the given string to check for
602 "[flags][width][.precision][length]s" string specifier.
603 @param[in] StrLength Maximum string length.
604
605 @return BOOLEAN TRUE means this is the formating string specifier. CurrentPosition is
606 returned at the position of "s".
607 FALSE means this is not the formating string specifier.. CurrentPosition is
608 returned at the position of failed character.
609
610 **/
611 BOOLEAN
612 CheckFormatingString (
613 IN CONST CHAR8 *FormatString,
614 IN OUT UINTN *CurrentPosition,
615 IN UINTN StrLength
616 )
617 {
618 CHAR8 FormatStringParamater;
619
620 while (*(FormatString + *CurrentPosition) != 's') {
621 //
622 // Loop until reach character 's' if the formating string is
623 // compliant with "[flags][width][.precision][length]" format for
624 // the string specifier.
625 //
626 FormatStringParamater = *(FormatString + *CurrentPosition);
627 if ((FormatStringParamater != '-') &&
628 (FormatStringParamater != '+') &&
629 (FormatStringParamater != '*') &&
630 (FormatStringParamater != '.') &&
631 !(((UINTN)FormatStringParamater >= (UINTN)'0') && ((UINTN)FormatStringParamater <= (UINTN)'9'))
632 ) {
633 return FALSE;
634 }
635 (*CurrentPosition)++;
636 if (*CurrentPosition >= StrLength) {
637 return FALSE;
638 }
639 };
640 return TRUE;
641 }
642
643 /**
644 This function clones *FormatString however replaces "%s" with "%a" in the
645 returned string.
646
647 @param[in] A Null-terminated ASCII format string.
648
649 @return The new format string. Caller has to free the memory of this string
650 using FreePool().
651
652 **/
653 CHAR8 *
654 ReplaceUnicodeToAsciiStrFormat (
655 IN CONST CHAR8 *FormatString
656 )
657 {
658 UINTN FormatStrSize;
659 UINTN FormatStrIndex;
660 UINTN FormatStrSpecifier;
661 BOOLEAN PercentageMark;
662 CHAR8 *TempFormatBuffer;
663 BOOLEAN IsFormatString;
664
665 //
666 // Error checking.
667 //
668 if (FormatString == NULL) {
669 return NULL;
670 }
671 FormatStrSize = AsciiStrSize(FormatString);
672 if (FormatStrSize == 0) {
673 return NULL;
674 }
675 TempFormatBuffer = AllocatePool(FormatStrSize); // Allocate memory for the
676 // new string.
677 if (TempFormatBuffer== NULL) {
678 return NULL;
679 }
680 //
681 // Clone *FormatString but replace "%s" wih "%a".
682 // "%%" is not considered as the format tag.
683 //
684 PercentageMark = FALSE;
685 FormatStrIndex = 0;
686 while (FormatStrIndex < FormatStrSize) {
687 if (PercentageMark == TRUE) {
688 //
689 // Previous character is "%".
690 //
691 PercentageMark = FALSE;
692 if (*(FormatString + FormatStrIndex) != '%') { // Check if this is double "%".
693 FormatStrSpecifier = FormatStrIndex;
694 //
695 // Check if this is the formating string specifier.
696 //
697 IsFormatString = CheckFormatingString (FormatString, &FormatStrSpecifier, FormatStrSize);
698 if ((FormatStrSpecifier - FormatStrIndex) != 0) {
699 CopyMem((VOID *)(TempFormatBuffer + FormatStrIndex),
700 (VOID *)(FormatString + FormatStrIndex),
701 FormatStrSpecifier - FormatStrIndex
702 );
703 }
704 FormatStrIndex = FormatStrSpecifier;
705 if (IsFormatString == TRUE) {
706 //
707 // Replace 's' with 'a' which is printed in ASCII
708 // format on edk2 environment.
709 //
710 *(TempFormatBuffer + FormatStrSpecifier) = 'a';
711 FormatStrIndex ++;
712 }
713 continue;
714 }
715 goto ContinueCheck;
716 }
717 if (*(FormatString + FormatStrIndex) == '%') {
718 //
719 // This character is "%", set the flag.
720 //
721 PercentageMark = TRUE;
722 }
723 ContinueCheck:
724 //
725 // Clone character to the new string and advance FormatStrIndex
726 // to process next character.
727 //
728 *(TempFormatBuffer + FormatStrIndex) = *(FormatString + FormatStrIndex);
729 FormatStrIndex++;
730 };
731 return TempFormatBuffer;
732 }
733
734 /**
735 This is the Redfish version of CRT vsnprintf function, this function replaces "%s" to
736 "%a" before invoking AsciiVSPrint(). That is because "%s" is unicode base on edk2
737 environment however "%s" is ascii code base on vsnprintf().
738 See definitions of AsciiVSPrint() for the details.
739
740 @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
741 ASCII string.
742 @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
743 @param FormatString A Null-terminated ASCII format string.
744 @param Marker VA_LIST marker for the variable argument list.
745
746 @return The number of ASCII characters in the produced output buffer not including the
747 Null-terminator.
748
749 **/
750 UINTN
751 EFIAPI
752 RedfishAsciiVSPrint (
753 OUT CHAR8 *StartOfBuffer,
754 IN UINTN BufferSize,
755 IN CONST CHAR8 *FormatString,
756 IN VA_LIST Marker
757 )
758 {
759 CHAR8 *TempFormatBuffer;
760 UINTN LenStrProduced;
761
762 //
763 // Looking for "%s" in the format string and replace it
764 // with "%a" for printing ASCII code characters on edk2
765 // environment.
766 //
767 TempFormatBuffer = ReplaceUnicodeToAsciiStrFormat (FormatString);
768 if (TempFormatBuffer == NULL) {
769 return 0;
770 }
771 LenStrProduced = AsciiVSPrint (StartOfBuffer, BufferSize, (CONST CHAR8 *)TempFormatBuffer, Marker);
772 FreePool (TempFormatBuffer);
773 return LenStrProduced;
774 }
775
776 /**
777 This is the Redfish version of CRT snprintf function, this function replaces "%s" to
778 "%a" before invoking AsciiSPrint(). That is because "%s" is unicode base on edk2
779 environment however "%s" is ascii code base on snprintf().
780 See definitions of AsciiSPrint() for the details.
781
782 @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
783 ASCII string.
784 @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
785 @param FormatString A Null-terminated ASCII format string.
786 @param ... Variable argument list whose contents are accessed based on the
787 format string specified by FormatString.
788
789 @return The number of ASCII characters in the produced output buffer not including the
790 Null-terminator.
791
792 **/
793 UINTN
794 EFIAPI
795 RedfishAsciiSPrint (
796 OUT CHAR8 *StartOfBuffer,
797 IN UINTN BufferSize,
798 IN CONST CHAR8 *FormatString,
799 ...
800 )
801 {
802 VA_LIST Marker;
803 UINTN LenStrProduced;
804
805 VA_START(Marker, FormatString);
806 LenStrProduced = RedfishAsciiVSPrint (StartOfBuffer, BufferSize, FormatString, Marker);
807 return LenStrProduced;
808 }
809