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