1 /* 2 * PROJECT: ReactOS CRT 3 * LICENSE: See COPYING in the top level directory 4 * PURPOSE: CRT's ecvt 5 * FILE: lib/sdk/crt/stdlib/ecvt.c 6 * PROGRAMERS: Gregor Schneider (parts based on ecvtbuf.c by DJ Delorie) 7 */ 8 9 #include <precomp.h> 10 #define NUMBER_EFMT 18 /* sign, dot, null, 15 for alignment */ 11 12 /* 13 * @implemented 14 */ 15 char * 16 _ecvt (double value, int ndigits, int *decpt, int *sign) 17 { 18 static char ecvtbuf[DBL_MAX_10_EXP + 10]; 19 char *cvtbuf, *s, *d; 20 21 if (ndigits < 0) ndigits = 0; 22 s = cvtbuf = (char*)malloc(ndigits + NUMBER_EFMT); 23 d = ecvtbuf; 24 25 *sign = 0; 26 *decpt = 0; 27 28 if (cvtbuf == NULL) 29 { 30 return NULL; 31 } 32 33 sprintf(cvtbuf, "%-+.*E", ndigits, value); 34 /* Treat special values */ 35 if (strncmp(s, "NaN", 3) == 0) 36 { 37 memcpy(ecvtbuf, s, 4); 38 } 39 else if (strncmp(s + 1, "Inf", 3) == 0) 40 { 41 memcpy(ecvtbuf, s, 5); 42 } 43 else 44 { 45 /* Set the sign */ 46 if (*s && *s == '-') 47 { 48 *sign = 1; 49 } 50 s++; 51 /* Copy the first digit */ 52 if (*s && *s != '.') 53 { 54 if (d - ecvtbuf < ndigits) 55 { 56 *d++ = *s++; 57 } 58 else 59 { 60 s++; 61 } 62 } 63 /* Skip the decimal point */ 64 if (*s && *s == '.') 65 { 66 s++; 67 } 68 /* Copy fractional digits */ 69 while (*s && *s != 'E') 70 { 71 if (d - ecvtbuf < ndigits) 72 { 73 *d++ = *s++; 74 } 75 else 76 { 77 s++; 78 } 79 } 80 /* Skip the exponent */ 81 if (*s && *s == 'E') 82 { 83 s++; 84 } 85 /* Set the decimal point to the exponent value plus the one digit we copied */ 86 *decpt = atoi(s) + 1; 87 /* Handle special decimal point cases */ 88 if (cvtbuf[1] == '0') 89 { 90 *decpt = 0; 91 } 92 if (ndigits < 1) 93 { 94 /* Need enhanced precision*/ 95 char* tbuf = (char*)malloc(NUMBER_EFMT); 96 if (tbuf == NULL) 97 { 98 free(cvtbuf); 99 return NULL; 100 } 101 sprintf(tbuf, "%-+.*E", ndigits + 2, value); 102 if (tbuf[1] >= '5') 103 { 104 (*decpt)++; 105 } 106 free(tbuf); 107 } 108 /* Pad with zeroes */ 109 while (d - ecvtbuf < ndigits) 110 { 111 *d++ = '0'; 112 } 113 /* Terminate */ 114 *d = '\0'; 115 } 116 free(cvtbuf); 117 return ecvtbuf; 118 } 119