Mark Radbourne / Mbed 2 deprecated iothub_client_sample_amqp

Dependencies:   EthernetInterface NTPClient iothub_amqp_transport iothub_client mbed-rtos mbed

Fork of iothub_client_sample_amqp by Azure IoT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers crt_abstractions.c Source File

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 }