parse_int.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /* Copyright (c) 2003, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. #include "lib/string/parse_int.h"
  6. #include <errno.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. /* Helper: common code to check whether the result of a strtol or strtoul or
  10. * strtoll is correct. */
  11. #define CHECK_STRTOX_RESULT() \
  12. /* Did an overflow occur? */ \
  13. if (errno == ERANGE) \
  14. goto err; \
  15. /* Was at least one character converted? */ \
  16. if (endptr == s) \
  17. goto err; \
  18. /* Were there unexpected unconverted characters? */ \
  19. if (!next && *endptr) \
  20. goto err; \
  21. /* Illogical (max, min) inputs? */ \
  22. if (max < min) \
  23. goto err; \
  24. /* Is r within limits? */ \
  25. if (r < min || r > max) \
  26. goto err; \
  27. if (ok) *ok = 1; \
  28. if (next) *next = endptr; \
  29. return r; \
  30. err: \
  31. if (ok) *ok = 0; \
  32. if (next) *next = endptr; \
  33. return 0
  34. /** Extract a long from the start of <b>s</b>, in the given numeric
  35. * <b>base</b>. If <b>base</b> is 0, <b>s</b> is parsed as a decimal,
  36. * octal, or hex number in the syntax of a C integer literal. If
  37. * there is unconverted data and <b>next</b> is provided, set
  38. * *<b>next</b> to the first unconverted character. An error has
  39. * occurred if no characters are converted; or if there are
  40. * unconverted characters and <b>next</b> is NULL; or if the parsed
  41. * value is not between <b>min</b> and <b>max</b>. When no error
  42. * occurs, return the parsed value and set *<b>ok</b> (if provided) to
  43. * 1. When an error occurs, return 0 and set *<b>ok</b> (if provided)
  44. * to 0.
  45. */
  46. long
  47. tor_parse_long(const char *s, int base, long min, long max,
  48. int *ok, char **next)
  49. {
  50. char *endptr;
  51. long r;
  52. if (base < 0) {
  53. if (ok)
  54. *ok = 0;
  55. return 0;
  56. }
  57. errno = 0;
  58. r = strtol(s, &endptr, base);
  59. CHECK_STRTOX_RESULT();
  60. }
  61. /** As tor_parse_long(), but return an unsigned long. */
  62. unsigned long
  63. tor_parse_ulong(const char *s, int base, unsigned long min,
  64. unsigned long max, int *ok, char **next)
  65. {
  66. char *endptr;
  67. unsigned long r;
  68. if (base < 0) {
  69. if (ok)
  70. *ok = 0;
  71. return 0;
  72. }
  73. errno = 0;
  74. r = strtoul(s, &endptr, base);
  75. CHECK_STRTOX_RESULT();
  76. }
  77. /** As tor_parse_long(), but return a double. */
  78. double
  79. tor_parse_double(const char *s, double min, double max, int *ok, char **next)
  80. {
  81. char *endptr;
  82. double r;
  83. errno = 0;
  84. r = strtod(s, &endptr);
  85. CHECK_STRTOX_RESULT();
  86. }
  87. /** As tor_parse_long, but return a uint64_t. Only base 10 is guaranteed to
  88. * work for now. */
  89. uint64_t
  90. tor_parse_uint64(const char *s, int base, uint64_t min,
  91. uint64_t max, int *ok, char **next)
  92. {
  93. char *endptr;
  94. uint64_t r;
  95. if (base < 0) {
  96. if (ok)
  97. *ok = 0;
  98. return 0;
  99. }
  100. errno = 0;
  101. #ifdef HAVE_STRTOULL
  102. r = (uint64_t)strtoull(s, &endptr, base);
  103. #elif defined(_WIN32)
  104. r = (uint64_t)_strtoui64(s, &endptr, base);
  105. #elif SIZEOF_LONG == 8
  106. r = (uint64_t)strtoul(s, &endptr, base);
  107. #else
  108. #error "I don't know how to parse 64-bit numbers."
  109. #endif /* defined(HAVE_STRTOULL) || ... */
  110. CHECK_STRTOX_RESULT();
  111. }