Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of azure_c_shared_utility by
crt_abstractions.c
00001 // Copyright (c) Microsoft. All rights reserved. 00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 00003 00004 #define __STDC_WANT_LIB_EXT1__ 1 00005 00006 #include <stdlib.h> 00007 #include <stddef.h> 00008 #include <stdarg.h> 00009 #include <limits.h> 00010 #include <float.h> 00011 #include <math.h> 00012 #include <errno.h> 00013 #include "azure_c_shared_utility/gballoc.h" 00014 #include "azure_c_shared_utility/optimize_size.h" 00015 #include "azure_c_shared_utility/crt_abstractions.h" 00016 00017 // VS 2008 does not have INFINITY and all the nice goodies... 00018 #if defined (TIZENRT) || defined (WINCE) 00019 #define DEFINE_INFINITY 1 00020 #else 00021 00022 #if defined _MSC_VER 00023 #if _MSC_VER <= 1500 00024 #define DEFINE_INFINITY 1 00025 #endif 00026 #endif 00027 #endif 00028 00029 #if defined DEFINE_INFINITY 00030 00031 #pragma warning(disable:4756 4056) // warning C4756: overflow in constant arithmetic 00032 00033 // These defines are missing in math.h for WEC2013 SDK 00034 #ifndef _HUGE_ENUF 00035 #define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow 00036 #endif 00037 00038 #define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF)) 00039 #define HUGE_VALF ((float)INFINITY) 00040 #define HUGE_VALL ((long double)INFINITY) 00041 #define NAN ((float)(INFINITY * 0.0F)) 00042 #endif 00043 00044 #ifdef _MSC_VER 00045 #else 00046 00047 /*Codes_SRS_CRT_ABSTRACTIONS_99_008: [strcat_s shall append the src to dst and terminates the resulting string with a null character.]*/ 00048 int strcat_s(char* dst, size_t dstSizeInBytes, const char* src) 00049 { 00050 int result; 00051 /*Codes_SRS_CRT_ABSTRACTIONS_99_004: [If dst is NULL or unterminated, the error code returned shall be EINVAL & dst shall not be modified.]*/ 00052 if (dst == NULL) 00053 { 00054 result = EINVAL; 00055 } 00056 /*Codes_SRS_CRT_ABSTRACTIONS_99_005: [If src is NULL, the error code returned shall be EINVAL and dst[0] shall be set to 0.]*/ 00057 else if (src == NULL) 00058 { 00059 dst[0] = '\0'; 00060 result = EINVAL; 00061 } 00062 else 00063 { 00064 /*Codes_SRS_CRT_ABSTRACTIONS_99_006: [If the dstSizeInBytes is 0 or smaller than the required size for dst & src, the error code returned shall be ERANGE & dst[0] set to 0.]*/ 00065 if (dstSizeInBytes == 0) 00066 { 00067 result = ERANGE; 00068 dst[0] = '\0'; 00069 } 00070 else 00071 { 00072 size_t dstStrLen = 0; 00073 #ifdef __STDC_LIB_EXT1__ 00074 dstStrLen = strnlen_s(dst, dstSizeInBytes); 00075 #else 00076 size_t i; 00077 for(i=0; (i < dstSizeInBytes) && (dst[i]!= '\0'); i++) 00078 { 00079 } 00080 dstStrLen = i; 00081 #endif 00082 /*Codes_SRS_CRT_ABSTRACTIONS_99_004: [If dst is NULL or unterminated, the error code returned shall be EINVAL & dst shall not be modified.]*/ 00083 if (dstSizeInBytes == dstStrLen) /* this means the dst string is not terminated*/ 00084 { 00085 result = EINVAL; 00086 } 00087 else 00088 { 00089 /*Codes_SRS_CRT_ABSTRACTIONS_99_009: [The initial character of src shall overwrite the terminating null character of dst.]*/ 00090 (void)strncpy(&dst[dstStrLen], src, dstSizeInBytes - dstStrLen); 00091 /*Codes_SRS_CRT_ABSTRACTIONS_99_006: [If the dstSizeInBytes is 0 or smaller than the required size for dst & src, the error code returned shall be ERANGE & dst[0] set to 0.]*/ 00092 if (dst[dstSizeInBytes-1] != '\0') 00093 { 00094 dst[0] = '\0'; 00095 result = ERANGE; 00096 } 00097 else 00098 { 00099 /*Codes_SRS_CRT_ABSTRACTIONS_99_003: [strcat_s shall return Zero upon success.]*/ 00100 result = 0; 00101 } 00102 } 00103 } 00104 } 00105 00106 return result; 00107 } 00108 00109 /*Codes_SRS_CRT_ABSTRACTIONS_99_025: [strncpy_s shall copy the first N characters of src to dst, where N is the lesser of MaxCount and the length of src.]*/ 00110 int strncpy_s(char* dst, size_t dstSizeInBytes, const char* src, size_t maxCount) 00111 { 00112 int result; 00113 int truncationFlag = 0; 00114 /*Codes_SRS_CRT_ABSTRACTIONS_99_020: [If dst is NULL, the error code returned shall be EINVAL and dst shall not be modified.]*/ 00115 if (dst == NULL) 00116 { 00117 result = EINVAL; 00118 } 00119 /*Codes_SRS_CRT_ABSTRACTIONS_99_021: [If src is NULL, the error code returned shall be EINVAL and dst[0] shall be set to 0.]*/ 00120 else if (src == NULL) 00121 { 00122 dst[0] = '\0'; 00123 result = EINVAL; 00124 } 00125 /*Codes_SRS_CRT_ABSTRACTIONS_99_022: [If the dstSizeInBytes is 0, the error code returned shall be EINVAL and dst shall not be modified.]*/ 00126 else if (dstSizeInBytes == 0) 00127 { 00128 result = EINVAL; 00129 } 00130 else 00131 { 00132 size_t srcLength = strlen(src); 00133 if (maxCount != _TRUNCATE) 00134 { 00135 /*Codes_SRS_CRT_ABSTRACTIONS_99_041: [If those N characters will fit within dst (whose size is given as dstSizeInBytes) and still leave room for a null terminator, then those characters shall be copied and a terminating null is appended; otherwise, strDest[0] is set to the null character and ERANGE error code returned.]*/ 00136 if (srcLength > maxCount) 00137 { 00138 srcLength = maxCount; 00139 } 00140 00141 /*Codes_SRS_CRT_ABSTRACTIONS_99_023: [If dst is not NULL & dstSizeInBytes is smaller than the required size for the src string, the error code returned shall be ERANGE and dst[0] shall be set to 0.]*/ 00142 if (srcLength + 1 > dstSizeInBytes) 00143 { 00144 dst[0] = '\0'; 00145 result = ERANGE; 00146 } 00147 else 00148 { 00149 (void)strncpy(dst, src, srcLength); 00150 dst[srcLength] = '\0'; 00151 /*Codes_SRS_CRT_ABSTRACTIONS_99_018: [strncpy_s shall return Zero upon success]*/ 00152 result = 0; 00153 } 00154 } 00155 /*Codes_SRS_CRT_ABSTRACTIONS_99_026: [If MaxCount is _TRUNCATE (defined as -1), then as much of src as will fit into dst shall be copied while still leaving room for the terminating null to be appended.]*/ 00156 else 00157 { 00158 if (srcLength + 1 > dstSizeInBytes ) 00159 { 00160 srcLength = dstSizeInBytes - 1; 00161 truncationFlag = 1; 00162 } 00163 (void)strncpy(dst, src, srcLength); 00164 dst[srcLength] = '\0'; 00165 result = 0; 00166 } 00167 } 00168 00169 /*Codes_SRS_CRT_ABSTRACTIONS_99_019: [If truncation occurred as a result of the copy, the error code returned shall be STRUNCATE.]*/ 00170 if (truncationFlag == 1) 00171 { 00172 result = STRUNCATE; 00173 } 00174 00175 return result; 00176 } 00177 00178 /* Codes_SRS_CRT_ABSTRACTIONS_99_016: [strcpy_s shall copy the contents in the address of src, including the terminating null character, to the location that's specified by dst.]*/ 00179 int strcpy_s(char* dst, size_t dstSizeInBytes, const char* src) 00180 { 00181 int result; 00182 00183 /* Codes_SRS_CRT_ABSTRACTIONS_99_012: [If dst is NULL, the error code returned shall be EINVAL & dst shall not be modified.]*/ 00184 if (dst == NULL) 00185 { 00186 result = EINVAL; 00187 } 00188 /* Codes_SRS_CRT_ABSTRACTIONS_99_013: [If src is NULL, the error code returned shall be EINVAL and dst[0] shall be set to 0.]*/ 00189 else if (src == NULL) 00190 { 00191 dst[0] = '\0'; 00192 result = EINVAL; 00193 } 00194 /* Codes_SRS_CRT_ABSTRACTIONS_99_014: [If the dstSizeInBytes is 0 or smaller than the required size for the src string, the error code returned shall be ERANGE & dst[0] set to 0.]*/ 00195 else if (dstSizeInBytes == 0) 00196 { 00197 dst[0] = '\0'; 00198 result = ERANGE; 00199 } 00200 else 00201 { 00202 size_t neededBuffer = strlen(src); 00203 /* Codes_SRS_CRT_ABSTRACTIONS_99_014: [If the dstSizeInBytes is 0 or smaller than the required size for the src string, the error code returned shall be ERANGE & dst[0] set to 0.]*/ 00204 if (neededBuffer + 1 > dstSizeInBytes) 00205 { 00206 dst[0] = '\0'; 00207 result = ERANGE; 00208 } 00209 else 00210 { 00211 (void)memcpy(dst, src, neededBuffer + 1); 00212 /*Codes_SRS_CRT_ABSTRACTIONS_99_011: [strcpy_s shall return Zero upon success]*/ 00213 result = 0; 00214 } 00215 } 00216 00217 return result; 00218 } 00219 00220 /*Codes_SRS_CRT_ABSTRACTIONS_99_029: [The sprintf_s function shall format and store series of characters and values in dst. Each argument (if any) is converted and output according to the corresponding Format Specification in the format variable.]*/ 00221 /*Codes_SRS_CRT_ABSTRACTIONS_99_031: [A null character is appended after the last character written.]*/ 00222 int sprintf_s(char* dst, size_t dstSizeInBytes, const char* format, ...) 00223 { 00224 int result; 00225 /*Codes_SRS_CRT_ABSTRACTIONS_99_028: [If dst or format is a null pointer, sprintf_s shall return -1 and set errno to EINVAL]*/ 00226 if ((dst == NULL) || 00227 (format == NULL)) 00228 { 00229 errno = EINVAL; 00230 result = -1; 00231 } 00232 else 00233 { 00234 /*Codes_SRS_CRT_ABSTRACTIONS_99_033: [sprintf_s shall check the format string for valid formatting characters. If the check fails, the function returns -1.]*/ 00235 00236 #if defined _MSC_VER 00237 #error crt_abstractions is not provided for Microsoft Compilers 00238 #else 00239 /*not Microsoft compiler... */ 00240 #if defined (__STDC_VERSION__) || (__cplusplus) 00241 #if ( \ 00242 ((__STDC_VERSION__ == 199901L) || (__STDC_VERSION__ == 201000L) || (__STDC_VERSION__ == 201112L)) || \ 00243 (defined __cplusplus) \ 00244 ) 00245 /*C99 compiler*/ 00246 va_list args; 00247 va_start(args, format); 00248 /*Codes_SRS_CRT_ABSTRACTIONS_99_027: [sprintf_s shall return the number of characters stored in dst upon success. This number shall not include the terminating null character.]*/ 00249 result = vsnprintf(dst, dstSizeInBytes, format, args); 00250 va_end(args); 00251 00252 /*C99: Thus, the null-terminated output has been completely written if and only if the returned value is nonnegative and less than n*/ 00253 if (result < 0) 00254 { 00255 result = -1; 00256 } 00257 else if ((size_t)result >= dstSizeInBytes) 00258 { 00259 /*Codes_SRS_CRT_ABSTRACTIONS_99_034: [If the dst buffer is too small for the text being printed, then dst is set to an empty string and the function shall return -1.]*/ 00260 dst[0] = '\0'; 00261 result = -1; 00262 } 00263 else 00264 { 00265 /*do nothing, all is fine*/ 00266 } 00267 #else 00268 #error STDC_VERSION defined, but of unknown value; unable to sprinf_s, or provide own implementation 00269 #endif 00270 #else 00271 #error for STDC_VERSION undefined (assumed C89), provide own implementation of sprintf_s 00272 #endif 00273 #endif 00274 } 00275 return result; 00276 } 00277 #endif /* _MSC_VER */ 00278 00279 /*Codes_SRS_CRT_ABSTRACTIONS_21_006: [The strtoull_s must use the letters from a(or A) through z(or Z) to represent the numbers between 10 to 35.]*/ 00280 /* returns the integer value that correspond to the character 'c'. If the character is invalid, it returns -1. */ 00281 #define DIGIT_VAL(c) (((c>='0') && (c<='9')) ? (c-'0') : ((c>='a') && (c<='z')) ? (c-'a'+10) : ((c>='A') && (c<='Z')) ? (c-'A'+10) : -1) 00282 #define IN_BASE_RANGE(d, b) ((d >= 0) && (d < b)) 00283 00284 /*Codes_SRS_CRT_ABSTRACTIONS_21_010: [The white-space must be one of the characters ' ', '\f', '\n', '\r', '\t', '\v'.]*/ 00285 #define IS_SPACE(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') 00286 00287 /*Codes_SRS_CRT_ABSTRACTIONS_21_001: [The strtoull_s must convert the initial portion of the string pointed to by nptr to unsigned long long int representation.]*/ 00288 /*Codes_SRS_CRT_ABSTRACTIONS_21_002: [The strtoull_s must resembling an integer represented in some radix determined by the value of base.]*/ 00289 /*Codes_SRS_CRT_ABSTRACTIONS_21_003: [The strtoull_s must return the integer that represents the value in the initial part of the string. If any.]*/ 00290 unsigned long long strtoull_s(const char* nptr, char** endptr, int base) 00291 { 00292 unsigned long long result = 0ULL; 00293 bool validStr = true; 00294 char* runner = (char*)nptr; 00295 bool isNegative = false; 00296 int digitVal; 00297 00298 /*Codes_SRS_CRT_ABSTRACTIONS_21_005: [The strtoull_s must convert number using base 2 to 36.]*/ 00299 /*Codes_SRS_CRT_ABSTRACTIONS_21_012: [If the subject sequence is empty or does not have the expected form, the strtoull_s must not perform any conversion; the value of nptr is stored in the object pointed to by endptr, provided that endptr is not a NULL pointer.]*/ 00300 /*Codes_SRS_CRT_ABSTRACTIONS_21_013: [If no conversion could be performed, the strtoull_s returns the value 0L.]*/ 00301 /*Codes_SRS_CRT_ABSTRACTIONS_21_035: [If the nptr is NULL, the strtoull_s must **not** perform any conversion and must returns 0L; endptr must receive NULL, provided that endptr is not a NULL pointer.]*/ 00302 if (((base >= 2) || (base == 0)) && (base <= 36) && (runner != NULL)) 00303 { 00304 /*Codes_SRS_CRT_ABSTRACTIONS_21_011: [The valid sequence starts after the first non-white-space character, followed by an optional positive or negative sign, a number or a letter(depending of the base).]*/ 00305 /*Codes_SRS_CRT_ABSTRACTIONS_21_010: [The white-space must be one of the characters ' ', '\f', '\n', '\r', '\t', '\v'.]*/ 00306 while (IS_SPACE(*runner)) 00307 { 00308 runner++; 00309 } 00310 if ((*runner) == '+') 00311 { 00312 runner++; 00313 } 00314 else if ((*runner) == '-') 00315 { 00316 /*Codes_SRS_CRT_ABSTRACTIONS_21_038: [If the subject sequence starts with a negative sign, the strtoull_s will convert it to the posive representation of the negative value.]*/ 00317 isNegative = true; 00318 runner++; 00319 } 00320 00321 if ((*runner) == '0') 00322 { 00323 if ((*(runner+1) == 'x') || (*(runner+1) == 'X')) 00324 { 00325 /*Codes_SRS_CRT_ABSTRACTIONS_21_008: [If the base is 0 and '0x' or '0X' precedes the number, strtoull_s must convert to a hexadecimal (base 16).]*/ 00326 /* hexadecimal... */ 00327 if ((base == 0) || (base == 16)) 00328 { 00329 base = 16; 00330 runner += 2; 00331 } 00332 } 00333 else if((base == 0) || (base == 8)) 00334 { 00335 /*Codes_SRS_CRT_ABSTRACTIONS_21_009: [If the base is 0 and '0' precedes the number, strtoull_s must convert to an octal (base 8).]*/ 00336 /* octal... */ 00337 base = 8; 00338 runner++; 00339 } 00340 } 00341 00342 if(base == 0) 00343 { 00344 /*Codes_SRS_CRT_ABSTRACTIONS_21_007: [If the base is 0 and no special chars precedes the number, strtoull_s must convert to a decimal (base 10).]*/ 00345 /* decimal... */ 00346 base = 10; 00347 } 00348 00349 digitVal = DIGIT_VAL(*runner); 00350 if (validStr && IN_BASE_RANGE(digitVal, base)) 00351 { 00352 errno = 0; 00353 do 00354 { 00355 if (((ULLONG_MAX - digitVal) / base) < result) 00356 { 00357 /*Codes_SRS_CRT_ABSTRACTIONS_21_014: [If the correct value is outside the range, the strtoull_s returns the value ULLONG_MAX, and errno will receive the value ERANGE.]*/ 00358 /* overflow... */ 00359 result = ULLONG_MAX; 00360 errno = ERANGE; 00361 } 00362 else 00363 { 00364 result = result * base + digitVal; 00365 } 00366 runner++; 00367 digitVal = DIGIT_VAL(*runner); 00368 } while (IN_BASE_RANGE(digitVal, base)); 00369 } 00370 else 00371 { 00372 runner = (char*)nptr; 00373 } 00374 } 00375 00376 /*Codes_SRS_CRT_ABSTRACTIONS_21_004: [The strtoull_s must return in endptr a final string of one or more unrecognized characters, including the terminating null character of the input string.]*/ 00377 if (endptr != NULL) 00378 { 00379 (*endptr) = (char*)runner; 00380 } 00381 00382 /*Codes_SRS_CRT_ABSTRACTIONS_21_038: [If the subject sequence starts with a negative sign, the strtoull_s will convert it to the posive representation of the negative value.]*/ 00383 if (isNegative) 00384 { 00385 result = ULLONG_MAX - result + 1; 00386 } 00387 00388 return result; 00389 } 00390 00391 /*Codes_SRS_CRT_ABSTRACTIONS_21_023: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtof_s must return the INFINITY value for float.]*/ 00392 /*Codes_SRS_CRT_ABSTRACTIONS_21_024: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtof_s must return 0.0f and points endptr to the first character after the 'NAN' sequence.]*/ 00393 /*Codes_SRS_CRT_ABSTRACTIONS_21_033: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtold_s must return the INFINITY value for long double.]*/ 00394 /*Codes_SRS_CRT_ABSTRACTIONS_21_034: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtold_s must return 0.0 and points endptr to the first character after the 'NAN' sequence.]*/ 00395 static int substricmp(const char* nptr, const char* subsrt) 00396 { 00397 int result = 0; 00398 while (((*subsrt) != '\0') && (result == 0)) 00399 { 00400 result = TOUPPER(*nptr) - TOUPPER(*subsrt); 00401 nptr++; 00402 subsrt++; 00403 } 00404 return result; 00405 } 00406 00407 /*Codes_SRS_CRT_ABSTRACTIONS_21_023: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtof_s must return the INFINITY value for float.]*/ 00408 /*Codes_SRS_CRT_ABSTRACTIONS_21_033: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtold_s must return the INFINITY value for long double.]*/ 00409 static bool isInfinity(const char** endptr) 00410 { 00411 bool result = false; 00412 if (substricmp((*endptr), "INF") == 0) 00413 { 00414 (*endptr) += 3; 00415 result = true; 00416 if (substricmp((*endptr), "INITY") == 0) 00417 { 00418 (*endptr) += 5; 00419 } 00420 } 00421 return result; 00422 } 00423 00424 /*Codes_SRS_CRT_ABSTRACTIONS_21_024: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtof_s must return 0.0f and points endptr to the first character after the 'NAN' sequence.]*/ 00425 /*Codes_SRS_CRT_ABSTRACTIONS_21_034: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtold_s must return 0.0 and points endptr to the first character after the 'NAN' sequence.]*/ 00426 static bool isNaN(const char** endptr) 00427 { 00428 const char* runner = (*endptr); 00429 bool result = false; 00430 if (substricmp(runner, "NAN") == 0) 00431 { 00432 runner += 3; 00433 result = true; 00434 if ((*runner) == '(') 00435 { 00436 do 00437 { 00438 runner++; 00439 } while (((*runner) != '\0') && ((*runner) != ')')); 00440 if ((*runner) == ')') 00441 runner++; 00442 else 00443 result = false; 00444 } 00445 } 00446 if (result) 00447 (*endptr) = runner; 00448 return result; 00449 } 00450 00451 #define FLOAT_STRING_TYPE_VALUES \ 00452 FST_INFINITY, \ 00453 FST_NAN, \ 00454 FST_NUMBER, \ 00455 FST_OVERFLOW, \ 00456 FST_ERROR 00457 00458 DEFINE_ENUM(FLOAT_STRING_TYPE, FLOAT_STRING_TYPE_VALUES); 00459 00460 static FLOAT_STRING_TYPE splitFloatString(const char* nptr, char** endptr, int *signal, double *fraction, int *exponential) 00461 { 00462 FLOAT_STRING_TYPE result = FST_ERROR; 00463 00464 unsigned long long ullInteger = 0; 00465 unsigned long long ullFraction = 0; 00466 int integerSize = 0; 00467 int fractionSize = 0; 00468 char* startptr; 00469 00470 (*endptr) = (char*)nptr; 00471 00472 /*Codes_SRS_CRT_ABSTRACTIONS_21_018: [The white-space for strtof_s must be one of the characters ' ', '\f', '\n', '\r', '\t', '\v'.]*/ 00473 /*Codes_SRS_CRT_ABSTRACTIONS_21_028: [The white-space for strtold_s must be one of the characters ' ', '\f', '\n', '\r', '\t', '\v'.]*/ 00474 while (IS_SPACE(**endptr)) 00475 { 00476 (*endptr)++; 00477 } 00478 00479 /*Codes_SRS_CRT_ABSTRACTIONS_21_019: [The valid sequence for strtof_s starts after the first non-white - space character, followed by an optional positive or negative sign, a number, 'INF', or 'NAN' (ignoring case).]*/ 00480 /*Codes_SRS_CRT_ABSTRACTIONS_21_029: [The valid sequence for strtold_s starts after the first non-white - space character, followed by an optional positive or negative sign, a number, 'INF', or 'NAN' (ignoring case).]*/ 00481 (*signal) = +1; 00482 if ((**endptr) == '+') 00483 { 00484 (*endptr)++; 00485 } 00486 else if ((**endptr) == '-') 00487 { 00488 (*signal) = -1; 00489 (*endptr)++; 00490 } 00491 00492 /*Codes_SRS_CRT_ABSTRACTIONS_21_023: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtof_s must return the INFINITY value for float.]*/ 00493 /*Codes_SRS_CRT_ABSTRACTIONS_21_033: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtold_s must return the INFINITY value for long double.]*/ 00494 if (isInfinity((const char**)endptr)) 00495 { 00496 result = FST_INFINITY; 00497 } 00498 /*Codes_SRS_CRT_ABSTRACTIONS_21_034: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtold_s must return 0.0 and points endptr to the first character after the 'NAN' sequence.]*/ 00499 /*Codes_SRS_CRT_ABSTRACTIONS_21_024: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtof_s must return 0.0f and points endptr to the first character after the 'NAN' sequence.]*/ 00500 else if (isNaN((const char**)endptr)) 00501 { 00502 result = FST_NAN; 00503 } 00504 else if (IN_BASE_RANGE(DIGIT_VAL(**endptr), 10)) 00505 { 00506 result = FST_NUMBER; 00507 startptr = *endptr; 00508 /* integers will go to the fraction and exponential. */ 00509 ullInteger = strtoull_s(startptr, endptr, 10); 00510 integerSize = (int)((*endptr) - startptr); 00511 if ((ullInteger == ULLONG_MAX) && (errno != 0)) 00512 { 00513 result = FST_OVERFLOW; 00514 } 00515 00516 /* get the real fraction part, if exist. */ 00517 if ((**endptr) == '.') 00518 { 00519 startptr = (*endptr) + 1; 00520 ullFraction = strtoull_s(startptr, endptr, 10); 00521 fractionSize = (int)((*endptr) - startptr); 00522 if ((ullFraction == ULLONG_MAX) && (errno != 0)) 00523 { 00524 result = FST_OVERFLOW; 00525 } 00526 } 00527 00528 if (((**endptr) == 'e') || ((**endptr) == 'E')) 00529 { 00530 startptr = (*endptr) + 1; 00531 (*exponential) = strtol(startptr, endptr, 10); 00532 if (((*exponential) < (DBL_MAX_10_EXP * (-1))) || ((*exponential) > DBL_MAX_10_EXP)) 00533 { 00534 result = FST_OVERFLOW; 00535 } 00536 } 00537 else 00538 { 00539 (*exponential) = 0; 00540 } 00541 00542 if (result == FST_NUMBER) 00543 { 00544 /* Add ullInteger to ullFraction. */ 00545 ullFraction += (ullInteger * (unsigned long long)(pow(10, (double)fractionSize))); 00546 (*fraction) = ((double)ullFraction / (pow(10.0f, (double)(fractionSize + integerSize - 1)))); 00547 00548 /* Unify rest of integerSize and fractionSize in the exponential. */ 00549 (*exponential) += integerSize - 1; 00550 } 00551 } 00552 00553 return result; 00554 } 00555 00556 /*Codes_SRS_CRT_ABSTRACTIONS_21_015: [The strtof_s must convert the initial portion of the string pointed to by nptr to float representation.]*/ 00557 /*Codes_SRS_CRT_ABSTRACTIONS_21_016: [The strtof_s must return the float that represents the value in the initial part of the string. If any.]*/ 00558 float strtof_s(const char* nptr, char** endptr) 00559 { 00560 int signal = 1; 00561 double fraction; 00562 int exponential; 00563 char* runner = (char*)nptr; 00564 double val; 00565 00566 /*Codes_SRS_CRT_ABSTRACTIONS_21_021: [If no conversion could be performed, the strtof_s returns the value 0.0.]*/ 00567 float result = 0.0; 00568 00569 /*Codes_SRS_CRT_ABSTRACTIONS_21_036: [**If the nptr is NULL, the strtof_s must not perform any conversion and must returns 0.0f; endptr must receive NULL, provided that endptr is not a NULL pointer.]*/ 00570 if (nptr != NULL) 00571 { 00572 switch (splitFloatString(nptr, &runner, &signal, &fraction, &exponential)) 00573 { 00574 case FST_INFINITY: 00575 /*Codes_SRS_CRT_ABSTRACTIONS_21_023: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtof_s must return the INFINITY value for float.]*/ 00576 result = INFINITY * (signal); 00577 errno = 0; 00578 break; 00579 case FST_NAN: 00580 /*Codes_SRS_CRT_ABSTRACTIONS_21_024: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtof_s must return 0.0f and points endptr to the first character after the 'NAN' sequence.]*/ 00581 result = NAN; 00582 break; 00583 case FST_NUMBER: 00584 val = fraction * pow(10.0, (double)exponential) * (double)signal; 00585 if ((val >= (FLT_MAX * (-1))) && (val <= FLT_MAX)) 00586 { 00587 /*Codes_SRS_CRT_ABSTRACTIONS_21_016: [The strtof_s must return the float that represents the value in the initial part of the string. If any.]*/ 00588 result = (float)val; 00589 } 00590 else 00591 { 00592 /*Codes_SRS_CRT_ABSTRACTIONS_21_022: [If the correct value is outside the range, the strtof_s returns the value plus or minus HUGE_VALF, and errno will receive the value ERANGE.]*/ 00593 result = HUGE_VALF * (signal); 00594 errno = ERANGE; 00595 } 00596 break; 00597 case FST_OVERFLOW: 00598 /*Codes_SRS_CRT_ABSTRACTIONS_21_022: [If the correct value is outside the range, the strtof_s returns the value plus or minus HUGE_VALF, and errno will receive the value ERANGE.]*/ 00599 result = HUGE_VALF * (signal); 00600 errno = ERANGE; 00601 break; 00602 default: 00603 /*Codes_SRS_CRT_ABSTRACTIONS_21_020: [If the subject sequence is empty or does not have the expected form, the strtof_s must not perform any conversion and must returns 0.0f; the value of nptr is stored in the object pointed to by endptr, provided that endptr is not a NULL pointer.]*/ 00604 runner = (char*)nptr; 00605 break; 00606 } 00607 } 00608 00609 /*Codes_SRS_CRT_ABSTRACTIONS_21_017: [The strtof_s must return in endptr a final string of one or more unrecognized characters, including the terminating null character of the input string.]*/ 00610 if (endptr != NULL) 00611 { 00612 (*endptr) = runner; 00613 } 00614 00615 return result; 00616 } 00617 00618 /*Codes_SRS_CRT_ABSTRACTIONS_21_025: [The strtold_s must convert the initial portion of the string pointed to by nptr to long double representation.]*/ 00619 /*Codes_SRS_CRT_ABSTRACTIONS_21_026: [The strtold_s must return the long double that represents the value in the initial part of the string. If any.]*/ 00620 long double strtold_s(const char* nptr, char** endptr) 00621 { 00622 int signal = 1; 00623 double fraction; 00624 int exponential; 00625 char* runner = (char*)nptr; 00626 00627 /*Codes_SRS_CRT_ABSTRACTIONS_21_031: [If no conversion could be performed, the strtold_s returns the value 0.0.]*/ 00628 long double result = 0.0; 00629 00630 /*Codes_SRS_CRT_ABSTRACTIONS_21_037: [If the nptr is NULL, the strtold_s must not perform any conversion and must returns 0.0; endptr must receive NULL, provided that endptr is not a NULL pointer.]*/ 00631 if (nptr != NULL) 00632 { 00633 switch (splitFloatString(nptr, &runner, &signal, &fraction, &exponential)) 00634 { 00635 case FST_INFINITY: 00636 /*Codes_SRS_CRT_ABSTRACTIONS_21_033: [If the string is 'INF' of 'INFINITY' (ignoring case), the strtold_s must return the INFINITY value for long double.]*/ 00637 result = INFINITY * (signal); 00638 errno = 0; 00639 break; 00640 case FST_NAN: 00641 /*Codes_SRS_CRT_ABSTRACTIONS_21_034: [If the string is 'NAN' or 'NAN(...)' (ignoring case), the strtold_s must return 0.0 and points endptr to the first character after the 'NAN' sequence.]*/ 00642 result = NAN; 00643 break; 00644 case FST_NUMBER: 00645 if ((exponential != DBL_MAX_10_EXP || (fraction <= 1.7976931348623158)) && 00646 (exponential != (DBL_MAX_10_EXP * (-1)) || (fraction <= 2.2250738585072014))) 00647 { 00648 /*Codes_SRS_CRT_ABSTRACTIONS_21_026: [The strtold_s must return the long double that represents the value in the initial part of the string. If any.]*/ 00649 result = fraction * pow(10.0, (double)exponential) * (double)signal; 00650 } 00651 else 00652 { 00653 /*Codes_SRS_CRT_ABSTRACTIONS_21_032: [If the correct value is outside the range, the strtold_s returns the value plus or minus HUGE_VALL, and errno will receive the value ERANGE.]*/ 00654 result = HUGE_VALF * (signal); 00655 errno = ERANGE; 00656 } 00657 break; 00658 case FST_OVERFLOW: 00659 /*Codes_SRS_CRT_ABSTRACTIONS_21_032: [If the correct value is outside the range, the strtold_s returns the value plus or minus HUGE_VALL, and errno will receive the value ERANGE.]*/ 00660 result = HUGE_VALF * (signal); 00661 errno = ERANGE; 00662 break; 00663 default: 00664 /*Codes_SRS_CRT_ABSTRACTIONS_21_030: [If the subject sequence is empty or does not have the expected form, the strtold_s must not perform any conversion and must returns 0.0; the value of nptr is stored in the object pointed to by endptr, provided that endptr is not a NULL pointer.]*/ 00665 runner = (char*)nptr; 00666 break; 00667 } 00668 } 00669 00670 /*Codes_SRS_CRT_ABSTRACTIONS_21_027: [The strtold_s must return in endptr a final string of one or more unrecognized characters, including the terminating null character of the input string.]*/ 00671 if (endptr != NULL) 00672 { 00673 (*endptr) = runner; 00674 } 00675 00676 return result; 00677 } 00678 00679 00680 /*Codes_SRS_CRT_ABSTRACTIONS_99_038: [mallocAndstrcpy_s shall allocate memory for destination buffer to fit the string in the source parameter.]*/ 00681 int mallocAndStrcpy_s(char** destination, const char* source) 00682 { 00683 int result; 00684 int copied_result; 00685 /*Codes_SRS_CRT_ABSTRACTIONS_99_036: [destination parameter or source parameter is NULL, the error code returned shall be EINVAL and destination shall not be modified.]*/ 00686 if ((destination == NULL) || (source == NULL)) 00687 { 00688 /*If strDestination or strSource is a NULL pointer[...]these functions return EINVAL */ 00689 result = EINVAL; 00690 } 00691 else 00692 { 00693 size_t l = strlen(source); 00694 char* temp = (char*)malloc(l + 1); 00695 00696 /*Codes_SRS_CRT_ABSTRACTIONS_99_037: [Upon failure to allocate memory for the destination, the function will return ENOMEM.]*/ 00697 if (temp == NULL) 00698 { 00699 result = ENOMEM; 00700 } 00701 else 00702 { 00703 *destination = temp; 00704 /*Codes_SRS_CRT_ABSTRACTIONS_99_039: [mallocAndstrcpy_s shall copy the contents in the address source, including the terminating null character into location specified by the destination pointer after the memory allocation.]*/ 00705 copied_result = strcpy_s(*destination, l + 1, source); 00706 if (copied_result < 0) /*strcpy_s error*/ 00707 { 00708 free(*destination); 00709 *destination = NULL; 00710 result = copied_result; 00711 } 00712 else 00713 { 00714 /*Codes_SRS_CRT_ABSTRACTIONS_99_035: [mallocAndstrcpy_s shall return Zero upon success]*/ 00715 result = 0; 00716 } 00717 } 00718 } 00719 return result; 00720 } 00721 00722 /*takes "value" and transforms it into a decimal string*/ 00723 /*10 => "10"*/ 00724 /*return 0 when everything went ok*/ 00725 /*Codes_SRS_CRT_ABSTRACTIONS_02_001: [unsignedIntToString shall convert the parameter value to its decimal representation as a string in the buffer indicated by parameter destination having the size indicated by parameter destinationSize.] */ 00726 int unsignedIntToString(char* destination, size_t destinationSize, unsigned int value) 00727 { 00728 int result; 00729 size_t pos; 00730 /*the below loop gets the number in reverse order*/ 00731 /*Codes_SRS_CRT_ABSTRACTIONS_02_003: [If destination is NULL then unsignedIntToString shall fail.] */ 00732 /*Codes_SRS_CRT_ABSTRACTIONS_02_002: [If the conversion fails for any reason (for example, insufficient buffer space), a non-zero return value shall be supplied and unsignedIntToString shall fail.] */ 00733 if ( 00734 (destination == NULL) || 00735 (destinationSize < 2) /*because the smallest number is '0\0' which requires 2 characters*/ 00736 ) 00737 { 00738 result = __FAILURE__; 00739 } 00740 else 00741 { 00742 pos = 0; 00743 do 00744 { 00745 destination[pos++] = '0' + (value % 10); 00746 value /= 10; 00747 } while ((value > 0) && (pos < (destinationSize-1))); 00748 00749 if (value == 0) 00750 { 00751 size_t w; 00752 destination[pos] = '\0'; 00753 /*all converted and they fit*/ 00754 for (w = 0; w <= (pos-1) >> 1; w++) 00755 { 00756 char temp; 00757 temp = destination[w]; 00758 destination[w] = destination[pos - 1 - w]; 00759 destination[pos -1 - w] = temp; 00760 } 00761 /*Codes_SRS_CRT_ABSTRACTIONS_02_004: [If the conversion has been successfull then unsignedIntToString shall return 0.] */ 00762 result = 0; 00763 } 00764 else 00765 { 00766 /*Codes_SRS_CRT_ABSTRACTIONS_02_002: [If the conversion fails for any reason (for example, insufficient buffer space), a non-zero return value shall be supplied and unsignedIntToString shall fail.] */ 00767 result = __FAILURE__; 00768 } 00769 } 00770 return result; 00771 } 00772 00773 /*takes "value" and transforms it into a decimal string*/ 00774 /*10 => "10"*/ 00775 /*return 0 when everything went ok*/ 00776 /*Codes_SRS_CRT_ABSTRACTIONS_02_001: [unsignedIntToString shall convert the parameter value to its decimal representation as a string in the buffer indicated by parameter destination having the size indicated by parameter destinationSize.] */ 00777 int size_tToString(char* destination, size_t destinationSize, size_t value) 00778 { 00779 int result; 00780 size_t pos; 00781 /*the below loop gets the number in reverse order*/ 00782 /*Codes_SRS_CRT_ABSTRACTIONS_02_003: [If destination is NULL then unsignedIntToString shall fail.] */ 00783 /*Codes_SRS_CRT_ABSTRACTIONS_02_002: [If the conversion fails for any reason (for example, insufficient buffer space), a non-zero return value shall be supplied and unsignedIntToString shall fail.] */ 00784 if ( 00785 (destination == NULL) || 00786 (destinationSize < 2) /*because the smallest number is '0\0' which requires 2 characters*/ 00787 ) 00788 { 00789 result = __FAILURE__; 00790 } 00791 else 00792 { 00793 pos = 0; 00794 do 00795 { 00796 destination[pos++] = '0' + (value % 10); 00797 value /= 10; 00798 } while ((value > 0) && (pos < (destinationSize - 1))); 00799 00800 if (value == 0) 00801 { 00802 size_t w; 00803 destination[pos] = '\0'; 00804 /*all converted and they fit*/ 00805 for (w = 0; w <= (pos - 1) >> 1; w++) 00806 { 00807 char temp; 00808 temp = destination[w]; 00809 destination[w] = destination[pos - 1 - w]; 00810 destination[pos - 1 - w] = temp; 00811 } 00812 /*Codes_SRS_CRT_ABSTRACTIONS_02_004: [If the conversion has been successfull then unsignedIntToString shall return 0.] */ 00813 result = 0; 00814 } 00815 else 00816 { 00817 /*Codes_SRS_CRT_ABSTRACTIONS_02_002: [If the conversion fails for any reason (for example, insufficient buffer space), a non-zero return value shall be supplied and unsignedIntToString shall fail.] */ 00818 result = __FAILURE__; 00819 } 00820 } 00821 return result; 00822 }
Generated on Tue Jul 12 2022 19:14:38 by
