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.
33 // <alnum> ::= [0-9] | [a-z] | [A-Z]
35 return ((('0' <= (c
)) && ((c
) <= '9')) ||
36 (('a' <= (c
)) && ((c
) <= 'z')) ||
37 (('A' <= (c
)) && ((c
) <= 'Z')));
41 Determine if a particular character is a digital character
43 @return Returns 1 if c is an digital character, otherwise returns 0.
53 return ((('0' <= (c
)) && ((c
) <= '9')) ||
54 (c
== 'e') || (c
== 'E') ||
55 (c
== '+') || (c
== '-') ||
60 Determine if a particular character is a space character
62 @return Returns 1 if c is a space character
72 return ((c
) == ' ') || ((c
) == '\t') || ((c
) == '\r') || ((c
) == '\n') || ((c
) == '\v') || ((c
) == '\f');
76 Allocates memory blocks
83 return AllocatePool ((UINTN
)size
);
87 De-allocates or frees a memory block
95 // In Standard C, free() handles a null pointer argument transparently. This
96 // is not true of FreePool() below, so protect it.
104 NetBSD Compatibility Function strdup creates a duplicate copy of a string.
106 @return Returns the pointer to duplicated string.
116 len
= strlen (str
) + 1;
117 if ((copy
= malloc (len
)) == NULL
) {
121 memcpy (copy
, str
, len
);
125 /** The toupper function converts a lowercase letter to a corresponding
128 @param[in] c The character to be converted.
130 @return If the argument is a character for which islower is true and
131 there are one or more corresponding characters, as specified by
132 the current locale, for which isupper is true, the toupper
133 function returns one of the corresponding characters (always the
134 same one for any given locale); otherwise, the argument is
142 if ((c
>= 'a') && (c
<= 'z')) {
152 @return Returns the value of digit.
159 if (((c
>= 'a') && (c
<= 'z')) || ((c
>= 'A') && (c
<= 'Z'))) {
160 /* If c is one of [A-Za-z]... */
161 c
= toupper (c
) - 7; // Adjust so 'A' is ('9' + 1)
164 return c
- '0'; // Value returned is between 0 and 35, inclusive.
167 /** The strtoll function converts the initial portion of the string pointed to
168 by nptr to long long int representation.
170 See the description for strtol for more information.
172 @return The strtoll function returns the converted value, if any. If no
173 conversion could be performed, zero is returned. If the correct
174 value is outside the range of representable values, LLONG_MIN or
175 LLONG_MAX is returned (according to the sign of the value, if any),
176 and the value of the macro ERANGE is stored in errno.
186 long long Result
= 0;
189 BOOLEAN Negative
= FALSE
;
193 if ((base
< 0) || (base
== 1) || (base
> 36)) {
194 if (endptr
!= NULL
) {
201 // Skip leading spaces.
202 while (isspace (*nptr
)) {
206 // Process Subject sequence: optional sign followed by digits.
210 } else if (*nptr
== '-') {
216 /* Might be Octal or Hex */
217 if (toupper (nptr
[1]) == 'X') {
219 if ((base
== 0) || (base
== 16)) {
220 nptr
+= 2; /* Skip the "0X" */
221 base
= 16; /* In case base was 0 */
224 /* Looks like Octal */
225 if ((base
== 0) || (base
== 8)) {
226 ++nptr
; /* Skip the leading "0" */
227 base
= 8; /* In case base was 0 */
233 /* If still zero then must be decimal */
238 for ( ; *nptr
== '0'; ++nptr
) {
239 /* Skip any remaining leading zeros */
245 while ( isalnum (*nptr
) && ((temp
= Digit2Val (*nptr
)) < base
)) {
247 Result
= MultS64x64 (Result
, base
) + (long long int)temp
;
248 if ( Result
<= Previous
) {
268 // Save pointer to final sequence
269 if (endptr
!= NULL
) {
270 *endptr
= (char *)pEnd
;
276 /** The strtol, strtoll, strtoul, and strtoull functions convert the initial
277 portion of the string pointed to by nptr to long int, long long int,
278 unsigned long int, and unsigned long long int representation, respectively.
279 First, they decompose the input string into three parts: an initial,
280 possibly empty, sequence of white-space characters (as specified by the
281 isspace function), a subject sequence resembling an integer represented in
282 some radix determined by the value of base, and a final string of one or
283 more unrecognized characters, including the terminating null character of
284 the input string. Then, they attempt to convert the subject sequence to an
285 integer, and return the result.
287 If the value of base is zero, the expected form of the subject sequence is
288 that of an integer constant, optionally preceded
289 by a plus or minus sign, but not including an integer suffix. If the value
290 of base is between 2 and 36 (inclusive), the expected form of the subject
291 sequence is a sequence of letters and digits representing an integer with
292 the radix specified by base, optionally preceded by a plus or minus sign,
293 but not including an integer suffix. The letters from a (or A) through z
294 (or Z) are ascribed the values 10 through 35; only letters and digits whose
295 ascribed values are less than that of base are permitted. If the value of
296 base is 16, the characters 0x or 0X may optionally precede the sequence of
297 letters and digits, following the sign if present.
299 The subject sequence is defined as the longest initial subsequence of the
300 input string, starting with the first non-white-space character, that is of
301 the expected form. The subject sequence contains no characters if the input
302 string is empty or consists entirely of white space, or if the first
303 non-white-space character is other than a sign or a permissible letter or digit.
305 If the subject sequence has the expected form and the value of base is
306 zero, the sequence of characters starting with the first digit is
307 interpreted as an integer constant. If the subject sequence has the
308 expected form and the value of base is between 2 and 36, it is used as the
309 base for conversion, ascribing to each letter its value as given above. If
310 the subject sequence begins with a minus sign, the value resulting from the
311 conversion is negated (in the return type). A pointer to the final string
312 is stored in the object pointed to by endptr, provided that endptr is
315 In other than the "C" locale, additional locale-specific subject sequence
316 forms may be accepted.
318 If the subject sequence is empty or does not have the expected form, no
319 conversion is performed; the value of nptr is stored in the object pointed
320 to by endptr, provided that endptr is not a null pointer.
322 @return The strtol, strtoll, strtoul, and strtoull functions return the
323 converted value, if any. If no conversion could be performed, zero
324 is returned. If the correct value is outside the range of
325 representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX,
326 ULONG_MAX, or ULLONG_MAX is returned (according to the return type
327 and sign of the value, if any), and the value of the macro ERANGE
341 BOOLEAN Negative
= FALSE
;
345 if ((base
< 0) || (base
== 1) || (base
> 36)) {
346 if (endptr
!= NULL
) {
353 // Skip leading spaces.
354 while (isspace (*nptr
)) {
358 // Process Subject sequence: optional sign followed by digits.
362 } else if (*nptr
== '-') {
368 /* Might be Octal or Hex */
369 if (toupper (nptr
[1]) == 'X') {
371 if ((base
== 0) || (base
== 16)) {
372 nptr
+= 2; /* Skip the "0X" */
373 base
= 16; /* In case base was 0 */
376 /* Looks like Octal */
377 if ((base
== 0) || (base
== 8)) {
378 ++nptr
; /* Skip the leading "0" */
379 base
= 8; /* In case base was 0 */
385 /* If still zero then must be decimal */
390 for ( ; *nptr
== '0'; ++nptr
) {
391 /* Skip any remaining leading zeros */
397 while ( isalnum (*nptr
) && ((temp
= Digit2Val (*nptr
)) < base
)) {
399 Result
= (Result
* base
) + (long int)temp
;
400 if ( Result
<= Previous
) {
420 // Save pointer to final sequence
421 if (endptr
!= NULL
) {
422 *endptr
= (char *)pEnd
;
428 /** The strtoull function converts the initial portion of the string pointed to
429 by nptr to unsigned long long int representation.
431 See the description for strtol for more information.
433 @return The strtoull function returns the converted value, if any. If no
434 conversion could be performed, zero is returned. If the correct
435 value is outside the range of representable values, ULLONG_MAX is
436 returned and the value of the macro ERANGE is stored in errno.
446 unsigned long long Result
= 0;
447 unsigned long long Previous
;
452 if ((base
< 0) || (base
== 1) || (base
> 36)) {
453 if (endptr
!= NULL
) {
460 // Skip leading spaces.
461 while (isspace (*nptr
)) {
465 // Process Subject sequence: optional + sign followed by digits.
471 /* Might be Octal or Hex */
472 if (toupper (nptr
[1]) == 'X') {
474 if ((base
== 0) || (base
== 16)) {
475 nptr
+= 2; /* Skip the "0X" */
476 base
= 16; /* In case base was 0 */
479 /* Looks like Octal */
480 if ((base
== 0) || (base
== 8)) {
481 ++nptr
; /* Skip the leading "0" */
482 base
= 8; /* In case base was 0 */
488 /* If still zero then must be decimal */
493 for ( ; *nptr
== '0'; ++nptr
) {
494 /* Skip any remaining leading zeros */
500 while ( isalnum (*nptr
) && ((temp
= Digit2Val (*nptr
)) < base
)) {
502 Result
= DivU64x32 (Result
, base
) + (unsigned long long)temp
;
503 if ( Result
< Previous
) {
513 // Save pointer to final sequence
514 if (endptr
!= NULL
) {
515 *endptr
= (char *)pEnd
;
522 edk2 Jansson port does not support doubles, simply return 0.
524 These conversion functions convert the initial portion of the string
525 pointed to by nptr to double, float, and long double representation,
528 The strtod(), strtof(), and strtold() functions return the converted
531 If endptr is not NULL, a pointer to the character after the last charac-
532 ter used in the conversion is stored in the location referenced by
535 If no conversion is performed, zero is returned and the value of nptr is
536 stored in the location referenced by endptr.
538 If the correct value would cause overflow, plus or minus HUGE_VAL,
539 HUGE_VALF, or HUGE_VALL is returned (according to the sign and type of
540 the return value), and ERANGE is stored in errno. If the correct value
541 would cause underflow, zero is returned and ERANGE is stored in errno.
547 const char *__restrict nptr
,
548 char **__restrict endptr
551 DEBUG ((DEBUG_INFO
, "We don't supprot double type on edk2 yet!"));
556 static UINT8 BitMask
[] = {
557 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
560 #define WHICH8(c) ((unsigned char)(c) >> 3)
561 #define WHICH_BIT(c) (BitMask[((c) & 0x7)])
562 #define BITMAP64 ((UINT64 *)bitmap)
567 unsigned char *bitmap
,
575 // Initialize bitmap. Bit 0 is always 1 which corresponds to '\0'
576 for (BITMAP64
[0] = index
= 1; index
< n
; index
++) {
580 // Set bits in bitmap corresponding to the characters in s2
581 for ( ; *s2
!= '\0'; s2
++) {
582 index
= WHICH8 (*s2
);
583 bit
= WHICH_BIT (*s2
);
584 bitmap
[index
] = bitmap
[index
] | bit
;
588 /** The strpbrk function locates the first occurrence in the string pointed to
589 by s1 of any character from the string pointed to by s2.
591 @return The strpbrk function returns a pointer to the character, or a
592 null pointer if no character from s2 occurs in s1.
600 UINT8 bitmap
[(((UCHAR_MAX
+ 1) / CHAR_BIT
) + (CHAR_BIT
- 1)) & ~7U];
604 BuildBitmap (bitmap
, s2
, sizeof (bitmap
) / sizeof (UINT64
));
606 for ( ; *s1
!= '\0'; ++s1
) {
607 index
= WHICH8 (*s1
);
608 bit
= WHICH_BIT (*s1
);
609 if ((bitmap
[index
] & bit
) != 0) {
617 /** The strerror function maps the number in errnum to a message string.
618 Typically, the values for errnum come from errno, but strerror shall map
619 any value of type int to a message.
621 The implementation shall behave as if no library function calls the
624 @return The strerror function returns a pointer to the string, the
625 contents of which are locale specific. The array pointed to
626 shall not be modified by the program, but may be overwritten by
627 a subsequent call to the strerror function.
634 return errnum_message
;
638 Allocate and zero-initialize array.
649 NumSize
= Num
* Size
;
652 RetVal
= malloc (NumSize
);
653 if ( RetVal
!= NULL
) {
654 (VOID
)ZeroMem (RetVal
, NumSize
);
658 DEBUG ((DEBUG_POOL
, "0x%p = calloc(%d, %d)\n", RetVal
, Num
, Size
));
664 // The arrays give the cumulative number of days up to the first of the
665 // month number used as the index (1 -> 12) for regular and leap years.
666 // The value at index 13 is for the whole year.
668 UINTN CumulativeDays
[2][14] = {
676 31 + 28 + 31 + 30 + 31,
677 31 + 28 + 31 + 30 + 31 + 30,
678 31 + 28 + 31 + 30 + 31 + 30 + 31,
679 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
680 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
681 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
682 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
683 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
692 31 + 29 + 31 + 30 + 31,
693 31 + 29 + 31 + 30 + 31 + 30,
694 31 + 29 + 31 + 30 + 31 + 30 + 31,
695 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
696 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
697 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
698 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
699 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
703 #define IsLeap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
704 #define SECSPERMIN (60)
705 #define SECSPERHOUR (60 * 60)
706 #define SECSPERDAY (24 * SECSPERHOUR)
709 Get the system time as seconds elapsed since midnight, January 1, 1970.
721 // Get the current time and date information
723 gRT
->GetTime (&Time
, NULL
);
727 // UTime should now be set to 00:00:00 on Jan 1 of the current year.
729 for (Year
= 1970, CalTime
= 0; Year
!= Time
.Year
; Year
++) {
730 CalTime
= CalTime
+ (time_t)(CumulativeDays
[IsLeap (Year
)][13] * SECSPERDAY
);
734 // Add in number of seconds for current Month, Day, Hour, Minute, Seconds, and TimeZone adjustment
737 (time_t)((Time
.TimeZone
!= EFI_UNSPECIFIED_TIMEZONE
) ? (Time
.TimeZone
* 60) : 0) +
738 (time_t)(CumulativeDays
[IsLeap (Time
.Year
)][Time
.Month
] * SECSPERDAY
) +
739 (time_t)(((Time
.Day
> 0) ? Time
.Day
- 1 : 0) * SECSPERDAY
) +
740 (time_t)(Time
.Hour
* SECSPERHOUR
) +
741 (time_t)(Time
.Minute
* 60) +
752 Performs a quick sort
759 int ( *compare
)(const void *, const void *)
762 ASSERT (base
!= NULL
);
763 ASSERT (compare
!= NULL
);
765 PerformQuickSort (base
, (UINTN
)num
, (UINTN
)width
, (SORT_COMPARE
)compare
);
770 Get character from stream, we don't support file operastion on edk2 JSON library.
772 @return Returns the character currently pointed by the internal file position indicator of the specified stream
784 Open stream file, we don't support file operastion on edk2 JSON library.
786 @return 0 Unsupported
791 const char *filename
,
799 Read stream from file, we don't support file operastion on edk2 JSON library.
801 @return 0 Unsupported
816 Write stream from file, we don't support file operastion on edk2 JSON library.
818 @return 0 Unsupported
833 Close file, we don't support file operastion on edk2 JSON library.
835 @return 0 Unsupported
847 Write the formatted string to file, we don't support file operastion on edk2 JSON library.
849 @return 0 Unsupported
863 This function check if this is the formating string specifier.
865 @param[in] FormatString A Null-terminated ASCII format string.
866 @param[in,out] CurrentPosition The starting position at the given string to check for
867 "[flags][width][.precision][length]s" string specifier.
868 @param[in] StrLength Maximum string length.
870 @return BOOLEAN TRUE means this is the formating string specifier. CurrentPosition is
871 returned at the position of "s".
872 FALSE means this is not the formating string specifier.. CurrentPosition is
873 returned at the position of failed character.
877 CheckFormatingString (
878 IN CONST CHAR8
*FormatString
,
879 IN OUT UINTN
*CurrentPosition
,
883 CHAR8 FormatStringParamater
;
885 while (*(FormatString
+ *CurrentPosition
) != 's') {
887 // Loop until reach character 's' if the formating string is
888 // compliant with "[flags][width][.precision][length]" format for
889 // the string specifier.
891 FormatStringParamater
= *(FormatString
+ *CurrentPosition
);
892 if ((FormatStringParamater
!= '-') &&
893 (FormatStringParamater
!= '+') &&
894 (FormatStringParamater
!= '*') &&
895 (FormatStringParamater
!= '.') &&
896 !(((UINTN
)FormatStringParamater
>= (UINTN
)'0') && ((UINTN
)FormatStringParamater
<= (UINTN
)'9'))
902 (*CurrentPosition
)++;
903 if (*CurrentPosition
>= StrLength
) {
912 This function clones *FormatString however replaces "%s" with "%a" in the
915 @param[in] A Null-terminated ASCII format string.
917 @return The new format string. Caller has to free the memory of this string
922 ReplaceUnicodeToAsciiStrFormat (
923 IN CONST CHAR8
*FormatString
927 UINTN FormatStrIndex
;
928 UINTN FormatStrSpecifier
;
929 BOOLEAN PercentageMark
;
930 CHAR8
*TempFormatBuffer
;
931 BOOLEAN IsFormatString
;
936 if (FormatString
== NULL
) {
940 FormatStrSize
= AsciiStrSize (FormatString
);
941 if (FormatStrSize
== 0) {
945 TempFormatBuffer
= AllocatePool (FormatStrSize
); // Allocate memory for the
947 if (TempFormatBuffer
== NULL
) {
952 // Clone *FormatString but replace "%s" wih "%a".
953 // "%%" is not considered as the format tag.
955 PercentageMark
= FALSE
;
957 while (FormatStrIndex
< FormatStrSize
) {
958 if (PercentageMark
== TRUE
) {
960 // Previous character is "%".
962 PercentageMark
= FALSE
;
963 if (*(FormatString
+ FormatStrIndex
) != '%') {
964 // Check if this is double "%".
965 FormatStrSpecifier
= FormatStrIndex
;
967 // Check if this is the formating string specifier.
969 IsFormatString
= CheckFormatingString (FormatString
, &FormatStrSpecifier
, FormatStrSize
);
970 if ((FormatStrSpecifier
- FormatStrIndex
) != 0) {
972 (VOID
*)(TempFormatBuffer
+ FormatStrIndex
),
973 (VOID
*)(FormatString
+ FormatStrIndex
),
974 FormatStrSpecifier
- FormatStrIndex
978 FormatStrIndex
= FormatStrSpecifier
;
979 if (IsFormatString
== TRUE
) {
981 // Replace 's' with 'a' which is printed in ASCII
982 // format on edk2 environment.
984 *(TempFormatBuffer
+ FormatStrSpecifier
) = 'a';
994 if (*(FormatString
+ FormatStrIndex
) == '%') {
996 // This character is "%", set the flag.
998 PercentageMark
= TRUE
;
1003 // Clone character to the new string and advance FormatStrIndex
1004 // to process next character.
1006 *(TempFormatBuffer
+ FormatStrIndex
) = *(FormatString
+ FormatStrIndex
);
1010 return TempFormatBuffer
;
1014 This is the Redfish version of CRT vsnprintf function, this function replaces "%s" to
1015 "%a" before invoking AsciiVSPrint(). That is because "%s" is unicode base on edk2
1016 environment however "%s" is ascii code base on vsnprintf().
1017 See definitions of AsciiVSPrint() for the details.
1019 @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
1021 @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
1022 @param FormatString A Null-terminated ASCII format string.
1023 @param Marker VA_LIST marker for the variable argument list.
1025 @return The number of ASCII characters in the produced output buffer not including the
1031 RedfishAsciiVSPrint (
1032 OUT CHAR8
*StartOfBuffer
,
1033 IN UINTN BufferSize
,
1034 IN CONST CHAR8
*FormatString
,
1038 CHAR8
*TempFormatBuffer
;
1039 UINTN LenStrProduced
;
1042 // Looking for "%s" in the format string and replace it
1043 // with "%a" for printing ASCII code characters on edk2
1046 TempFormatBuffer
= ReplaceUnicodeToAsciiStrFormat (FormatString
);
1047 if (TempFormatBuffer
== NULL
) {
1051 LenStrProduced
= AsciiVSPrint (StartOfBuffer
, BufferSize
, (CONST CHAR8
*)TempFormatBuffer
, Marker
);
1052 FreePool (TempFormatBuffer
);
1053 return LenStrProduced
;
1057 This is the Redfish version of CRT snprintf function, this function replaces "%s" to
1058 "%a" before invoking AsciiSPrint(). That is because "%s" is unicode base on edk2
1059 environment however "%s" is ascii code base on snprintf().
1060 See definitions of AsciiSPrint() for the details.
1062 @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
1064 @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
1065 @param FormatString A Null-terminated ASCII format string.
1066 @param ... Variable argument list whose contents are accessed based on the
1067 format string specified by FormatString.
1069 @return The number of ASCII characters in the produced output buffer not including the
1075 RedfishAsciiSPrint (
1076 OUT CHAR8
*StartOfBuffer
,
1077 IN UINTN BufferSize
,
1078 IN CONST CHAR8
*FormatString
,
1083 UINTN LenStrProduced
;
1085 VA_START (Marker
, FormatString
);
1086 LenStrProduced
= RedfishAsciiVSPrint (StartOfBuffer
, BufferSize
, FormatString
, Marker
);
1087 return LenStrProduced
;