source: azure_iot_hub/trunk/azure_iohub/c-utility/src/crt_abstractions.c@ 388

Last change on this file since 388 was 388, checked in by coas-nagasima, 5 years ago

Azure IoT Hub Device C SDK を使ったサンプルの追加

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