-_ecvt really uses a static buffer for return values
[reactos.git] / reactos / lib / sdk / crt / stdlib / ecvt.c
index 0f11ad8..e5dca6c 100644 (file)
@@ -1,7 +1,12 @@
-/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
-#include <precomp.h>
+/*
+ * PROJECT:         ReactOS CRT
+ * LICENSE:         See COPYING in the top level directory
+ * PURPOSE:         CRT's ecvt
+ * FILE:            lib/sdk/crt/stdlib/ecvt.c
+ * PROGRAMERS:      Gregor Schneider (parts based on ecvtbuf.c by DJ Delorie)
+ */
 
-char *ecvtbuf (double, int, int *, int *, char *);
+#include <precomp.h>
 
 /*
  * @implemented
@@ -9,6 +14,103 @@ char *ecvtbuf (double, int, int *, int *, char *);
 char *
 _ecvt (double value, int ndigits, int *decpt, int *sign)
 {
-  static char ecvt_buf[DBL_MAX_10_EXP + 10];
-  return ecvtbuf (value, ndigits, decpt, sign, ecvt_buf);
+  static char ecvtbuf[DBL_MAX_10_EXP + 10];
+  char *cvtbuf, *s, *d;
+
+  s = cvtbuf = (char*)malloc(ndigits + 18); /* sign, dot, null, 15 for alignment */
+  d = ecvtbuf;
+
+  *sign = 0;
+  *decpt = 0;
+
+  if (cvtbuf == NULL)
+  {
+    return NULL;
+  }
+
+  sprintf(cvtbuf, "%-+.*E", ndigits, value);
+  /* Treat special values */
+  if (strncmp(s, "NaN", 3) == 0)
+  {
+    memcpy(ecvtbuf, s, 4);
+  }
+  else if (strncmp(s + 1, "Inf", 3) == 0)
+  {
+    memcpy(ecvtbuf, s, 5);
+  }
+  else 
+  {
+    /* Set the sign */
+    if (*s && *s == '-')
+    {
+      *sign = 1;
+    }
+    s++;
+    /* Copy the first digit */
+    if (*s && *s != '.')
+    {
+      if (d - ecvtbuf < ndigits)
+      {
+        *d++ = *s++;
+      }
+      else
+      {
+        s++;
+      }
+    }
+    /* Skip the decimal point */
+    if (*s && *s == '.')
+    {
+      s++;
+    }
+    /* Copy fractional digits */
+    while (*s && *s != 'E')
+    {
+      if (d - ecvtbuf < ndigits)
+      {
+        *d++ = *s++;
+      }
+      else
+      {
+        s++;
+      }
+    }
+    /* Skip the exponent */
+    if (*s && *s == 'E')
+    {
+      s++;
+    }
+    /* Set the decimal point to the exponent value plus the one digit we copied */
+    *decpt = atoi(s) + 1;
+    /* Handle special decimal point cases */
+    if (cvtbuf[1] == '0')
+    {
+      *decpt = 0;
+    }
+    if (ndigits < 1)
+    {
+      /* Need enhanced precision*/
+      char* tbuf = (char*)malloc(ndigits + 18);
+      if (tbuf == NULL)
+      {
+        free(cvtbuf);
+        return NULL;
+      }
+      sprintf(tbuf, "%-+.*E", ndigits + 2, value);
+      if (tbuf[1] >= '5')
+      {
+        (*decpt)++;
+      }
+      free(tbuf);
+    }
+    /* Pad with zeroes */
+    while (d - ecvtbuf < ndigits)
+    {
+      *d++ = '0';
+    }
+    /* Terminate */
+    *d = '\0';
+  }
+  free(cvtbuf);
+  return ecvtbuf;
 }