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