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