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