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>
20 Determine if a particular character is an alphanumeric character
21 @return Returns 1 if c is an alphanumeric character, otherwise returns 0.
26 // <alnum> ::= [0-9] | [a-z] | [A-Z]
28 return ((('0' <= (c
)) && ((c
) <= '9')) ||
29 (('a' <= (c
)) && ((c
) <= 'z')) ||
30 (('A' <= (c
)) && ((c
) <= 'Z')));
34 Determine if a particular character is a digital character
36 @return Returns 1 if c is an digital character, otherwise returns 0.
43 return ((('0' <= (c
)) && ((c
) <= '9')) ||
44 (c
== 'e') || (c
== 'E') ||
45 (c
== '+') || (c
== '-') ||
50 Determine if a particular character is a space character
52 @return Returns 1 if c is a space character
59 return ((c
) == ' ') || ((c
) == '\t') || ((c
) == '\r') || ((c
) == '\n') || ((c
) == '\v') || ((c
) == '\f');
63 Allocates memory blocks
65 void *malloc (size_t size
)
67 return AllocatePool ((UINTN
) size
);
71 De-allocates or frees a memory block
76 // In Standard C, free() handles a null pointer argument transparently. This
77 // is not true of FreePool() below, so protect it.
85 NetBSD Compatibility Function strdup creates a duplicate copy of a string.
87 @return Returns the pointer to duplicated string.
89 char * strdup(const char *str
)
94 len
= strlen(str
) + 1;
95 if ((copy
= malloc(len
)) == NULL
)
97 memcpy(copy
, str
, len
);
101 /** The toupper function converts a lowercase letter to a corresponding
104 @param[in] c The character to be converted.
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
118 if ( (c
>= 'a') && (c
<= 'z') ) {
127 @return Returns the value of digit.
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)
135 return c
- '0'; // Value returned is between 0 and 35, inclusive.
139 /** The strtoll function converts the initial portion of the string pointed to
140 by nptr to long long int representation.
142 See the description for strtol for more information.
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.
151 strtoll(const char * nptr
, char ** endptr
, int base
)
154 long long Result
= 0;
157 BOOLEAN Negative
= FALSE
;
161 if((base
< 0) || (base
== 1) || (base
> 36)) {
167 // Skip leading spaces.
168 while(isspace(*nptr
)) ++nptr
;
170 // Process Subject sequence: optional sign followed by digits.
175 else if(*nptr
== '-') {
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 */
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 */
194 if(base
== 0) { /* If still zero then must be decimal */
198 for( ; *nptr
== '0'; ++nptr
); /* Skip any remaining leading zeros */
202 while( isalnum(*nptr
) && ((temp
= Digit2Val(*nptr
)) < base
)) {
204 Result
= MultS64x64 (Result
, base
) + (long long int)temp
;
205 if( Result
<= Previous
) { // Detect Overflow
222 // Save pointer to final sequence
224 *endptr
= (char *)pEnd
;
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.
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.
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.
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
268 In other than the "C" locale, additional locale-specific subject sequence
269 forms may be accepted.
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.
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
284 strtol(const char * nptr
, char ** endptr
, int base
)
290 BOOLEAN Negative
= FALSE
;
294 if((base
< 0) || (base
== 1) || (base
> 36)) {
300 // Skip leading spaces.
301 while(isspace(*nptr
)) ++nptr
;
303 // Process Subject sequence: optional sign followed by digits.
308 else if(*nptr
== '-') {
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 */
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 */
327 if(base
== 0) { /* If still zero then must be decimal */
331 for( ; *nptr
== '0'; ++nptr
); /* Skip any remaining leading zeros */
335 while( isalnum(*nptr
) && ((temp
= Digit2Val(*nptr
)) < base
)) {
337 Result
= (Result
* base
) + (long int)temp
;
338 if( Result
<= Previous
) { // Detect Overflow
355 // Save pointer to final sequence
357 *endptr
= (char *)pEnd
;
362 /** The strtoull function converts the initial portion of the string pointed to
363 by nptr to unsigned long long int representation.
365 See the description for strtol for more information.
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.
373 strtoull(const char * nptr
, char ** endptr
, int base
)
376 unsigned long long Result
= 0;
377 unsigned long long Previous
;
382 if((base
< 0) || (base
== 1) || (base
> 36)) {
388 // Skip leading spaces.
389 while(isspace(*nptr
)) ++nptr
;
391 // Process Subject sequence: optional + sign followed by digits.
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 */
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 */
410 if(base
== 0) { /* If still zero then must be decimal */
414 for( ; *nptr
== '0'; ++nptr
); /* Skip any remaining leading zeros */
418 while( isalnum(*nptr
) && ((temp
= Digit2Val(*nptr
)) < base
)) {
420 Result
= DivU64x32 (Result
, base
) + (unsigned long long)temp
;
421 if( Result
< Previous
) { // If we overflowed
429 // Save pointer to final sequence
431 *endptr
= (char *)pEnd
;
437 edk2 Jansson port does not support doubles, simply return 0.
439 These conversion functions convert the initial portion of the string
440 pointed to by nptr to double, float, and long double representation,
443 The strtod(), strtof(), and strtold() functions return the converted
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
450 If no conversion is performed, zero is returned and the value of nptr is
451 stored in the location referenced by endptr.
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.
461 strtod (const char * __restrict nptr
, char ** __restrict endptr
) {
463 DEBUG((DEBUG_INFO
, "We don't supprot double type on edk2 yet!"));
469 Allocate and zero-initialize array.
472 calloc(size_t Num
, size_t Size
)
477 NumSize
= Num
* Size
;
480 RetVal
= malloc(NumSize
);
481 if( RetVal
!= NULL
) {
482 (VOID
)ZeroMem( RetVal
, NumSize
);
485 DEBUG((DEBUG_POOL
, "0x%p = calloc(%d, %d)\n", RetVal
, Num
, Size
));
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.
495 UINTN CumulativeDays
[2][14] = {
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
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
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)
536 Get the system time as seconds elapsed since midnight, January 1, 1970.
538 time_t time (time_t *timer
)
545 // Get the current time and date information
547 gRT
->GetTime (&Time
, NULL
);
551 // UTime should now be set to 00:00:00 on Jan 1 of the current year.
553 for (Year
= 1970, CalTime
= 0; Year
!= Time
.Year
; Year
++) {
554 CalTime
= CalTime
+ (time_t)(CumulativeDays
[IsLeap(Year
)][13] * SECSPERDAY
);
558 // Add in number of seconds for current Month, Day, Hour, Minute, Seconds, and TimeZone adjustment
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) +
576 Performs a quick sort
578 void qsort (void *base
, size_t num
, size_t width
, int (*compare
)(const void *, const void *))
581 ASSERT (base
!= NULL
);
582 ASSERT (compare
!= NULL
);
584 PerformQuickSort (base
, (UINTN
)num
, (UINTN
)width
, (SORT_COMPARE
)compare
);
589 Get character from stream, we don't support file operastion on edk2 JSON library.
591 @return Returns the character currently pointed by the internal file position indicator of the specified stream
594 int fgetc(FILE * _File
){
598 This function check if this is the formating string specifier.
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.
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.
612 CheckFormatingString (
613 IN CONST CHAR8
*FormatString
,
614 IN OUT UINTN
*CurrentPosition
,
618 CHAR8 FormatStringParamater
;
620 while (*(FormatString
+ *CurrentPosition
) != 's') {
622 // Loop until reach character 's' if the formating string is
623 // compliant with "[flags][width][.precision][length]" format for
624 // the string specifier.
626 FormatStringParamater
= *(FormatString
+ *CurrentPosition
);
627 if ((FormatStringParamater
!= '-') &&
628 (FormatStringParamater
!= '+') &&
629 (FormatStringParamater
!= '*') &&
630 (FormatStringParamater
!= '.') &&
631 !(((UINTN
)FormatStringParamater
>= (UINTN
)'0') && ((UINTN
)FormatStringParamater
<= (UINTN
)'9'))
635 (*CurrentPosition
)++;
636 if (*CurrentPosition
>= StrLength
) {
644 This function clones *FormatString however replaces "%s" with "%a" in the
647 @param[in] A Null-terminated ASCII format string.
649 @return The new format string. Caller has to free the memory of this string
654 ReplaceUnicodeToAsciiStrFormat (
655 IN CONST CHAR8
*FormatString
659 UINTN FormatStrIndex
;
660 UINTN FormatStrSpecifier
;
661 BOOLEAN PercentageMark
;
662 CHAR8
*TempFormatBuffer
;
663 BOOLEAN IsFormatString
;
668 if (FormatString
== NULL
) {
671 FormatStrSize
= AsciiStrSize(FormatString
);
672 if (FormatStrSize
== 0) {
675 TempFormatBuffer
= AllocatePool(FormatStrSize
); // Allocate memory for the
677 if (TempFormatBuffer
== NULL
) {
681 // Clone *FormatString but replace "%s" wih "%a".
682 // "%%" is not considered as the format tag.
684 PercentageMark
= FALSE
;
686 while (FormatStrIndex
< FormatStrSize
) {
687 if (PercentageMark
== TRUE
) {
689 // Previous character is "%".
691 PercentageMark
= FALSE
;
692 if (*(FormatString
+ FormatStrIndex
) != '%') { // Check if this is double "%".
693 FormatStrSpecifier
= FormatStrIndex
;
695 // Check if this is the formating string specifier.
697 IsFormatString
= CheckFormatingString (FormatString
, &FormatStrSpecifier
, FormatStrSize
);
698 if ((FormatStrSpecifier
- FormatStrIndex
) != 0) {
699 CopyMem((VOID
*)(TempFormatBuffer
+ FormatStrIndex
),
700 (VOID
*)(FormatString
+ FormatStrIndex
),
701 FormatStrSpecifier
- FormatStrIndex
704 FormatStrIndex
= FormatStrSpecifier
;
705 if (IsFormatString
== TRUE
) {
707 // Replace 's' with 'a' which is printed in ASCII
708 // format on edk2 environment.
710 *(TempFormatBuffer
+ FormatStrSpecifier
) = 'a';
717 if (*(FormatString
+ FormatStrIndex
) == '%') {
719 // This character is "%", set the flag.
721 PercentageMark
= TRUE
;
725 // Clone character to the new string and advance FormatStrIndex
726 // to process next character.
728 *(TempFormatBuffer
+ FormatStrIndex
) = *(FormatString
+ FormatStrIndex
);
731 return TempFormatBuffer
;
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.
740 @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
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.
746 @return The number of ASCII characters in the produced output buffer not including the
752 RedfishAsciiVSPrint (
753 OUT CHAR8
*StartOfBuffer
,
755 IN CONST CHAR8
*FormatString
,
759 CHAR8
*TempFormatBuffer
;
760 UINTN LenStrProduced
;
763 // Looking for "%s" in the format string and replace it
764 // with "%a" for printing ASCII code characters on edk2
767 TempFormatBuffer
= ReplaceUnicodeToAsciiStrFormat (FormatString
);
768 if (TempFormatBuffer
== NULL
) {
771 LenStrProduced
= AsciiVSPrint (StartOfBuffer
, BufferSize
, (CONST CHAR8
*)TempFormatBuffer
, Marker
);
772 FreePool (TempFormatBuffer
);
773 return LenStrProduced
;
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.
782 @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
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.
789 @return The number of ASCII characters in the produced output buffer not including the
796 OUT CHAR8
*StartOfBuffer
,
798 IN CONST CHAR8
*FormatString
,
803 UINTN LenStrProduced
;
805 VA_START(Marker
, FormatString
);
806 LenStrProduced
= RedfishAsciiVSPrint (StartOfBuffer
, BufferSize
, FormatString
, Marker
);
807 return LenStrProduced
;