busybox/libbb/bb_strtod.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * Utility routines.
   4 *
   5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
   6 *
   7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
   8 */
   9#include "libbb.h"
  10#include <math.h>  /* just for HUGE_VAL */
  11
  12#define NOT_DIGIT(a) (((unsigned char)(a-'0')) > 9)
  13
  14#if 0 // UNUSED
  15double FAST_FUNC bb_strtod(const char *arg, char **endp)
  16{
  17        double v;
  18        char *endptr;
  19
  20        /* Allow .NN form. People want to use "sleep .15" etc */
  21        if (arg[0] != '-' && arg[0] != '.' && NOT_DIGIT(arg[0]))
  22                goto err;
  23        errno = 0;
  24        v = strtod(arg, &endptr);
  25        if (endp)
  26                *endp = endptr;
  27        if (endptr[0]) {
  28                /* "1234abcg" or out-of-range? */
  29                if (isalnum(endptr[0]) || errno) {
  30 err:
  31                        errno = ERANGE;
  32                        return HUGE_VAL;
  33                }
  34                /* good number, just suspicious terminator */
  35                errno = EINVAL;
  36        }
  37        return v;
  38}
  39#endif
  40
  41#if 0
  42/* String to timespec: "NNNN[.NNNNN]" -> struct timespec.
  43 * Can be used for other fixed-point needs.
  44 * Returns pointer past last converted char,
  45 * and returns errno similar to bb_strtoXX functions.
  46 */
  47char* FAST_FUNC bb_str_to_ts(struct timespec *ts, const char *arg)
  48{
  49        if (sizeof(ts->tv_sec) <= sizeof(int))
  50                ts->tv_sec = bb_strtou(arg, &arg, 10);
  51        else if (sizeof(ts->tv_sec) <= sizeof(long))
  52                ts->tv_sec = bb_strtoul(arg, &arg, 10);
  53        else
  54                ts->tv_sec = bb_strtoull(arg, &arg, 10);
  55        ts->tv_nsec = 0;
  56
  57        if (*arg != '.')
  58                return arg;
  59
  60        /* !EINVAL: number is not ok (alphanumeric ending, overflow etc) */
  61        if (errno != EINVAL)
  62                return arg;
  63
  64        if (!*++arg) /* "NNN." */
  65                return arg;
  66
  67        { /* "NNN.xxx" - parse xxx */
  68                int ndigits;
  69                char *p;
  70                char buf[10]; /* we never use more than 9 digits */
  71
  72                /* Need to make a copy to avoid false overflow */
  73                safe_strncpy(buf, arg, 10);
  74                ts->tv_nsec = bb_strtou(buf, &p, 10);
  75                ndigits = p - buf;
  76                arg += ndigits;
  77                /* normalize to nsec */
  78                while (ndigits < 9) {
  79                        ndigits++;
  80                        ts->tv_nsec *= 10;
  81                }
  82                while (isdigit(*arg)) /* skip possible 10th plus digits */
  83                        arg++;
  84        }
  85        return arg;
  86}
  87#endif
  88