12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088 |
- /** @file
- CRT wrapper functions for system call,the string operation functions
- are remodeled after edk2-libc.
- Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
- (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <Uefi.h>
- #include <Library/RedfishCrtLib.h>
- #include <Library/MemoryAllocationLib.h>
- #include <Library/SortLib.h>
- #include <Library/UefiRuntimeServicesTableLib.h>
- int errno = 0;
- char errnum_message[] = "We don't support to map errnum to the error message on edk2 Redfish\n";
- // This is required to keep VC++ happy if you use floating-point
- int _fltused = 1;
- /**
- Determine if a particular character is an alphanumeric character
- @return Returns 1 if c is an alphanumeric character, otherwise returns 0.
- **/
- int
- isalnum (
- int c
- )
- {
- //
- // <alnum> ::= [0-9] | [a-z] | [A-Z]
- //
- return ((('0' <= (c)) && ((c) <= '9')) ||
- (('a' <= (c)) && ((c) <= 'z')) ||
- (('A' <= (c)) && ((c) <= 'Z')));
- }
- /**
- Determine if a particular character is a digital character
- @return Returns 1 if c is an digital character, otherwise returns 0.
- **/
- int
- isdchar (
- int c
- )
- {
- //
- // [0-9] | [e +-.]
- //
- return ((('0' <= (c)) && ((c) <= '9')) ||
- (c == 'e') || (c == 'E') ||
- (c == '+') || (c == '-') ||
- (c == '.'));
- }
- /**
- Determine if a particular character is a space character
- @return Returns 1 if c is a space character
- **/
- int
- isspace (
- int c
- )
- {
- //
- // <space> ::= [ ]
- //
- return ((c) == ' ') || ((c) == '\t') || ((c) == '\r') || ((c) == '\n') || ((c) == '\v') || ((c) == '\f');
- }
- /**
- Allocates memory blocks
- */
- void *
- malloc (
- size_t size
- )
- {
- return AllocatePool ((UINTN)size);
- }
- /**
- De-allocates or frees a memory block
- */
- void
- free (
- void *ptr
- )
- {
- //
- // In Standard C, free() handles a null pointer argument transparently. This
- // is not true of FreePool() below, so protect it.
- //
- if (ptr != NULL) {
- FreePool (ptr);
- }
- }
- /**
- NetBSD Compatibility Function strdup creates a duplicate copy of a string.
- @return Returns the pointer to duplicated string.
- **/
- char *
- strdup (
- const char *str
- )
- {
- size_t len;
- char *copy;
- len = strlen (str) + 1;
- if ((copy = malloc (len)) == NULL) {
- return (NULL);
- }
- memcpy (copy, str, len);
- return (copy);
- }
- /** The toupper function converts a lowercase letter to a corresponding
- uppercase letter.
- @param[in] c The character to be converted.
- @return If the argument is a character for which islower is true and
- there are one or more corresponding characters, as specified by
- the current locale, for which isupper is true, the toupper
- function returns one of the corresponding characters (always the
- same one for any given locale); otherwise, the argument is
- returned unchanged.
- **/
- int
- toupper (
- IN int c
- )
- {
- if ((c >= 'a') && (c <= 'z')) {
- c = c - ('a' - 'A');
- }
- return c;
- }
- /**
- Digit to a value.
- @return Returns the value of digit.
- **/
- int
- Digit2Val (
- int c
- )
- {
- if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) {
- /* If c is one of [A-Za-z]... */
- c = toupper (c) - 7; // Adjust so 'A' is ('9' + 1)
- }
- return c - '0'; // Value returned is between 0 and 35, inclusive.
- }
- /** The strtoll function converts the initial portion of the string pointed to
- by nptr to long long int representation.
- See the description for strtol for more information.
- @return The strtoll function returns the converted value, if any. If no
- conversion could be performed, zero is returned. If the correct
- value is outside the range of representable values, LLONG_MIN or
- LLONG_MAX is returned (according to the sign of the value, if any),
- and the value of the macro ERANGE is stored in errno.
- **/
- long long
- strtoll (
- const char *nptr,
- char **endptr,
- int base
- )
- {
- const char *pEnd;
- long long Result = 0;
- long long Previous;
- int temp;
- BOOLEAN Negative = FALSE;
- pEnd = nptr;
- if ((base < 0) || (base == 1) || (base > 36)) {
- if (endptr != NULL) {
- *endptr = NULL;
- }
- return 0;
- }
- // Skip leading spaces.
- while (isspace (*nptr)) {
- ++nptr;
- }
- // Process Subject sequence: optional sign followed by digits.
- if (*nptr == '+') {
- Negative = FALSE;
- ++nptr;
- } else if (*nptr == '-') {
- Negative = TRUE;
- ++nptr;
- }
- if (*nptr == '0') {
- /* Might be Octal or Hex */
- if (toupper (nptr[1]) == 'X') {
- /* Looks like Hex */
- if ((base == 0) || (base == 16)) {
- nptr += 2; /* Skip the "0X" */
- base = 16; /* In case base was 0 */
- }
- } else {
- /* Looks like Octal */
- if ((base == 0) || (base == 8)) {
- ++nptr; /* Skip the leading "0" */
- base = 8; /* In case base was 0 */
- }
- }
- }
- if (base == 0) {
- /* If still zero then must be decimal */
- base = 10;
- }
- if (*nptr == '0') {
- for ( ; *nptr == '0'; ++nptr) {
- /* Skip any remaining leading zeros */
- }
- pEnd = nptr;
- }
- while ( isalnum (*nptr) && ((temp = Digit2Val (*nptr)) < base)) {
- Previous = Result;
- Result = MultS64x64 (Result, base) + (long long int)temp;
- if ( Result <= Previous) {
- // Detect Overflow
- if (Negative) {
- Result = LLONG_MIN;
- } else {
- Result = LLONG_MAX;
- }
- Negative = FALSE;
- errno = ERANGE;
- break;
- }
- pEnd = ++nptr;
- }
- if (Negative) {
- Result = -Result;
- }
- // Save pointer to final sequence
- if (endptr != NULL) {
- *endptr = (char *)pEnd;
- }
- return Result;
- }
- /** The strtol, strtoll, strtoul, and strtoull functions convert the initial
- portion of the string pointed to by nptr to long int, long long int,
- unsigned long int, and unsigned long long int representation, respectively.
- First, they decompose the input string into three parts: an initial,
- possibly empty, sequence of white-space characters (as specified by the
- isspace function), a subject sequence resembling an integer represented in
- some radix determined by the value of base, and a final string of one or
- more unrecognized characters, including the terminating null character of
- the input string. Then, they attempt to convert the subject sequence to an
- integer, and return the result.
- If the value of base is zero, the expected form of the subject sequence is
- that of an integer constant, optionally preceded
- by a plus or minus sign, but not including an integer suffix. If the value
- of base is between 2 and 36 (inclusive), the expected form of the subject
- sequence is a sequence of letters and digits representing an integer with
- the radix specified by base, optionally preceded by a plus or minus sign,
- but not including an integer suffix. The letters from a (or A) through z
- (or Z) are ascribed the values 10 through 35; only letters and digits whose
- ascribed values are less than that of base are permitted. If the value of
- base is 16, the characters 0x or 0X may optionally precede the sequence of
- letters and digits, following the sign if present.
- The subject sequence is defined as the longest initial subsequence of the
- input string, starting with the first non-white-space character, that is of
- the expected form. The subject sequence contains no characters if the input
- string is empty or consists entirely of white space, or if the first
- non-white-space character is other than a sign or a permissible letter or digit.
- If the subject sequence has the expected form and the value of base is
- zero, the sequence of characters starting with the first digit is
- interpreted as an integer constant. If the subject sequence has the
- expected form and the value of base is between 2 and 36, it is used as the
- base for conversion, ascribing to each letter its value as given above. If
- the subject sequence begins with a minus sign, the value resulting from the
- conversion is negated (in the return type). A pointer to the final string
- is stored in the object pointed to by endptr, provided that endptr is
- not a null pointer.
- In other than the "C" locale, additional locale-specific subject sequence
- forms may be accepted.
- If the subject sequence is empty or does not have the expected form, no
- conversion is performed; the value of nptr is stored in the object pointed
- to by endptr, provided that endptr is not a null pointer.
- @return The strtol, strtoll, strtoul, and strtoull functions return the
- converted value, if any. If no conversion could be performed, zero
- is returned. If the correct value is outside the range of
- representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX,
- ULONG_MAX, or ULLONG_MAX is returned (according to the return type
- and sign of the value, if any), and the value of the macro ERANGE
- is stored in errno.
- **/
- long
- strtol (
- const char *nptr,
- char **endptr,
- int base
- )
- {
- const char *pEnd;
- long Result = 0;
- long Previous;
- int temp;
- BOOLEAN Negative = FALSE;
- pEnd = nptr;
- if ((base < 0) || (base == 1) || (base > 36)) {
- if (endptr != NULL) {
- *endptr = NULL;
- }
- return 0;
- }
- // Skip leading spaces.
- while (isspace (*nptr)) {
- ++nptr;
- }
- // Process Subject sequence: optional sign followed by digits.
- if (*nptr == '+') {
- Negative = FALSE;
- ++nptr;
- } else if (*nptr == '-') {
- Negative = TRUE;
- ++nptr;
- }
- if (*nptr == '0') {
- /* Might be Octal or Hex */
- if (toupper (nptr[1]) == 'X') {
- /* Looks like Hex */
- if ((base == 0) || (base == 16)) {
- nptr += 2; /* Skip the "0X" */
- base = 16; /* In case base was 0 */
- }
- } else {
- /* Looks like Octal */
- if ((base == 0) || (base == 8)) {
- ++nptr; /* Skip the leading "0" */
- base = 8; /* In case base was 0 */
- }
- }
- }
- if (base == 0) {
- /* If still zero then must be decimal */
- base = 10;
- }
- if (*nptr == '0') {
- for ( ; *nptr == '0'; ++nptr) {
- /* Skip any remaining leading zeros */
- }
- pEnd = nptr;
- }
- while ( isalnum (*nptr) && ((temp = Digit2Val (*nptr)) < base)) {
- Previous = Result;
- Result = (Result * base) + (long int)temp;
- if ( Result <= Previous) {
- // Detect Overflow
- if (Negative) {
- Result = LONG_MIN;
- } else {
- Result = LONG_MAX;
- }
- Negative = FALSE;
- errno = ERANGE;
- break;
- }
- pEnd = ++nptr;
- }
- if (Negative) {
- Result = -Result;
- }
- // Save pointer to final sequence
- if (endptr != NULL) {
- *endptr = (char *)pEnd;
- }
- return Result;
- }
- /** The strtoull function converts the initial portion of the string pointed to
- by nptr to unsigned long long int representation.
- See the description for strtol for more information.
- @return The strtoull function returns the converted value, if any. If no
- conversion could be performed, zero is returned. If the correct
- value is outside the range of representable values, ULLONG_MAX is
- returned and the value of the macro ERANGE is stored in errno.
- **/
- unsigned long long
- strtoull (
- const char *nptr,
- char **endptr,
- int base
- )
- {
- const char *pEnd;
- unsigned long long Result = 0;
- unsigned long long Previous;
- int temp;
- pEnd = nptr;
- if ((base < 0) || (base == 1) || (base > 36)) {
- if (endptr != NULL) {
- *endptr = NULL;
- }
- return 0;
- }
- // Skip leading spaces.
- while (isspace (*nptr)) {
- ++nptr;
- }
- // Process Subject sequence: optional + sign followed by digits.
- if (*nptr == '+') {
- ++nptr;
- }
- if (*nptr == '0') {
- /* Might be Octal or Hex */
- if (toupper (nptr[1]) == 'X') {
- /* Looks like Hex */
- if ((base == 0) || (base == 16)) {
- nptr += 2; /* Skip the "0X" */
- base = 16; /* In case base was 0 */
- }
- } else {
- /* Looks like Octal */
- if ((base == 0) || (base == 8)) {
- ++nptr; /* Skip the leading "0" */
- base = 8; /* In case base was 0 */
- }
- }
- }
- if (base == 0) {
- /* If still zero then must be decimal */
- base = 10;
- }
- if (*nptr == '0') {
- for ( ; *nptr == '0'; ++nptr) {
- /* Skip any remaining leading zeros */
- }
- pEnd = nptr;
- }
- while ( isalnum (*nptr) && ((temp = Digit2Val (*nptr)) < base)) {
- Previous = Result;
- Result = DivU64x32 (Result, base) + (unsigned long long)temp;
- if ( Result < Previous) {
- // If we overflowed
- Result = ULLONG_MAX;
- errno = ERANGE;
- break;
- }
- pEnd = ++nptr;
- }
- // Save pointer to final sequence
- if (endptr != NULL) {
- *endptr = (char *)pEnd;
- }
- return Result;
- }
- /**
- edk2 Jansson port does not support doubles, simply return 0.
- These conversion functions convert the initial portion of the string
- pointed to by nptr to double, float, and long double representation,
- respectively.
- The strtod(), strtof(), and strtold() functions return the converted
- value, if any.
- If endptr is not NULL, a pointer to the character after the last charac-
- ter used in the conversion is stored in the location referenced by
- endptr.
- If no conversion is performed, zero is returned and the value of nptr is
- stored in the location referenced by endptr.
- If the correct value would cause overflow, plus or minus HUGE_VAL,
- HUGE_VALF, or HUGE_VALL is returned (according to the sign and type of
- the return value), and ERANGE is stored in errno. If the correct value
- would cause underflow, zero is returned and ERANGE is stored in errno.
- @return Return 0.
- **/
- double
- strtod (
- const char *__restrict nptr,
- char **__restrict endptr
- )
- {
- DEBUG ((DEBUG_INFO, "We don't supprot double type on edk2 yet!"));
- ASSERT (FALSE);
- return (double)0;
- }
- static UINT8 BitMask[] = {
- 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
- };
- #define WHICH8(c) ((unsigned char)(c) >> 3)
- #define WHICH_BIT(c) (BitMask[((c) & 0x7)])
- #define BITMAP64 ((UINT64 *)bitmap)
- static
- void
- BuildBitmap (
- unsigned char *bitmap,
- const char *s2,
- int n
- )
- {
- unsigned char bit;
- int index;
- // Initialize bitmap. Bit 0 is always 1 which corresponds to '\0'
- for (BITMAP64[0] = index = 1; index < n; index++) {
- BITMAP64[index] = 0;
- }
- // Set bits in bitmap corresponding to the characters in s2
- for ( ; *s2 != '\0'; s2++) {
- index = WHICH8 (*s2);
- bit = WHICH_BIT (*s2);
- bitmap[index] = bitmap[index] | bit;
- }
- }
- /** The strpbrk function locates the first occurrence in the string pointed to
- by s1 of any character from the string pointed to by s2.
- @return The strpbrk function returns a pointer to the character, or a
- null pointer if no character from s2 occurs in s1.
- **/
- char *
- strpbrk (
- const char *s1,
- const char *s2
- )
- {
- UINT8 bitmap[(((UCHAR_MAX + 1) / CHAR_BIT) + (CHAR_BIT - 1)) & ~7U];
- UINT8 bit;
- int index;
- BuildBitmap (bitmap, s2, sizeof (bitmap) / sizeof (UINT64));
- for ( ; *s1 != '\0'; ++s1) {
- index = WHICH8 (*s1);
- bit = WHICH_BIT (*s1);
- if ((bitmap[index] & bit) != 0) {
- return (char *)s1;
- }
- }
- return NULL;
- }
- /** The strerror function maps the number in errnum to a message string.
- Typically, the values for errnum come from errno, but strerror shall map
- any value of type int to a message.
- The implementation shall behave as if no library function calls the
- strerror function.
- @return The strerror function returns a pointer to the string, the
- contents of which are locale specific. The array pointed to
- shall not be modified by the program, but may be overwritten by
- a subsequent call to the strerror function.
- **/
- char *
- strerror (
- int errnum
- )
- {
- return errnum_message;
- }
- /**
- Allocate and zero-initialize array.
- **/
- void *
- calloc (
- size_t Num,
- size_t Size
- )
- {
- void *RetVal;
- size_t NumSize;
- NumSize = Num * Size;
- RetVal = NULL;
- if (NumSize != 0) {
- RetVal = malloc (NumSize);
- if ( RetVal != NULL) {
- (VOID)ZeroMem (RetVal, NumSize);
- }
- }
- DEBUG ((DEBUG_POOL, "0x%p = calloc(%d, %d)\n", RetVal, Num, Size));
- return RetVal;
- }
- //
- // The arrays give the cumulative number of days up to the first of the
- // month number used as the index (1 -> 12) for regular and leap years.
- // The value at index 13 is for the whole year.
- //
- UINTN CumulativeDays[2][14] = {
- {
- 0,
- 0,
- 31,
- 31 + 28,
- 31 + 28 + 31,
- 31 + 28 + 31 + 30,
- 31 + 28 + 31 + 30 + 31,
- 31 + 28 + 31 + 30 + 31 + 30,
- 31 + 28 + 31 + 30 + 31 + 30 + 31,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
- },
- {
- 0,
- 0,
- 31,
- 31 + 29,
- 31 + 29 + 31,
- 31 + 29 + 31 + 30,
- 31 + 29 + 31 + 30 + 31,
- 31 + 29 + 31 + 30 + 31 + 30,
- 31 + 29 + 31 + 30 + 31 + 30 + 31,
- 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
- 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
- 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
- 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
- 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
- }
- };
- #define IsLeap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
- #define SECSPERMIN (60)
- #define SECSPERHOUR (60 * 60)
- #define SECSPERDAY (24 * SECSPERHOUR)
- /**
- Get the system time as seconds elapsed since midnight, January 1, 1970.
- **/
- time_t
- time (
- time_t *timer
- )
- {
- EFI_TIME Time;
- time_t CalTime;
- UINTN Year;
- //
- // Get the current time and date information
- //
- gRT->GetTime (&Time, NULL);
- //
- // Years Handling
- // UTime should now be set to 00:00:00 on Jan 1 of the current year.
- //
- for (Year = 1970, CalTime = 0; Year != Time.Year; Year++) {
- CalTime = CalTime + (time_t)(CumulativeDays[IsLeap (Year)][13] * SECSPERDAY);
- }
- //
- // Add in number of seconds for current Month, Day, Hour, Minute, Seconds, and TimeZone adjustment
- //
- CalTime = CalTime +
- (time_t)((Time.TimeZone != EFI_UNSPECIFIED_TIMEZONE) ? (Time.TimeZone * 60) : 0) +
- (time_t)(CumulativeDays[IsLeap (Time.Year)][Time.Month] * SECSPERDAY) +
- (time_t)(((Time.Day > 0) ? Time.Day - 1 : 0) * SECSPERDAY) +
- (time_t)(Time.Hour * SECSPERHOUR) +
- (time_t)(Time.Minute * 60) +
- (time_t)Time.Second;
- if (timer != NULL) {
- *timer = CalTime;
- }
- return CalTime;
- }
- /**
- Performs a quick sort
- **/
- void
- qsort (
- void *base,
- size_t num,
- size_t width,
- int ( *compare )(const void *, const void *)
- )
- {
- ASSERT (base != NULL);
- ASSERT (compare != NULL);
- PerformQuickSort (base, (UINTN)num, (UINTN)width, (SORT_COMPARE)compare);
- return;
- }
- /**
- Get character from stream, we don't support file operastion on edk2 JSON library.
- @return Returns the character currently pointed by the internal file position indicator of the specified stream
- **/
- int
- fgetc (
- FILE *_File
- )
- {
- return EOF;
- }
- /**
- Open stream file, we don't support file operastion on edk2 JSON library.
- @return 0 Unsupported
- **/
- FILE *
- fopen (
- const char *filename,
- const char *mode
- )
- {
- return NULL;
- }
- /**
- Read stream from file, we don't support file operastion on edk2 JSON library.
- @return 0 Unsupported
- **/
- size_t
- fread (
- void *ptr,
- size_t size,
- size_t count,
- FILE *stream
- )
- {
- return 0;
- }
- /**
- Write stream from file, we don't support file operastion on edk2 JSON library.
- @return 0 Unsupported
- **/
- size_t
- fwrite (
- const void *ptr,
- size_t size,
- size_t count,
- FILE *stream
- )
- {
- return 0;
- }
- /**
- Close file, we don't support file operastion on edk2 JSON library.
- @return 0 Unsupported
- **/
- int
- fclose (
- FILE *stream
- )
- {
- return EOF;
- }
- /**
- Write the formatted string to file, we don't support file operastion on edk2 JSON library.
- @return 0 Unsupported
- **/
- int
- fprintf (
- FILE *stream,
- const char *format,
- ...
- )
- {
- return -1;
- }
- /**
- This function check if this is the formating string specifier.
- @param[in] FormatString A Null-terminated ASCII format string.
- @param[in,out] CurrentPosition The starting position at the given string to check for
- "[flags][width][.precision][length]s" string specifier.
- @param[in] StrLength Maximum string length.
- @return BOOLEAN TRUE means this is the formating string specifier. CurrentPosition is
- returned at the position of "s".
- FALSE means this is not the formating string specifier.. CurrentPosition is
- returned at the position of failed character.
- **/
- BOOLEAN
- CheckFormatingString (
- IN CONST CHAR8 *FormatString,
- IN OUT UINTN *CurrentPosition,
- IN UINTN StrLength
- )
- {
- CHAR8 FormatStringParamater;
- while (*(FormatString + *CurrentPosition) != 's') {
- //
- // Loop until reach character 's' if the formating string is
- // compliant with "[flags][width][.precision][length]" format for
- // the string specifier.
- //
- FormatStringParamater = *(FormatString + *CurrentPosition);
- if ((FormatStringParamater != '-') &&
- (FormatStringParamater != '+') &&
- (FormatStringParamater != '*') &&
- (FormatStringParamater != '.') &&
- !(((UINTN)FormatStringParamater >= (UINTN)'0') && ((UINTN)FormatStringParamater <= (UINTN)'9'))
- )
- {
- return FALSE;
- }
- (*CurrentPosition)++;
- if (*CurrentPosition >= StrLength) {
- return FALSE;
- }
- }
- return TRUE;
- }
- /**
- This function clones *FormatString however replaces "%s" with "%a" in the
- returned string.
- @param[in] A Null-terminated ASCII format string.
- @return The new format string. Caller has to free the memory of this string
- using FreePool().
- **/
- CHAR8 *
- ReplaceUnicodeToAsciiStrFormat (
- IN CONST CHAR8 *FormatString
- )
- {
- UINTN FormatStrSize;
- UINTN FormatStrIndex;
- UINTN FormatStrSpecifier;
- BOOLEAN PercentageMark;
- CHAR8 *TempFormatBuffer;
- BOOLEAN IsFormatString;
- //
- // Error checking.
- //
- if (FormatString == NULL) {
- return NULL;
- }
- FormatStrSize = AsciiStrSize (FormatString);
- if (FormatStrSize == 0) {
- return NULL;
- }
- TempFormatBuffer = AllocatePool (FormatStrSize); // Allocate memory for the
- // new string.
- if (TempFormatBuffer == NULL) {
- return NULL;
- }
- //
- // Clone *FormatString but replace "%s" wih "%a".
- // "%%" is not considered as the format tag.
- //
- PercentageMark = FALSE;
- FormatStrIndex = 0;
- while (FormatStrIndex < FormatStrSize) {
- if (PercentageMark == TRUE) {
- //
- // Previous character is "%".
- //
- PercentageMark = FALSE;
- if (*(FormatString + FormatStrIndex) != '%') {
- // Check if this is double "%".
- FormatStrSpecifier = FormatStrIndex;
- //
- // Check if this is the formating string specifier.
- //
- IsFormatString = CheckFormatingString (FormatString, &FormatStrSpecifier, FormatStrSize);
- if ((FormatStrSpecifier - FormatStrIndex) != 0) {
- CopyMem (
- (VOID *)(TempFormatBuffer + FormatStrIndex),
- (VOID *)(FormatString + FormatStrIndex),
- FormatStrSpecifier - FormatStrIndex
- );
- }
- FormatStrIndex = FormatStrSpecifier;
- if (IsFormatString == TRUE) {
- //
- // Replace 's' with 'a' which is printed in ASCII
- // format on edk2 environment.
- //
- *(TempFormatBuffer + FormatStrSpecifier) = 'a';
- FormatStrIndex++;
- }
- continue;
- }
- goto ContinueCheck;
- }
- if (*(FormatString + FormatStrIndex) == '%') {
- //
- // This character is "%", set the flag.
- //
- PercentageMark = TRUE;
- }
- ContinueCheck:
- //
- // Clone character to the new string and advance FormatStrIndex
- // to process next character.
- //
- *(TempFormatBuffer + FormatStrIndex) = *(FormatString + FormatStrIndex);
- FormatStrIndex++;
- }
- return TempFormatBuffer;
- }
- /**
- This is the Redfish version of CRT vsnprintf function, this function replaces "%s" to
- "%a" before invoking AsciiVSPrint(). That is because "%s" is unicode base on edk2
- environment however "%s" is ascii code base on vsnprintf().
- See definitions of AsciiVSPrint() for the details.
- @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
- ASCII string.
- @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
- @param FormatString A Null-terminated ASCII format string.
- @param Marker VA_LIST marker for the variable argument list.
- @return The number of ASCII characters in the produced output buffer not including the
- Null-terminator.
- **/
- UINTN
- EFIAPI
- RedfishAsciiVSPrint (
- OUT CHAR8 *StartOfBuffer,
- IN UINTN BufferSize,
- IN CONST CHAR8 *FormatString,
- IN VA_LIST Marker
- )
- {
- CHAR8 *TempFormatBuffer;
- UINTN LenStrProduced;
- //
- // Looking for "%s" in the format string and replace it
- // with "%a" for printing ASCII code characters on edk2
- // environment.
- //
- TempFormatBuffer = ReplaceUnicodeToAsciiStrFormat (FormatString);
- if (TempFormatBuffer == NULL) {
- return 0;
- }
- LenStrProduced = AsciiVSPrint (StartOfBuffer, BufferSize, (CONST CHAR8 *)TempFormatBuffer, Marker);
- FreePool (TempFormatBuffer);
- return LenStrProduced;
- }
- /**
- This is the Redfish version of CRT snprintf function, this function replaces "%s" to
- "%a" before invoking AsciiSPrint(). That is because "%s" is unicode base on edk2
- environment however "%s" is ascii code base on snprintf().
- See definitions of AsciiSPrint() for the details.
- @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
- ASCII string.
- @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
- @param FormatString A Null-terminated ASCII format string.
- @param ... Variable argument list whose contents are accessed based on the
- format string specified by FormatString.
- @return The number of ASCII characters in the produced output buffer not including the
- Null-terminator.
- **/
- UINTN
- EFIAPI
- RedfishAsciiSPrint (
- OUT CHAR8 *StartOfBuffer,
- IN UINTN BufferSize,
- IN CONST CHAR8 *FormatString,
- ...
- )
- {
- VA_LIST Marker;
- UINTN LenStrProduced;
- VA_START (Marker, FormatString);
- LenStrProduced = RedfishAsciiVSPrint (StartOfBuffer, BufferSize, FormatString, Marker);
- return LenStrProduced;
- }
|