2 CRT wrapper functions for system call,the string operation functions
3 are remodeled after edk2-libc.
5 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
6 (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <Library/RedfishCrtLib.h>
13 #include <Library/MemoryAllocationLib.h>
14 #include <Library/SortLib.h>
15 #include <Library/UefiRuntimeServicesTableLib.h>
18 char errnum_message
[] = "We don't support to map errnum to the error message on edk2 Redfish\n";
20 // This is required to keep VC++ happy if you use floating-point
24 Determine if a particular character is an alphanumeric character
25 @return Returns 1 if c is an alphanumeric character, otherwise returns 0.
30 // <alnum> ::= [0-9] | [a-z] | [A-Z]
32 return ((('0' <= (c
)) && ((c
) <= '9')) ||
33 (('a' <= (c
)) && ((c
) <= 'z')) ||
34 (('A' <= (c
)) && ((c
) <= 'Z')));
38 Determine if a particular character is a digital character
40 @return Returns 1 if c is an digital character, otherwise returns 0.
47 return ((('0' <= (c
)) && ((c
) <= '9')) ||
48 (c
== 'e') || (c
== 'E') ||
49 (c
== '+') || (c
== '-') ||
54 Determine if a particular character is a space character
56 @return Returns 1 if c is a space character
63 return ((c
) == ' ') || ((c
) == '\t') || ((c
) == '\r') || ((c
) == '\n') || ((c
) == '\v') || ((c
) == '\f');
67 Allocates memory blocks
69 void *malloc (size_t size
)
71 return AllocatePool ((UINTN
) size
);
75 De-allocates or frees a memory block
80 // In Standard C, free() handles a null pointer argument transparently. This
81 // is not true of FreePool() below, so protect it.
89 NetBSD Compatibility Function strdup creates a duplicate copy of a string.
91 @return Returns the pointer to duplicated string.
93 char * strdup(const char *str
)
98 len
= strlen(str
) + 1;
99 if ((copy
= malloc(len
)) == NULL
)
101 memcpy(copy
, str
, len
);
105 /** The toupper function converts a lowercase letter to a corresponding
108 @param[in] c The character to be converted.
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
122 if ( (c
>= 'a') && (c
<= 'z') ) {
131 @return Returns the value of digit.
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)
139 return c
- '0'; // Value returned is between 0 and 35, inclusive.
143 /** The strtoll function converts the initial portion of the string pointed to
144 by nptr to long long int representation.
146 See the description for strtol for more information.
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.
155 strtoll(const char * nptr
, char ** endptr
, int base
)
158 long long Result
= 0;
161 BOOLEAN Negative
= FALSE
;
165 if((base
< 0) || (base
== 1) || (base
> 36)) {
171 // Skip leading spaces.
172 while(isspace(*nptr
)) ++nptr
;
174 // Process Subject sequence: optional sign followed by digits.
179 else if(*nptr
== '-') {
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 */
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 */
198 if(base
== 0) { /* If still zero then must be decimal */
202 for( ; *nptr
== '0'; ++nptr
); /* Skip any remaining leading zeros */
206 while( isalnum(*nptr
) && ((temp
= Digit2Val(*nptr
)) < base
)) {
208 Result
= MultS64x64 (Result
, base
) + (long long int)temp
;
209 if( Result
<= Previous
) { // Detect Overflow
226 // Save pointer to final sequence
228 *endptr
= (char *)pEnd
;
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.
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.
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.
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
272 In other than the "C" locale, additional locale-specific subject sequence
273 forms may be accepted.
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.
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
288 strtol(const char * nptr
, char ** endptr
, int base
)
294 BOOLEAN Negative
= FALSE
;
298 if((base
< 0) || (base
== 1) || (base
> 36)) {
304 // Skip leading spaces.
305 while(isspace(*nptr
)) ++nptr
;
307 // Process Subject sequence: optional sign followed by digits.
312 else if(*nptr
== '-') {
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 */
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 */
331 if(base
== 0) { /* If still zero then must be decimal */
335 for( ; *nptr
== '0'; ++nptr
); /* Skip any remaining leading zeros */
339 while( isalnum(*nptr
) && ((temp
= Digit2Val(*nptr
)) < base
)) {
341 Result
= (Result
* base
) + (long int)temp
;
342 if( Result
<= Previous
) { // Detect Overflow
359 // Save pointer to final sequence
361 *endptr
= (char *)pEnd
;
366 /** The strtoull function converts the initial portion of the string pointed to
367 by nptr to unsigned long long int representation.
369 See the description for strtol for more information.
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.
377 strtoull(const char * nptr
, char ** endptr
, int base
)
380 unsigned long long Result
= 0;
381 unsigned long long Previous
;
386 if((base
< 0) || (base
== 1) || (base
> 36)) {
392 // Skip leading spaces.
393 while(isspace(*nptr
)) ++nptr
;
395 // Process Subject sequence: optional + sign followed by digits.
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 */
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 */
414 if(base
== 0) { /* If still zero then must be decimal */
418 for( ; *nptr
== '0'; ++nptr
); /* Skip any remaining leading zeros */
422 while( isalnum(*nptr
) && ((temp
= Digit2Val(*nptr
)) < base
)) {
424 Result
= DivU64x32 (Result
, base
) + (unsigned long long)temp
;
425 if( Result
< Previous
) { // If we overflowed
433 // Save pointer to final sequence
435 *endptr
= (char *)pEnd
;
441 edk2 Jansson port does not support doubles, simply return 0.
443 These conversion functions convert the initial portion of the string
444 pointed to by nptr to double, float, and long double representation,
447 The strtod(), strtof(), and strtold() functions return the converted
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
454 If no conversion is performed, zero is returned and the value of nptr is
455 stored in the location referenced by endptr.
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.
465 strtod (const char * __restrict nptr
, char ** __restrict endptr
) {
467 DEBUG((DEBUG_INFO
, "We don't supprot double type on edk2 yet!"));
472 static UINT8 BitMask
[] = {
473 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
476 #define WHICH8(c) ((unsigned char)(c) >> 3)
477 #define WHICH_BIT(c) (BitMask[((c) & 0x7)])
478 #define BITMAP64 ((UINT64 *)bitmap)
482 BuildBitmap(unsigned char * bitmap
, const char *s2
, int n
)
487 // Initialize bitmap. Bit 0 is always 1 which corresponds to '\0'
488 for (BITMAP64
[0] = index
= 1; index
< n
; index
++) {
492 // Set bits in bitmap corresponding to the characters in s2
493 for (; *s2
!= '\0'; s2
++) {
495 bit
= WHICH_BIT(*s2
);
496 bitmap
[index
] = bitmap
[index
] | bit
;
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.
503 @return The strpbrk function returns a pointer to the character, or a
504 null pointer if no character from s2 occurs in s1.
507 strpbrk(const char *s1
, const char *s2
)
509 UINT8 bitmap
[ (((UCHAR_MAX
+ 1) / CHAR_BIT
) + (CHAR_BIT
- 1)) & ~7U];
513 BuildBitmap( bitmap
, s2
, sizeof(bitmap
) / sizeof(UINT64
));
515 for( ; *s1
!= '\0'; ++s1
) {
517 bit
= WHICH_BIT(*s1
);
518 if( (bitmap
[index
] & bit
) != 0) {
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.
529 The implementation shall behave as if no library function calls the
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.
540 return errnum_message
;
544 Allocate and zero-initialize array.
547 calloc(size_t Num
, size_t Size
)
552 NumSize
= Num
* Size
;
555 RetVal
= malloc(NumSize
);
556 if( RetVal
!= NULL
) {
557 (VOID
)ZeroMem( RetVal
, NumSize
);
560 DEBUG((DEBUG_POOL
, "0x%p = calloc(%d, %d)\n", RetVal
, Num
, Size
));
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.
570 UINTN CumulativeDays
[2][14] = {
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
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
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)
611 Get the system time as seconds elapsed since midnight, January 1, 1970.
613 time_t time (time_t *timer
)
620 // Get the current time and date information
622 gRT
->GetTime (&Time
, NULL
);
626 // UTime should now be set to 00:00:00 on Jan 1 of the current year.
628 for (Year
= 1970, CalTime
= 0; Year
!= Time
.Year
; Year
++) {
629 CalTime
= CalTime
+ (time_t)(CumulativeDays
[IsLeap(Year
)][13] * SECSPERDAY
);
633 // Add in number of seconds for current Month, Day, Hour, Minute, Seconds, and TimeZone adjustment
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) +
651 Performs a quick sort
653 void qsort (void *base
, size_t num
, size_t width
, int (*compare
)(const void *, const void *))
656 ASSERT (base
!= NULL
);
657 ASSERT (compare
!= NULL
);
659 PerformQuickSort (base
, (UINTN
)num
, (UINTN
)width
, (SORT_COMPARE
)compare
);
664 Get character from stream, we don't support file operastion on edk2 JSON library.
666 @return Returns the character currently pointed by the internal file position indicator of the specified stream
669 int fgetc(FILE * _File
){
673 Open stream file, we don't support file operastion on edk2 JSON library.
675 @return 0 Unsupported
678 FILE *fopen (const char *filename
, const char *mode
) {
682 Read stream from file, we don't support file operastion on edk2 JSON library.
684 @return 0 Unsupported
687 size_t fread (void * ptr
, size_t size
, size_t count
, FILE * stream
) {
691 Write stream from file, we don't support file operastion on edk2 JSON library.
693 @return 0 Unsupported
696 size_t fwrite (const void * ptr
, size_t size
, size_t count
, FILE * stream
) {
700 Close file, we don't support file operastion on edk2 JSON library.
702 @return 0 Unsupported
705 int fclose (FILE * stream
) {
709 Write the formatted string to file, we don't support file operastion on edk2 JSON library.
711 @return 0 Unsupported
714 int fprintf (FILE * stream
, const char * format
, ...) {
718 This function check if this is the formating string specifier.
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.
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.
732 CheckFormatingString (
733 IN CONST CHAR8
*FormatString
,
734 IN OUT UINTN
*CurrentPosition
,
738 CHAR8 FormatStringParamater
;
740 while (*(FormatString
+ *CurrentPosition
) != 's') {
742 // Loop until reach character 's' if the formating string is
743 // compliant with "[flags][width][.precision][length]" format for
744 // the string specifier.
746 FormatStringParamater
= *(FormatString
+ *CurrentPosition
);
747 if ((FormatStringParamater
!= '-') &&
748 (FormatStringParamater
!= '+') &&
749 (FormatStringParamater
!= '*') &&
750 (FormatStringParamater
!= '.') &&
751 !(((UINTN
)FormatStringParamater
>= (UINTN
)'0') && ((UINTN
)FormatStringParamater
<= (UINTN
)'9'))
755 (*CurrentPosition
)++;
756 if (*CurrentPosition
>= StrLength
) {
764 This function clones *FormatString however replaces "%s" with "%a" in the
767 @param[in] A Null-terminated ASCII format string.
769 @return The new format string. Caller has to free the memory of this string
774 ReplaceUnicodeToAsciiStrFormat (
775 IN CONST CHAR8
*FormatString
779 UINTN FormatStrIndex
;
780 UINTN FormatStrSpecifier
;
781 BOOLEAN PercentageMark
;
782 CHAR8
*TempFormatBuffer
;
783 BOOLEAN IsFormatString
;
788 if (FormatString
== NULL
) {
791 FormatStrSize
= AsciiStrSize(FormatString
);
792 if (FormatStrSize
== 0) {
795 TempFormatBuffer
= AllocatePool(FormatStrSize
); // Allocate memory for the
797 if (TempFormatBuffer
== NULL
) {
801 // Clone *FormatString but replace "%s" wih "%a".
802 // "%%" is not considered as the format tag.
804 PercentageMark
= FALSE
;
806 while (FormatStrIndex
< FormatStrSize
) {
807 if (PercentageMark
== TRUE
) {
809 // Previous character is "%".
811 PercentageMark
= FALSE
;
812 if (*(FormatString
+ FormatStrIndex
) != '%') { // Check if this is double "%".
813 FormatStrSpecifier
= FormatStrIndex
;
815 // Check if this is the formating string specifier.
817 IsFormatString
= CheckFormatingString (FormatString
, &FormatStrSpecifier
, FormatStrSize
);
818 if ((FormatStrSpecifier
- FormatStrIndex
) != 0) {
819 CopyMem((VOID
*)(TempFormatBuffer
+ FormatStrIndex
),
820 (VOID
*)(FormatString
+ FormatStrIndex
),
821 FormatStrSpecifier
- FormatStrIndex
824 FormatStrIndex
= FormatStrSpecifier
;
825 if (IsFormatString
== TRUE
) {
827 // Replace 's' with 'a' which is printed in ASCII
828 // format on edk2 environment.
830 *(TempFormatBuffer
+ FormatStrSpecifier
) = 'a';
837 if (*(FormatString
+ FormatStrIndex
) == '%') {
839 // This character is "%", set the flag.
841 PercentageMark
= TRUE
;
845 // Clone character to the new string and advance FormatStrIndex
846 // to process next character.
848 *(TempFormatBuffer
+ FormatStrIndex
) = *(FormatString
+ FormatStrIndex
);
851 return TempFormatBuffer
;
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.
860 @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
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.
866 @return The number of ASCII characters in the produced output buffer not including the
872 RedfishAsciiVSPrint (
873 OUT CHAR8
*StartOfBuffer
,
875 IN CONST CHAR8
*FormatString
,
879 CHAR8
*TempFormatBuffer
;
880 UINTN LenStrProduced
;
883 // Looking for "%s" in the format string and replace it
884 // with "%a" for printing ASCII code characters on edk2
887 TempFormatBuffer
= ReplaceUnicodeToAsciiStrFormat (FormatString
);
888 if (TempFormatBuffer
== NULL
) {
891 LenStrProduced
= AsciiVSPrint (StartOfBuffer
, BufferSize
, (CONST CHAR8
*)TempFormatBuffer
, Marker
);
892 FreePool (TempFormatBuffer
);
893 return LenStrProduced
;
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.
902 @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
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.
909 @return The number of ASCII characters in the produced output buffer not including the
916 OUT CHAR8
*StartOfBuffer
,
918 IN CONST CHAR8
*FormatString
,
923 UINTN LenStrProduced
;
925 VA_START(Marker
, FormatString
);
926 LenStrProduced
= RedfishAsciiVSPrint (StartOfBuffer
, BufferSize
, FormatString
, Marker
);
927 return LenStrProduced
;