WIP. send a large constant string twice a second, in order to test out the transport with something indicative of our required load.

Dependencies:   FXOS8700CQ NTPClient azure_umqtt_c iothub_mqtt_transport mbed-rtos mbed wolfSSL Socket lwip-eth lwip-sys lwip

Fork of FXOS8700CQ_To_Azure_IoT by Mark Radbourne

Committer:
julianhigginson
Date:
Thu Jan 05 23:40:24 2017 +0000
Revision:
7:0d1a0fe537dc
Parent:
3:c0556ff7b8e3
modified dummy message for minimal data transport

Who changed what in which revision?

UserRevisionLine numberNew contents of line
markrad 3:c0556ff7b8e3 1 // Copyright (c) Microsoft. All rights reserved.
markrad 3:c0556ff7b8e3 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
markrad 3:c0556ff7b8e3 3
markrad 3:c0556ff7b8e3 4 #define __STDC_WANT_LIB_EXT1__ 1
markrad 3:c0556ff7b8e3 5
markrad 3:c0556ff7b8e3 6 #include <stdlib.h>
markrad 3:c0556ff7b8e3 7 #ifdef _CRTDBG_MAP_ALLOC
markrad 3:c0556ff7b8e3 8 #include <crtdbg.h>
markrad 3:c0556ff7b8e3 9 #endif
markrad 3:c0556ff7b8e3 10 #include "azure_c_shared_utility/gballoc.h"
markrad 3:c0556ff7b8e3 11
markrad 3:c0556ff7b8e3 12 #include "azure_c_shared_utility/crt_abstractions.h"
markrad 3:c0556ff7b8e3 13 #include "errno.h"
markrad 3:c0556ff7b8e3 14 #include <stddef.h>
markrad 3:c0556ff7b8e3 15 #include <limits.h>
markrad 3:c0556ff7b8e3 16 #include <float.h>
markrad 3:c0556ff7b8e3 17 #include <math.h>
markrad 3:c0556ff7b8e3 18
markrad 3:c0556ff7b8e3 19
markrad 3:c0556ff7b8e3 20 #ifdef WINCE
markrad 3:c0556ff7b8e3 21 #pragma warning(disable:4756) // warning C4756: overflow in constant arithmetic
markrad 3:c0556ff7b8e3 22
markrad 3:c0556ff7b8e3 23 // These defines are missing in math.h for WEC2013 SDK
markrad 3:c0556ff7b8e3 24 #ifndef _HUGE_ENUF
markrad 3:c0556ff7b8e3 25 #define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow
markrad 3:c0556ff7b8e3 26 #endif
markrad 3:c0556ff7b8e3 27
markrad 3:c0556ff7b8e3 28 #define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF))
markrad 3:c0556ff7b8e3 29 #define HUGE_VALF ((float)INFINITY)
markrad 3:c0556ff7b8e3 30 #define HUGE_VALL ((long double)INFINITY)
markrad 3:c0556ff7b8e3 31 #define NAN ((float)(INFINITY * 0.0F))
markrad 3:c0556ff7b8e3 32 #endif
markrad 3:c0556ff7b8e3 33
markrad 3:c0556ff7b8e3 34
markrad 3:c0556ff7b8e3 35
markrad 3:c0556ff7b8e3 36 #ifdef _MSC_VER
markrad 3:c0556ff7b8e3 37 #else
markrad 3:c0556ff7b8e3 38
markrad 3:c0556ff7b8e3 39 #include <stdarg.h>
markrad 3:c0556ff7b8e3 40
markrad 3:c0556ff7b8e3 41 /*Codes_SRS_CRT_ABSTRACTIONS_99_008: [strcat_s shall append the src to dst and terminates the resulting string with a null character.]*/
markrad 3:c0556ff7b8e3 42 int strcat_s(char* dst, size_t dstSizeInBytes, const char* src)
markrad 3:c0556ff7b8e3 43 {
markrad 3:c0556ff7b8e3 44 int result;
markrad 3:c0556ff7b8e3 45 /*Codes_SRS_CRT_ABSTRACTIONS_99_004: [If dst is NULL or unterminated, the error code returned shall be EINVAL & dst shall not be modified.]*/
markrad 3:c0556ff7b8e3 46 if (dst == NULL)
markrad 3:c0556ff7b8e3 47 {
markrad 3:c0556ff7b8e3 48 result = EINVAL;
markrad 3:c0556ff7b8e3 49 }
markrad 3:c0556ff7b8e3 50 /*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.]*/
markrad 3:c0556ff7b8e3 51 else if (src == NULL)
markrad 3:c0556ff7b8e3 52 {
markrad 3:c0556ff7b8e3 53 dst[0] = '\0';
markrad 3:c0556ff7b8e3 54 result = EINVAL;
markrad 3:c0556ff7b8e3 55 }
markrad 3:c0556ff7b8e3 56 else
markrad 3:c0556ff7b8e3 57 {
markrad 3:c0556ff7b8e3 58 /*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.]*/
markrad 3:c0556ff7b8e3 59 if (dstSizeInBytes == 0)
markrad 3:c0556ff7b8e3 60 {
markrad 3:c0556ff7b8e3 61 result = ERANGE;
markrad 3:c0556ff7b8e3 62 dst[0] = '\0';
markrad 3:c0556ff7b8e3 63 }
markrad 3:c0556ff7b8e3 64 else
markrad 3:c0556ff7b8e3 65 {
markrad 3:c0556ff7b8e3 66 size_t dstStrLen = 0;
markrad 3:c0556ff7b8e3 67 #ifdef __STDC_LIB_EXT1__
markrad 3:c0556ff7b8e3 68 dstStrLen = strnlen_s(dst, dstSizeInBytes);
markrad 3:c0556ff7b8e3 69 #else
markrad 3:c0556ff7b8e3 70 size_t i;
markrad 3:c0556ff7b8e3 71 for(i=0; (i < dstSizeInBytes) && (dst[i]!= '\0'); i++)
markrad 3:c0556ff7b8e3 72 {
markrad 3:c0556ff7b8e3 73 }
markrad 3:c0556ff7b8e3 74 dstStrLen = i;
markrad 3:c0556ff7b8e3 75 #endif
markrad 3:c0556ff7b8e3 76 /*Codes_SRS_CRT_ABSTRACTIONS_99_004: [If dst is NULL or unterminated, the error code returned shall be EINVAL & dst shall not be modified.]*/
markrad 3:c0556ff7b8e3 77 if (dstSizeInBytes == dstStrLen) /* this means the dst string is not terminated*/
markrad 3:c0556ff7b8e3 78 {
markrad 3:c0556ff7b8e3 79 result = EINVAL;
markrad 3:c0556ff7b8e3 80 }
markrad 3:c0556ff7b8e3 81 else
markrad 3:c0556ff7b8e3 82 {
markrad 3:c0556ff7b8e3 83 /*Codes_SRS_CRT_ABSTRACTIONS_99_009: [The initial character of src shall overwrite the terminating null character of dst.]*/
markrad 3:c0556ff7b8e3 84 (void)strncpy(&dst[dstStrLen], src, dstSizeInBytes - dstStrLen);
markrad 3:c0556ff7b8e3 85 /*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.]*/
markrad 3:c0556ff7b8e3 86 if (dst[dstSizeInBytes-1] != '\0')
markrad 3:c0556ff7b8e3 87 {
markrad 3:c0556ff7b8e3 88 dst[0] = '\0';
markrad 3:c0556ff7b8e3 89 result = ERANGE;
markrad 3:c0556ff7b8e3 90 }
markrad 3:c0556ff7b8e3 91 else
markrad 3:c0556ff7b8e3 92 {
markrad 3:c0556ff7b8e3 93 /*Codes_SRS_CRT_ABSTRACTIONS_99_003: [strcat_s shall return Zero upon success.]*/
markrad 3:c0556ff7b8e3 94 result = 0;
markrad 3:c0556ff7b8e3 95 }
markrad 3:c0556ff7b8e3 96 }
markrad 3:c0556ff7b8e3 97 }
markrad 3:c0556ff7b8e3 98 }
markrad 3:c0556ff7b8e3 99
markrad 3:c0556ff7b8e3 100 return result;
markrad 3:c0556ff7b8e3 101 }
markrad 3:c0556ff7b8e3 102
markrad 3:c0556ff7b8e3 103 /*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.]*/
markrad 3:c0556ff7b8e3 104 int strncpy_s(char* dst, size_t dstSizeInBytes, const char* src, size_t maxCount)
markrad 3:c0556ff7b8e3 105 {
markrad 3:c0556ff7b8e3 106 int result;
markrad 3:c0556ff7b8e3 107 int truncationFlag = 0;
markrad 3:c0556ff7b8e3 108 /*Codes_SRS_CRT_ABSTRACTIONS_99_020: [If dst is NULL, the error code returned shall be EINVAL and dst shall not be modified.]*/
markrad 3:c0556ff7b8e3 109 if (dst == NULL)
markrad 3:c0556ff7b8e3 110 {
markrad 3:c0556ff7b8e3 111 result = EINVAL;
markrad 3:c0556ff7b8e3 112 }
markrad 3:c0556ff7b8e3 113 /*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.]*/
markrad 3:c0556ff7b8e3 114 else if (src == NULL)
markrad 3:c0556ff7b8e3 115 {
markrad 3:c0556ff7b8e3 116 dst[0] = '\0';
markrad 3:c0556ff7b8e3 117 result = EINVAL;
markrad 3:c0556ff7b8e3 118 }
markrad 3:c0556ff7b8e3 119 /*Codes_SRS_CRT_ABSTRACTIONS_99_022: [If the dstSizeInBytes is 0, the error code returned shall be EINVAL and dst shall not be modified.]*/
markrad 3:c0556ff7b8e3 120 else if (dstSizeInBytes == 0)
markrad 3:c0556ff7b8e3 121 {
markrad 3:c0556ff7b8e3 122 result = EINVAL;
markrad 3:c0556ff7b8e3 123 }
markrad 3:c0556ff7b8e3 124 else
markrad 3:c0556ff7b8e3 125 {
markrad 3:c0556ff7b8e3 126 size_t srcLength = strlen(src);
markrad 3:c0556ff7b8e3 127 if (maxCount != _TRUNCATE)
markrad 3:c0556ff7b8e3 128 {
markrad 3:c0556ff7b8e3 129 /*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.]*/
markrad 3:c0556ff7b8e3 130 if (srcLength > maxCount)
markrad 3:c0556ff7b8e3 131 {
markrad 3:c0556ff7b8e3 132 srcLength = maxCount;
markrad 3:c0556ff7b8e3 133 }
markrad 3:c0556ff7b8e3 134
markrad 3:c0556ff7b8e3 135 /*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.]*/
markrad 3:c0556ff7b8e3 136 if (srcLength + 1 > dstSizeInBytes)
markrad 3:c0556ff7b8e3 137 {
markrad 3:c0556ff7b8e3 138 dst[0] = '\0';
markrad 3:c0556ff7b8e3 139 result = ERANGE;
markrad 3:c0556ff7b8e3 140 }
markrad 3:c0556ff7b8e3 141 else
markrad 3:c0556ff7b8e3 142 {
markrad 3:c0556ff7b8e3 143 (void)strncpy(dst, src, srcLength);
markrad 3:c0556ff7b8e3 144 dst[srcLength] = '\0';
markrad 3:c0556ff7b8e3 145 /*Codes_SRS_CRT_ABSTRACTIONS_99_018: [strncpy_s shall return Zero upon success]*/
markrad 3:c0556ff7b8e3 146 result = 0;
markrad 3:c0556ff7b8e3 147 }
markrad 3:c0556ff7b8e3 148 }
markrad 3:c0556ff7b8e3 149 /*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.]*/
markrad 3:c0556ff7b8e3 150 else
markrad 3:c0556ff7b8e3 151 {
markrad 3:c0556ff7b8e3 152 if (srcLength + 1 > dstSizeInBytes )
markrad 3:c0556ff7b8e3 153 {
markrad 3:c0556ff7b8e3 154 srcLength = dstSizeInBytes - 1;
markrad 3:c0556ff7b8e3 155 truncationFlag = 1;
markrad 3:c0556ff7b8e3 156 }
markrad 3:c0556ff7b8e3 157 (void)strncpy(dst, src, srcLength);
markrad 3:c0556ff7b8e3 158 dst[srcLength] = '\0';
markrad 3:c0556ff7b8e3 159 result = 0;
markrad 3:c0556ff7b8e3 160 }
markrad 3:c0556ff7b8e3 161 }
markrad 3:c0556ff7b8e3 162
markrad 3:c0556ff7b8e3 163 /*Codes_SRS_CRT_ABSTRACTIONS_99_019: [If truncation occurred as a result of the copy, the error code returned shall be STRUNCATE.]*/
markrad 3:c0556ff7b8e3 164 if (truncationFlag == 1)
markrad 3:c0556ff7b8e3 165 {
markrad 3:c0556ff7b8e3 166 result = STRUNCATE;
markrad 3:c0556ff7b8e3 167 }
markrad 3:c0556ff7b8e3 168
markrad 3:c0556ff7b8e3 169 return result;
markrad 3:c0556ff7b8e3 170 }
markrad 3:c0556ff7b8e3 171
markrad 3:c0556ff7b8e3 172 /* 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.]*/
markrad 3:c0556ff7b8e3 173 int strcpy_s(char* dst, size_t dstSizeInBytes, const char* src)
markrad 3:c0556ff7b8e3 174 {
markrad 3:c0556ff7b8e3 175 int result;
markrad 3:c0556ff7b8e3 176
markrad 3:c0556ff7b8e3 177 /* Codes_SRS_CRT_ABSTRACTIONS_99_012: [If dst is NULL, the error code returned shall be EINVAL & dst shall not be modified.]*/
markrad 3:c0556ff7b8e3 178 if (dst == NULL)
markrad 3:c0556ff7b8e3 179 {
markrad 3:c0556ff7b8e3 180 result = EINVAL;
markrad 3:c0556ff7b8e3 181 }
markrad 3:c0556ff7b8e3 182 /* 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.]*/
markrad 3:c0556ff7b8e3 183 else if (src == NULL)
markrad 3:c0556ff7b8e3 184 {
markrad 3:c0556ff7b8e3 185 dst[0] = '\0';
markrad 3:c0556ff7b8e3 186 result = EINVAL;
markrad 3:c0556ff7b8e3 187 }
markrad 3:c0556ff7b8e3 188 /* 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.]*/
markrad 3:c0556ff7b8e3 189 else if (dstSizeInBytes == 0)
markrad 3:c0556ff7b8e3 190 {
markrad 3:c0556ff7b8e3 191 dst[0] = '\0';
markrad 3:c0556ff7b8e3 192 result = ERANGE;
markrad 3:c0556ff7b8e3 193 }
markrad 3:c0556ff7b8e3 194 else
markrad 3:c0556ff7b8e3 195 {
markrad 3:c0556ff7b8e3 196 size_t neededBuffer = strlen(src);
markrad 3:c0556ff7b8e3 197 /* 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.]*/
markrad 3:c0556ff7b8e3 198 if (neededBuffer + 1 > dstSizeInBytes)
markrad 3:c0556ff7b8e3 199 {
markrad 3:c0556ff7b8e3 200 dst[0] = '\0';
markrad 3:c0556ff7b8e3 201 result = ERANGE;
markrad 3:c0556ff7b8e3 202 }
markrad 3:c0556ff7b8e3 203 else
markrad 3:c0556ff7b8e3 204 {
markrad 3:c0556ff7b8e3 205 memcpy(dst, src, neededBuffer + 1);
markrad 3:c0556ff7b8e3 206 /*Codes_SRS_CRT_ABSTRACTIONS_99_011: [strcpy_s shall return Zero upon success]*/
markrad 3:c0556ff7b8e3 207 result = 0;
markrad 3:c0556ff7b8e3 208 }
markrad 3:c0556ff7b8e3 209 }
markrad 3:c0556ff7b8e3 210
markrad 3:c0556ff7b8e3 211 return result;
markrad 3:c0556ff7b8e3 212 }
markrad 3:c0556ff7b8e3 213
markrad 3:c0556ff7b8e3 214 /*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.]*/
markrad 3:c0556ff7b8e3 215 /*Codes_SRS_CRT_ABSTRACTIONS_99_031: [A null character is appended after the last character written.]*/
markrad 3:c0556ff7b8e3 216 int sprintf_s(char* dst, size_t dstSizeInBytes, const char* format, ...)
markrad 3:c0556ff7b8e3 217 {
markrad 3:c0556ff7b8e3 218 int result;
markrad 3:c0556ff7b8e3 219 /*Codes_SRS_CRT_ABSTRACTIONS_99_028: [If dst or format is a null pointer, sprintf_s shall return -1 and set errno to EINVAL]*/
markrad 3:c0556ff7b8e3 220 if ((dst == NULL) ||
markrad 3:c0556ff7b8e3 221 (format == NULL))
markrad 3:c0556ff7b8e3 222 {
markrad 3:c0556ff7b8e3 223 errno = EINVAL;
markrad 3:c0556ff7b8e3 224 result = -1;
markrad 3:c0556ff7b8e3 225 }
markrad 3:c0556ff7b8e3 226 else
markrad 3:c0556ff7b8e3 227 {
markrad 3:c0556ff7b8e3 228 /*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.]*/
markrad 3:c0556ff7b8e3 229
markrad 3:c0556ff7b8e3 230 #if defined _MSC_VER
markrad 3:c0556ff7b8e3 231 #error crt_abstractions is not provided for Microsoft Compilers
markrad 3:c0556ff7b8e3 232 #else
markrad 3:c0556ff7b8e3 233 /*not Microsoft compiler... */
markrad 3:c0556ff7b8e3 234 #if defined (__STDC_VERSION__) || (__cplusplus)
markrad 3:c0556ff7b8e3 235 #if ( \
markrad 3:c0556ff7b8e3 236 ((__STDC_VERSION__ == 199901L) || (__STDC_VERSION__ == 201000L) || (__STDC_VERSION__ == 201112L)) || \
markrad 3:c0556ff7b8e3 237 (defined __cplusplus) \
markrad 3:c0556ff7b8e3 238 )
markrad 3:c0556ff7b8e3 239 /*C99 compiler*/
markrad 3:c0556ff7b8e3 240 va_list args;
markrad 3:c0556ff7b8e3 241 va_start(args, format);
markrad 3:c0556ff7b8e3 242 /*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.]*/
markrad 3:c0556ff7b8e3 243 result = vsnprintf(dst, dstSizeInBytes, format, args);
markrad 3:c0556ff7b8e3 244 va_end(args);
markrad 3:c0556ff7b8e3 245
markrad 3:c0556ff7b8e3 246 /*C99: Thus, the null-terminated output has been completely written if and only if the returned value is nonnegative and less than n*/
markrad 3:c0556ff7b8e3 247 if (result < 0)
markrad 3:c0556ff7b8e3 248 {
markrad 3:c0556ff7b8e3 249 result = -1;
markrad 3:c0556ff7b8e3 250 }
markrad 3:c0556ff7b8e3 251 else if ((size_t)result >= dstSizeInBytes)
markrad 3:c0556ff7b8e3 252 {
markrad 3:c0556ff7b8e3 253 /*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.]*/
markrad 3:c0556ff7b8e3 254 dst[0] = '\0';
markrad 3:c0556ff7b8e3 255 result = -1;
markrad 3:c0556ff7b8e3 256 }
markrad 3:c0556ff7b8e3 257 else
markrad 3:c0556ff7b8e3 258 {
markrad 3:c0556ff7b8e3 259 /*do nothing, all is fine*/
markrad 3:c0556ff7b8e3 260 }
markrad 3:c0556ff7b8e3 261 #else
markrad 3:c0556ff7b8e3 262 #error STDC_VERSION defined, but of unknown value; unable to sprinf_s, or provide own implementation
markrad 3:c0556ff7b8e3 263 #endif
markrad 3:c0556ff7b8e3 264 #else
markrad 3:c0556ff7b8e3 265 #error for STDC_VERSION undefined (assumed C89), provide own implementation of sprintf_s
markrad 3:c0556ff7b8e3 266 #endif
markrad 3:c0556ff7b8e3 267 #endif
markrad 3:c0556ff7b8e3 268 }
markrad 3:c0556ff7b8e3 269 return result;
markrad 3:c0556ff7b8e3 270 }
markrad 3:c0556ff7b8e3 271 #endif /* _MSC_VER */
markrad 3:c0556ff7b8e3 272
markrad 3:c0556ff7b8e3 273 /*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.]*/
markrad 3:c0556ff7b8e3 274 /* returns the integer value that correspond to the character 'c'. If the character is invalid, it returns -1. */
markrad 3:c0556ff7b8e3 275 #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)
markrad 3:c0556ff7b8e3 276 #define IN_BASE_RANGE(d, b) ((d >= 0) && (d < b))
markrad 3:c0556ff7b8e3 277
markrad 3:c0556ff7b8e3 278 /*Codes_SRS_CRT_ABSTRACTIONS_21_010: [The white-space must be one of the characters ' ', '\f', '\n', '\r', '\t', '\v'.]*/
markrad 3:c0556ff7b8e3 279 #define IS_SPACE(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
markrad 3:c0556ff7b8e3 280
markrad 3:c0556ff7b8e3 281 /*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.]*/
markrad 3:c0556ff7b8e3 282 /*Codes_SRS_CRT_ABSTRACTIONS_21_002: [The strtoull_s must resembling an integer represented in some radix determined by the value of base.]*/
markrad 3:c0556ff7b8e3 283 /*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.]*/
markrad 3:c0556ff7b8e3 284 unsigned long long strtoull_s(const char* nptr, char** endptr, int base)
markrad 3:c0556ff7b8e3 285 {
markrad 3:c0556ff7b8e3 286 unsigned long long result = 0ULL;
markrad 3:c0556ff7b8e3 287 bool validStr = true;
markrad 3:c0556ff7b8e3 288 char* runner = (char*)nptr;
markrad 3:c0556ff7b8e3 289 bool isNegative = false;
markrad 3:c0556ff7b8e3 290 int digitVal;
markrad 3:c0556ff7b8e3 291
markrad 3:c0556ff7b8e3 292 /*Codes_SRS_CRT_ABSTRACTIONS_21_005: [The strtoull_s must convert number using base 2 to 36.]*/
markrad 3:c0556ff7b8e3 293 /*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.]*/
markrad 3:c0556ff7b8e3 294 /*Codes_SRS_CRT_ABSTRACTIONS_21_013: [If no conversion could be performed, the strtoull_s returns the value 0L.]*/
markrad 3:c0556ff7b8e3 295 /*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.]*/
markrad 3:c0556ff7b8e3 296 if (((base >= 2) || (base == 0)) && (base <= 36) && (runner != NULL))
markrad 3:c0556ff7b8e3 297 {
markrad 3:c0556ff7b8e3 298 /*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).]*/
markrad 3:c0556ff7b8e3 299 /*Codes_SRS_CRT_ABSTRACTIONS_21_010: [The white-space must be one of the characters ' ', '\f', '\n', '\r', '\t', '\v'.]*/
markrad 3:c0556ff7b8e3 300 while (IS_SPACE(*runner))
markrad 3:c0556ff7b8e3 301 {
markrad 3:c0556ff7b8e3 302 runner++;
markrad 3:c0556ff7b8e3 303 }
markrad 3:c0556ff7b8e3 304 if ((*runner) == '+')
markrad 3:c0556ff7b8e3 305 {
markrad 3:c0556ff7b8e3 306 runner++;
markrad 3:c0556ff7b8e3 307 }
markrad 3:c0556ff7b8e3 308 else if ((*runner) == '-')
markrad 3:c0556ff7b8e3 309 {
markrad 3:c0556ff7b8e3 310 /*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.]*/
markrad 3:c0556ff7b8e3 311 isNegative = true;
markrad 3:c0556ff7b8e3 312 runner++;
markrad 3:c0556ff7b8e3 313 }
markrad 3:c0556ff7b8e3 314
markrad 3:c0556ff7b8e3 315 if ((*runner) == '0')
markrad 3:c0556ff7b8e3 316 {
markrad 3:c0556ff7b8e3 317 if ((*(runner+1) == 'x') || (*(runner+1) == 'X'))
markrad 3:c0556ff7b8e3 318 {
markrad 3:c0556ff7b8e3 319 /*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).]*/
markrad 3:c0556ff7b8e3 320 /* hexadecimal... */
markrad 3:c0556ff7b8e3 321 if ((base == 0) || (base == 16))
markrad 3:c0556ff7b8e3 322 {
markrad 3:c0556ff7b8e3 323 base = 16;
markrad 3:c0556ff7b8e3 324 runner += 2;
markrad 3:c0556ff7b8e3 325 }
markrad 3:c0556ff7b8e3 326 }
markrad 3:c0556ff7b8e3 327 else if((base == 0) || (base == 8))
markrad 3:c0556ff7b8e3 328 {
markrad 3:c0556ff7b8e3 329 /*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).]*/
markrad 3:c0556ff7b8e3 330 /* octal... */
markrad 3:c0556ff7b8e3 331 base = 8;
markrad 3:c0556ff7b8e3 332 runner++;
markrad 3:c0556ff7b8e3 333 }
markrad 3:c0556ff7b8e3 334 }
markrad 3:c0556ff7b8e3 335
markrad 3:c0556ff7b8e3 336 if(base == 0)
markrad 3:c0556ff7b8e3 337 {
markrad 3:c0556ff7b8e3 338 /*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).]*/
markrad 3:c0556ff7b8e3 339 /* decimal... */
markrad 3:c0556ff7b8e3 340 base = 10;
markrad 3:c0556ff7b8e3 341 }
markrad 3:c0556ff7b8e3 342
markrad 3:c0556ff7b8e3 343 digitVal = DIGIT_VAL(*runner);
markrad 3:c0556ff7b8e3 344 if (validStr && IN_BASE_RANGE(digitVal, base))
markrad 3:c0556ff7b8e3 345 {
markrad 3:c0556ff7b8e3 346 errno = 0;
markrad 3:c0556ff7b8e3 347 do
markrad 3:c0556ff7b8e3 348 {
markrad 3:c0556ff7b8e3 349 if (((ULLONG_MAX - digitVal) / base) < result)
markrad 3:c0556ff7b8e3 350 {
markrad 3:c0556ff7b8e3 351 /*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.]*/
markrad 3:c0556ff7b8e3 352 /* overflow... */
markrad 3:c0556ff7b8e3 353 result = ULLONG_MAX;
markrad 3:c0556ff7b8e3 354 errno = ERANGE;
markrad 3:c0556ff7b8e3 355 }
markrad 3:c0556ff7b8e3 356 else
markrad 3:c0556ff7b8e3 357 {
markrad 3:c0556ff7b8e3 358 result = result * base + digitVal;
markrad 3:c0556ff7b8e3 359 }
markrad 3:c0556ff7b8e3 360 runner++;
markrad 3:c0556ff7b8e3 361 digitVal = DIGIT_VAL(*runner);
markrad 3:c0556ff7b8e3 362 } while (IN_BASE_RANGE(digitVal, base));
markrad 3:c0556ff7b8e3 363 }
markrad 3:c0556ff7b8e3 364 else
markrad 3:c0556ff7b8e3 365 {
markrad 3:c0556ff7b8e3 366 runner = (char*)nptr;
markrad 3:c0556ff7b8e3 367 }
markrad 3:c0556ff7b8e3 368 }
markrad 3:c0556ff7b8e3 369
markrad 3:c0556ff7b8e3 370 /*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.]*/
markrad 3:c0556ff7b8e3 371 if (endptr != NULL)
markrad 3:c0556ff7b8e3 372 {
markrad 3:c0556ff7b8e3 373 (*endptr) = (char*)runner;
markrad 3:c0556ff7b8e3 374 }
markrad 3:c0556ff7b8e3 375
markrad 3:c0556ff7b8e3 376 /*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.]*/
markrad 3:c0556ff7b8e3 377 if (isNegative)
markrad 3:c0556ff7b8e3 378 {
markrad 3:c0556ff7b8e3 379 result = ULLONG_MAX - result + 1;
markrad 3:c0556ff7b8e3 380 }
markrad 3:c0556ff7b8e3 381
markrad 3:c0556ff7b8e3 382 return result;
markrad 3:c0556ff7b8e3 383 }
markrad 3:c0556ff7b8e3 384
markrad 3:c0556ff7b8e3 385 /*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.]*/
markrad 3:c0556ff7b8e3 386 /*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.]*/
markrad 3:c0556ff7b8e3 387 /*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.]*/
markrad 3:c0556ff7b8e3 388 /*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.]*/
markrad 3:c0556ff7b8e3 389 #define TOUPPER(c) (((c>='a') && (c<='z'))?c-'a'+'A':c)
markrad 3:c0556ff7b8e3 390 static int substricmp(const char* nptr, const char* subsrt)
markrad 3:c0556ff7b8e3 391 {
markrad 3:c0556ff7b8e3 392 int result = 0;
markrad 3:c0556ff7b8e3 393 while (((*subsrt) != '\0') && (result == 0))
markrad 3:c0556ff7b8e3 394 {
markrad 3:c0556ff7b8e3 395 result = TOUPPER(*nptr) - TOUPPER(*subsrt);
markrad 3:c0556ff7b8e3 396 nptr++;
markrad 3:c0556ff7b8e3 397 subsrt++;
markrad 3:c0556ff7b8e3 398 }
markrad 3:c0556ff7b8e3 399 return result;
markrad 3:c0556ff7b8e3 400 }
markrad 3:c0556ff7b8e3 401
markrad 3:c0556ff7b8e3 402 /*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.]*/
markrad 3:c0556ff7b8e3 403 /*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.]*/
markrad 3:c0556ff7b8e3 404 static bool isInfinity(const char** endptr)
markrad 3:c0556ff7b8e3 405 {
markrad 3:c0556ff7b8e3 406 bool result = false;
markrad 3:c0556ff7b8e3 407 if (substricmp((*endptr), "INF") == 0)
markrad 3:c0556ff7b8e3 408 {
markrad 3:c0556ff7b8e3 409 (*endptr) += 3;
markrad 3:c0556ff7b8e3 410 result = true;
markrad 3:c0556ff7b8e3 411 if (substricmp((*endptr), "INITY") == 0)
markrad 3:c0556ff7b8e3 412 {
markrad 3:c0556ff7b8e3 413 (*endptr) += 5;
markrad 3:c0556ff7b8e3 414 }
markrad 3:c0556ff7b8e3 415 }
markrad 3:c0556ff7b8e3 416 return result;
markrad 3:c0556ff7b8e3 417 }
markrad 3:c0556ff7b8e3 418
markrad 3:c0556ff7b8e3 419 /*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.]*/
markrad 3:c0556ff7b8e3 420 /*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.]*/
markrad 3:c0556ff7b8e3 421 static bool isNaN(const char** endptr)
markrad 3:c0556ff7b8e3 422 {
markrad 3:c0556ff7b8e3 423 const char* runner = (*endptr);
markrad 3:c0556ff7b8e3 424 bool result = false;
markrad 3:c0556ff7b8e3 425 if (substricmp(runner, "NAN") == 0)
markrad 3:c0556ff7b8e3 426 {
markrad 3:c0556ff7b8e3 427 runner += 3;
markrad 3:c0556ff7b8e3 428 result = true;
markrad 3:c0556ff7b8e3 429 if ((*runner) == '(')
markrad 3:c0556ff7b8e3 430 {
markrad 3:c0556ff7b8e3 431 do
markrad 3:c0556ff7b8e3 432 {
markrad 3:c0556ff7b8e3 433 runner++;
markrad 3:c0556ff7b8e3 434 } while (((*runner) != '\0') && ((*runner) != ')'));
markrad 3:c0556ff7b8e3 435 if ((*runner) == ')')
markrad 3:c0556ff7b8e3 436 runner++;
markrad 3:c0556ff7b8e3 437 else
markrad 3:c0556ff7b8e3 438 result = false;
markrad 3:c0556ff7b8e3 439 }
markrad 3:c0556ff7b8e3 440 }
markrad 3:c0556ff7b8e3 441 if (result)
markrad 3:c0556ff7b8e3 442 (*endptr) = runner;
markrad 3:c0556ff7b8e3 443 return result;
markrad 3:c0556ff7b8e3 444 }
markrad 3:c0556ff7b8e3 445
markrad 3:c0556ff7b8e3 446 #define FLOAT_STRING_TYPE_VALUES \
markrad 3:c0556ff7b8e3 447 FST_INFINITY, \
markrad 3:c0556ff7b8e3 448 FST_NAN, \
markrad 3:c0556ff7b8e3 449 FST_NUMBER, \
markrad 3:c0556ff7b8e3 450 FST_OVERFLOW, \
markrad 3:c0556ff7b8e3 451 FST_ERROR
markrad 3:c0556ff7b8e3 452
markrad 3:c0556ff7b8e3 453 DEFINE_ENUM(FLOAT_STRING_TYPE, FLOAT_STRING_TYPE_VALUES);
markrad 3:c0556ff7b8e3 454
markrad 3:c0556ff7b8e3 455 static FLOAT_STRING_TYPE splitFloatString(const char* nptr, char** endptr, int *signal, double *fraction, int *exponential)
markrad 3:c0556ff7b8e3 456 {
markrad 3:c0556ff7b8e3 457 FLOAT_STRING_TYPE result = FST_ERROR;
markrad 3:c0556ff7b8e3 458
markrad 3:c0556ff7b8e3 459 unsigned long long ullInteger = 0;
markrad 3:c0556ff7b8e3 460 unsigned long long ullFraction = 0;
markrad 3:c0556ff7b8e3 461 int integerSize = 0;
markrad 3:c0556ff7b8e3 462 int fractionSize = 0;
markrad 3:c0556ff7b8e3 463 char* startptr;
markrad 3:c0556ff7b8e3 464
markrad 3:c0556ff7b8e3 465 (*endptr) = (char*)nptr;
markrad 3:c0556ff7b8e3 466
markrad 3:c0556ff7b8e3 467 /*Codes_SRS_CRT_ABSTRACTIONS_21_018: [The white-space for strtof_s must be one of the characters ' ', '\f', '\n', '\r', '\t', '\v'.]*/
markrad 3:c0556ff7b8e3 468 /*Codes_SRS_CRT_ABSTRACTIONS_21_028: [The white-space for strtold_s must be one of the characters ' ', '\f', '\n', '\r', '\t', '\v'.]*/
markrad 3:c0556ff7b8e3 469 while (IS_SPACE(**endptr))
markrad 3:c0556ff7b8e3 470 {
markrad 3:c0556ff7b8e3 471 (*endptr)++;
markrad 3:c0556ff7b8e3 472 }
markrad 3:c0556ff7b8e3 473
markrad 3:c0556ff7b8e3 474 /*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).]*/
markrad 3:c0556ff7b8e3 475 /*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).]*/
markrad 3:c0556ff7b8e3 476 (*signal) = +1;
markrad 3:c0556ff7b8e3 477 if ((**endptr) == '+')
markrad 3:c0556ff7b8e3 478 {
markrad 3:c0556ff7b8e3 479 (*endptr)++;
markrad 3:c0556ff7b8e3 480 }
markrad 3:c0556ff7b8e3 481 else if ((**endptr) == '-')
markrad 3:c0556ff7b8e3 482 {
markrad 3:c0556ff7b8e3 483 (*signal) = -1;
markrad 3:c0556ff7b8e3 484 (*endptr)++;
markrad 3:c0556ff7b8e3 485 }
markrad 3:c0556ff7b8e3 486
markrad 3:c0556ff7b8e3 487 /*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.]*/
markrad 3:c0556ff7b8e3 488 /*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.]*/
markrad 3:c0556ff7b8e3 489 if (isInfinity((const char**)endptr))
markrad 3:c0556ff7b8e3 490 {
markrad 3:c0556ff7b8e3 491 result = FST_INFINITY;
markrad 3:c0556ff7b8e3 492 }
markrad 3:c0556ff7b8e3 493 /*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.]*/
markrad 3:c0556ff7b8e3 494 /*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.]*/
markrad 3:c0556ff7b8e3 495 else if (isNaN((const char**)endptr))
markrad 3:c0556ff7b8e3 496 {
markrad 3:c0556ff7b8e3 497 result = FST_NAN;
markrad 3:c0556ff7b8e3 498 }
markrad 3:c0556ff7b8e3 499 else if (IN_BASE_RANGE(DIGIT_VAL(**endptr), 10))
markrad 3:c0556ff7b8e3 500 {
markrad 3:c0556ff7b8e3 501 result = FST_NUMBER;
markrad 3:c0556ff7b8e3 502 startptr = *endptr;
markrad 3:c0556ff7b8e3 503 /* integers will go to the fraction and exponential. */
markrad 3:c0556ff7b8e3 504 ullInteger = strtoull_s(startptr, endptr, 10);
markrad 3:c0556ff7b8e3 505 integerSize = (int)((*endptr) - startptr);
markrad 3:c0556ff7b8e3 506 if ((ullInteger == ULLONG_MAX) && (errno != 0))
markrad 3:c0556ff7b8e3 507 {
markrad 3:c0556ff7b8e3 508 result = FST_OVERFLOW;
markrad 3:c0556ff7b8e3 509 }
markrad 3:c0556ff7b8e3 510
markrad 3:c0556ff7b8e3 511 /* get the real fraction part, if exist. */
markrad 3:c0556ff7b8e3 512 if ((**endptr) == '.')
markrad 3:c0556ff7b8e3 513 {
markrad 3:c0556ff7b8e3 514 startptr = (*endptr) + 1;
markrad 3:c0556ff7b8e3 515 ullFraction = strtoull_s(startptr, endptr, 10);
markrad 3:c0556ff7b8e3 516 fractionSize = (int)((*endptr) - startptr);
markrad 3:c0556ff7b8e3 517 if ((ullFraction == ULLONG_MAX) && (errno != 0))
markrad 3:c0556ff7b8e3 518 {
markrad 3:c0556ff7b8e3 519 result = FST_OVERFLOW;
markrad 3:c0556ff7b8e3 520 }
markrad 3:c0556ff7b8e3 521 }
markrad 3:c0556ff7b8e3 522
markrad 3:c0556ff7b8e3 523 if (((**endptr) == 'e') || ((**endptr) == 'E'))
markrad 3:c0556ff7b8e3 524 {
markrad 3:c0556ff7b8e3 525 startptr = (*endptr) + 1;
markrad 3:c0556ff7b8e3 526 (*exponential) = strtol(startptr, endptr, 10);
markrad 3:c0556ff7b8e3 527 if (((*exponential) < (DBL_MAX_10_EXP * (-1))) || ((*exponential) > DBL_MAX_10_EXP))
markrad 3:c0556ff7b8e3 528 {
markrad 3:c0556ff7b8e3 529 result = FST_OVERFLOW;
markrad 3:c0556ff7b8e3 530 }
markrad 3:c0556ff7b8e3 531 }
markrad 3:c0556ff7b8e3 532 else
markrad 3:c0556ff7b8e3 533 {
markrad 3:c0556ff7b8e3 534 (*exponential) = 0;
markrad 3:c0556ff7b8e3 535 }
markrad 3:c0556ff7b8e3 536
markrad 3:c0556ff7b8e3 537 if (result == FST_NUMBER)
markrad 3:c0556ff7b8e3 538 {
markrad 3:c0556ff7b8e3 539 /* Add ullInteger to ullFraction. */
markrad 3:c0556ff7b8e3 540 ullFraction += (ullInteger * (unsigned long long)(pow(10, (double)fractionSize)));
markrad 3:c0556ff7b8e3 541 (*fraction) = ((double)ullFraction / (pow(10.0f, (double)(fractionSize + integerSize - 1))));
markrad 3:c0556ff7b8e3 542
markrad 3:c0556ff7b8e3 543 /* Unify rest of integerSize and fractionSize in the exponential. */
markrad 3:c0556ff7b8e3 544 (*exponential) += integerSize - 1;
markrad 3:c0556ff7b8e3 545 }
markrad 3:c0556ff7b8e3 546 }
markrad 3:c0556ff7b8e3 547
markrad 3:c0556ff7b8e3 548 return result;
markrad 3:c0556ff7b8e3 549 }
markrad 3:c0556ff7b8e3 550
markrad 3:c0556ff7b8e3 551 /*Codes_SRS_CRT_ABSTRACTIONS_21_015: [The strtof_s must convert the initial portion of the string pointed to by nptr to float representation.]*/
markrad 3:c0556ff7b8e3 552 /*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.]*/
markrad 3:c0556ff7b8e3 553 float strtof_s(const char* nptr, char** endptr)
markrad 3:c0556ff7b8e3 554 {
markrad 3:c0556ff7b8e3 555 int signal = 1;
markrad 3:c0556ff7b8e3 556 double fraction;
markrad 3:c0556ff7b8e3 557 int exponential;
markrad 3:c0556ff7b8e3 558 char* runner = (char*)nptr;
markrad 3:c0556ff7b8e3 559 double val;
markrad 3:c0556ff7b8e3 560
markrad 3:c0556ff7b8e3 561 /*Codes_SRS_CRT_ABSTRACTIONS_21_021: [If no conversion could be performed, the strtof_s returns the value 0.0.]*/
markrad 3:c0556ff7b8e3 562 float result = 0.0;
markrad 3:c0556ff7b8e3 563
markrad 3:c0556ff7b8e3 564 /*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.]*/
markrad 3:c0556ff7b8e3 565 if (nptr != NULL)
markrad 3:c0556ff7b8e3 566 {
markrad 3:c0556ff7b8e3 567 switch (splitFloatString(nptr, &runner, &signal, &fraction, &exponential))
markrad 3:c0556ff7b8e3 568 {
markrad 3:c0556ff7b8e3 569 case FST_INFINITY:
markrad 3:c0556ff7b8e3 570 /*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.]*/
markrad 3:c0556ff7b8e3 571 result = INFINITY * (signal);
markrad 3:c0556ff7b8e3 572 errno = 0;
markrad 3:c0556ff7b8e3 573 break;
markrad 3:c0556ff7b8e3 574 case FST_NAN:
markrad 3:c0556ff7b8e3 575 /*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.]*/
markrad 3:c0556ff7b8e3 576 result = NAN;
markrad 3:c0556ff7b8e3 577 break;
markrad 3:c0556ff7b8e3 578 case FST_NUMBER:
markrad 3:c0556ff7b8e3 579 val = fraction * pow(10.0, (double)exponential) * (double)signal;
markrad 3:c0556ff7b8e3 580 if ((val >= (FLT_MAX * (-1))) && (val <= FLT_MAX))
markrad 3:c0556ff7b8e3 581 {
markrad 3:c0556ff7b8e3 582 /*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.]*/
markrad 3:c0556ff7b8e3 583 result = (float)val;
markrad 3:c0556ff7b8e3 584 }
markrad 3:c0556ff7b8e3 585 else
markrad 3:c0556ff7b8e3 586 {
markrad 3:c0556ff7b8e3 587 /*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.]*/
markrad 3:c0556ff7b8e3 588 result = HUGE_VALF * (signal);
markrad 3:c0556ff7b8e3 589 errno = ERANGE;
markrad 3:c0556ff7b8e3 590 }
markrad 3:c0556ff7b8e3 591 break;
markrad 3:c0556ff7b8e3 592 case FST_OVERFLOW:
markrad 3:c0556ff7b8e3 593 /*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.]*/
markrad 3:c0556ff7b8e3 594 result = HUGE_VALF * (signal);
markrad 3:c0556ff7b8e3 595 errno = ERANGE;
markrad 3:c0556ff7b8e3 596 break;
markrad 3:c0556ff7b8e3 597 default:
markrad 3:c0556ff7b8e3 598 /*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.]*/
markrad 3:c0556ff7b8e3 599 runner = (char*)nptr;
markrad 3:c0556ff7b8e3 600 break;
markrad 3:c0556ff7b8e3 601 }
markrad 3:c0556ff7b8e3 602 }
markrad 3:c0556ff7b8e3 603
markrad 3:c0556ff7b8e3 604 /*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.]*/
markrad 3:c0556ff7b8e3 605 if (endptr != NULL)
markrad 3:c0556ff7b8e3 606 {
markrad 3:c0556ff7b8e3 607 (*endptr) = runner;
markrad 3:c0556ff7b8e3 608 }
markrad 3:c0556ff7b8e3 609
markrad 3:c0556ff7b8e3 610 return result;
markrad 3:c0556ff7b8e3 611 }
markrad 3:c0556ff7b8e3 612
markrad 3:c0556ff7b8e3 613 /*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.]*/
markrad 3:c0556ff7b8e3 614 /*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.]*/
markrad 3:c0556ff7b8e3 615 long double strtold_s(const char* nptr, char** endptr)
markrad 3:c0556ff7b8e3 616 {
markrad 3:c0556ff7b8e3 617 int signal = 1;
markrad 3:c0556ff7b8e3 618 double fraction;
markrad 3:c0556ff7b8e3 619 int exponential;
markrad 3:c0556ff7b8e3 620 char* runner = (char*)nptr;
markrad 3:c0556ff7b8e3 621
markrad 3:c0556ff7b8e3 622 /*Codes_SRS_CRT_ABSTRACTIONS_21_031: [If no conversion could be performed, the strtold_s returns the value 0.0.]*/
markrad 3:c0556ff7b8e3 623 long double result = 0.0;
markrad 3:c0556ff7b8e3 624
markrad 3:c0556ff7b8e3 625 /*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.]*/
markrad 3:c0556ff7b8e3 626 if (nptr != NULL)
markrad 3:c0556ff7b8e3 627 {
markrad 3:c0556ff7b8e3 628 switch (splitFloatString(nptr, &runner, &signal, &fraction, &exponential))
markrad 3:c0556ff7b8e3 629 {
markrad 3:c0556ff7b8e3 630 case FST_INFINITY:
markrad 3:c0556ff7b8e3 631 /*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.]*/
markrad 3:c0556ff7b8e3 632 result = INFINITY * (signal);
markrad 3:c0556ff7b8e3 633 errno = 0;
markrad 3:c0556ff7b8e3 634 break;
markrad 3:c0556ff7b8e3 635 case FST_NAN:
markrad 3:c0556ff7b8e3 636 /*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.]*/
markrad 3:c0556ff7b8e3 637 result = NAN;
markrad 3:c0556ff7b8e3 638 break;
markrad 3:c0556ff7b8e3 639 case FST_NUMBER:
markrad 3:c0556ff7b8e3 640 if ((exponential != DBL_MAX_10_EXP || (fraction <= 1.7976931348623158)) &&
markrad 3:c0556ff7b8e3 641 (exponential != (DBL_MAX_10_EXP * (-1)) || (fraction <= 2.2250738585072014)))
markrad 3:c0556ff7b8e3 642 {
markrad 3:c0556ff7b8e3 643 /*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.]*/
markrad 3:c0556ff7b8e3 644 result = fraction * pow(10.0, (double)exponential) * (double)signal;
markrad 3:c0556ff7b8e3 645 }
markrad 3:c0556ff7b8e3 646 else
markrad 3:c0556ff7b8e3 647 {
markrad 3:c0556ff7b8e3 648 /*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.]*/
markrad 3:c0556ff7b8e3 649 result = HUGE_VALF * (signal);
markrad 3:c0556ff7b8e3 650 errno = ERANGE;
markrad 3:c0556ff7b8e3 651 }
markrad 3:c0556ff7b8e3 652 break;
markrad 3:c0556ff7b8e3 653 case FST_OVERFLOW:
markrad 3:c0556ff7b8e3 654 /*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.]*/
markrad 3:c0556ff7b8e3 655 result = HUGE_VALF * (signal);
markrad 3:c0556ff7b8e3 656 errno = ERANGE;
markrad 3:c0556ff7b8e3 657 break;
markrad 3:c0556ff7b8e3 658 default:
markrad 3:c0556ff7b8e3 659 /*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.]*/
markrad 3:c0556ff7b8e3 660 runner = (char*)nptr;
markrad 3:c0556ff7b8e3 661 break;
markrad 3:c0556ff7b8e3 662 }
markrad 3:c0556ff7b8e3 663 }
markrad 3:c0556ff7b8e3 664
markrad 3:c0556ff7b8e3 665 /*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.]*/
markrad 3:c0556ff7b8e3 666 if (endptr != NULL)
markrad 3:c0556ff7b8e3 667 {
markrad 3:c0556ff7b8e3 668 (*endptr) = runner;
markrad 3:c0556ff7b8e3 669 }
markrad 3:c0556ff7b8e3 670
markrad 3:c0556ff7b8e3 671 return result;
markrad 3:c0556ff7b8e3 672 }
markrad 3:c0556ff7b8e3 673
markrad 3:c0556ff7b8e3 674
markrad 3:c0556ff7b8e3 675 /*Codes_SRS_CRT_ABSTRACTIONS_99_038: [mallocAndstrcpy_s shall allocate memory for destination buffer to fit the string in the source parameter.]*/
markrad 3:c0556ff7b8e3 676 int mallocAndStrcpy_s(char** destination, const char* source)
markrad 3:c0556ff7b8e3 677 {
markrad 3:c0556ff7b8e3 678 int result;
markrad 3:c0556ff7b8e3 679 int copied_result;
markrad 3:c0556ff7b8e3 680 /*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.]*/
markrad 3:c0556ff7b8e3 681 if ((destination == NULL) || (source == NULL))
markrad 3:c0556ff7b8e3 682 {
markrad 3:c0556ff7b8e3 683 /*If strDestination or strSource is a NULL pointer[...]these functions return EINVAL */
markrad 3:c0556ff7b8e3 684 result = EINVAL;
markrad 3:c0556ff7b8e3 685 }
markrad 3:c0556ff7b8e3 686 else
markrad 3:c0556ff7b8e3 687 {
markrad 3:c0556ff7b8e3 688 size_t l = strlen(source);
markrad 3:c0556ff7b8e3 689 char* temp = (char*)malloc(l + 1);
markrad 3:c0556ff7b8e3 690
markrad 3:c0556ff7b8e3 691 /*Codes_SRS_CRT_ABSTRACTIONS_99_037: [Upon failure to allocate memory for the destination, the function will return ENOMEM.]*/
markrad 3:c0556ff7b8e3 692 if (temp == NULL)
markrad 3:c0556ff7b8e3 693 {
markrad 3:c0556ff7b8e3 694 result = ENOMEM;
markrad 3:c0556ff7b8e3 695 }
markrad 3:c0556ff7b8e3 696 else
markrad 3:c0556ff7b8e3 697 {
markrad 3:c0556ff7b8e3 698 *destination = temp;
markrad 3:c0556ff7b8e3 699 /*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.]*/
markrad 3:c0556ff7b8e3 700 copied_result = strcpy_s(*destination, l + 1, source);
markrad 3:c0556ff7b8e3 701 if (copied_result < 0) /*strcpy_s error*/
markrad 3:c0556ff7b8e3 702 {
markrad 3:c0556ff7b8e3 703 free(*destination);
markrad 3:c0556ff7b8e3 704 *destination = NULL;
markrad 3:c0556ff7b8e3 705 result = copied_result;
markrad 3:c0556ff7b8e3 706 }
markrad 3:c0556ff7b8e3 707 else
markrad 3:c0556ff7b8e3 708 {
markrad 3:c0556ff7b8e3 709 /*Codes_SRS_CRT_ABSTRACTIONS_99_035: [mallocAndstrcpy_s shall return Zero upon success]*/
markrad 3:c0556ff7b8e3 710 result = 0;
markrad 3:c0556ff7b8e3 711 }
markrad 3:c0556ff7b8e3 712 }
markrad 3:c0556ff7b8e3 713 }
markrad 3:c0556ff7b8e3 714 return result;
markrad 3:c0556ff7b8e3 715 }
markrad 3:c0556ff7b8e3 716
markrad 3:c0556ff7b8e3 717 /*takes "value" and transforms it into a decimal string*/
markrad 3:c0556ff7b8e3 718 /*10 => "10"*/
markrad 3:c0556ff7b8e3 719 /*return 0 when everything went ok*/
markrad 3:c0556ff7b8e3 720 /*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.] */
markrad 3:c0556ff7b8e3 721 int unsignedIntToString(char* destination, size_t destinationSize, unsigned int value)
markrad 3:c0556ff7b8e3 722 {
markrad 3:c0556ff7b8e3 723 int result;
markrad 3:c0556ff7b8e3 724 size_t pos;
markrad 3:c0556ff7b8e3 725 /*the below loop gets the number in reverse order*/
markrad 3:c0556ff7b8e3 726 /*Codes_SRS_CRT_ABSTRACTIONS_02_003: [If destination is NULL then unsignedIntToString shall fail.] */
markrad 3:c0556ff7b8e3 727 /*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.] */
markrad 3:c0556ff7b8e3 728 if (
markrad 3:c0556ff7b8e3 729 (destination == NULL) ||
markrad 3:c0556ff7b8e3 730 (destinationSize < 2) /*because the smallest number is '0\0' which requires 2 characters*/
markrad 3:c0556ff7b8e3 731 )
markrad 3:c0556ff7b8e3 732 {
markrad 3:c0556ff7b8e3 733 result = __LINE__;
markrad 3:c0556ff7b8e3 734 }
markrad 3:c0556ff7b8e3 735 else
markrad 3:c0556ff7b8e3 736 {
markrad 3:c0556ff7b8e3 737 pos = 0;
markrad 3:c0556ff7b8e3 738 do
markrad 3:c0556ff7b8e3 739 {
markrad 3:c0556ff7b8e3 740 destination[pos++] = '0' + (value % 10);
markrad 3:c0556ff7b8e3 741 value /= 10;
markrad 3:c0556ff7b8e3 742 } while ((value > 0) && (pos < (destinationSize-1)));
markrad 3:c0556ff7b8e3 743
markrad 3:c0556ff7b8e3 744 if (value == 0)
markrad 3:c0556ff7b8e3 745 {
markrad 3:c0556ff7b8e3 746 size_t w;
markrad 3:c0556ff7b8e3 747 destination[pos] = '\0';
markrad 3:c0556ff7b8e3 748 /*all converted and they fit*/
markrad 3:c0556ff7b8e3 749 for (w = 0; w <= (pos-1) >> 1; w++)
markrad 3:c0556ff7b8e3 750 {
markrad 3:c0556ff7b8e3 751 char temp;
markrad 3:c0556ff7b8e3 752 temp = destination[w];
markrad 3:c0556ff7b8e3 753 destination[w] = destination[pos - 1 - w];
markrad 3:c0556ff7b8e3 754 destination[pos -1 - w] = temp;
markrad 3:c0556ff7b8e3 755 }
markrad 3:c0556ff7b8e3 756 /*Codes_SRS_CRT_ABSTRACTIONS_02_004: [If the conversion has been successfull then unsignedIntToString shall return 0.] */
markrad 3:c0556ff7b8e3 757 result = 0;
markrad 3:c0556ff7b8e3 758 }
markrad 3:c0556ff7b8e3 759 else
markrad 3:c0556ff7b8e3 760 {
markrad 3:c0556ff7b8e3 761 /*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.] */
markrad 3:c0556ff7b8e3 762 result = __LINE__;
markrad 3:c0556ff7b8e3 763 }
markrad 3:c0556ff7b8e3 764 }
markrad 3:c0556ff7b8e3 765 return result;
markrad 3:c0556ff7b8e3 766 }
markrad 3:c0556ff7b8e3 767
markrad 3:c0556ff7b8e3 768 /*takes "value" and transforms it into a decimal string*/
markrad 3:c0556ff7b8e3 769 /*10 => "10"*/
markrad 3:c0556ff7b8e3 770 /*return 0 when everything went ok*/
markrad 3:c0556ff7b8e3 771 /*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.] */
markrad 3:c0556ff7b8e3 772 int size_tToString(char* destination, size_t destinationSize, size_t value)
markrad 3:c0556ff7b8e3 773 {
markrad 3:c0556ff7b8e3 774 int result;
markrad 3:c0556ff7b8e3 775 size_t pos;
markrad 3:c0556ff7b8e3 776 /*the below loop gets the number in reverse order*/
markrad 3:c0556ff7b8e3 777 /*Codes_SRS_CRT_ABSTRACTIONS_02_003: [If destination is NULL then unsignedIntToString shall fail.] */
markrad 3:c0556ff7b8e3 778 /*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.] */
markrad 3:c0556ff7b8e3 779 if (
markrad 3:c0556ff7b8e3 780 (destination == NULL) ||
markrad 3:c0556ff7b8e3 781 (destinationSize < 2) /*because the smallest number is '0\0' which requires 2 characters*/
markrad 3:c0556ff7b8e3 782 )
markrad 3:c0556ff7b8e3 783 {
markrad 3:c0556ff7b8e3 784 result = __LINE__;
markrad 3:c0556ff7b8e3 785 }
markrad 3:c0556ff7b8e3 786 else
markrad 3:c0556ff7b8e3 787 {
markrad 3:c0556ff7b8e3 788 pos = 0;
markrad 3:c0556ff7b8e3 789 do
markrad 3:c0556ff7b8e3 790 {
markrad 3:c0556ff7b8e3 791 destination[pos++] = '0' + (value % 10);
markrad 3:c0556ff7b8e3 792 value /= 10;
markrad 3:c0556ff7b8e3 793 } while ((value > 0) && (pos < (destinationSize - 1)));
markrad 3:c0556ff7b8e3 794
markrad 3:c0556ff7b8e3 795 if (value == 0)
markrad 3:c0556ff7b8e3 796 {
markrad 3:c0556ff7b8e3 797 size_t w;
markrad 3:c0556ff7b8e3 798 destination[pos] = '\0';
markrad 3:c0556ff7b8e3 799 /*all converted and they fit*/
markrad 3:c0556ff7b8e3 800 for (w = 0; w <= (pos - 1) >> 1; w++)
markrad 3:c0556ff7b8e3 801 {
markrad 3:c0556ff7b8e3 802 char temp;
markrad 3:c0556ff7b8e3 803 temp = destination[w];
markrad 3:c0556ff7b8e3 804 destination[w] = destination[pos - 1 - w];
markrad 3:c0556ff7b8e3 805 destination[pos - 1 - w] = temp;
markrad 3:c0556ff7b8e3 806 }
markrad 3:c0556ff7b8e3 807 /*Codes_SRS_CRT_ABSTRACTIONS_02_004: [If the conversion has been successfull then unsignedIntToString shall return 0.] */
markrad 3:c0556ff7b8e3 808 result = 0;
markrad 3:c0556ff7b8e3 809 }
markrad 3:c0556ff7b8e3 810 else
markrad 3:c0556ff7b8e3 811 {
markrad 3:c0556ff7b8e3 812 /*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.] */
markrad 3:c0556ff7b8e3 813 result = __LINE__;
markrad 3:c0556ff7b8e3 814 }
markrad 3:c0556ff7b8e3 815 }
markrad 3:c0556ff7b8e3 816 return result;
markrad 3:c0556ff7b8e3 817 }