bb_strtod.c 1.9 KB

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