diff options
author | Nick Mathewson <nickm@torproject.org> | 2018-06-26 21:02:29 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2018-06-26 21:02:29 -0400 |
commit | 80730c45e032544155074022c0df5b6909b68faa (patch) | |
tree | 6b658e33d565c4912d0c18232f5c0855b4499a36 /src/lib/string | |
parent | 7159edf9090e0a0e4c7d02e80b81bc00083884cc (diff) | |
download | tor-80730c45e032544155074022c0df5b6909b68faa.tar.gz tor-80730c45e032544155074022c0df5b6909b68faa.zip |
Move tor_parse_long and friends into parse_int.h in libtor-string
Diffstat (limited to 'src/lib/string')
-rw-r--r-- | src/lib/string/include.am | 2 | ||||
-rw-r--r-- | src/lib/string/parse_int.c | 126 | ||||
-rw-r--r-- | src/lib/string/parse_int.h | 20 |
3 files changed, 148 insertions, 0 deletions
diff --git a/src/lib/string/include.am b/src/lib/string/include.am index e532d5030f..edd74b8a3e 100644 --- a/src/lib/string/include.am +++ b/src/lib/string/include.am @@ -9,6 +9,7 @@ src_lib_libtor_string_a_SOURCES = \ src/lib/string/compat_ctype.c \ src/lib/string/compat_string.c \ src/lib/string/util_string.c \ + src/lib/string/parse_int.c \ src/lib/string/printf.c \ src/lib/string/scanf.c @@ -21,5 +22,6 @@ noinst_HEADERS += \ src/lib/string/compat_ctype.h \ src/lib/string/compat_string.h \ src/lib/string/util_string.h \ + src/lib/string/parse_int.h \ src/lib/string/printf.h \ src/lib/string/scanf.h diff --git a/src/lib/string/parse_int.c b/src/lib/string/parse_int.c new file mode 100644 index 0000000000..e552730cc4 --- /dev/null +++ b/src/lib/string/parse_int.c @@ -0,0 +1,126 @@ +/* Copyright (c) 2003, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "lib/string/parse_int.h" + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +/* Helper: common code to check whether the result of a strtol or strtoul or + * strtoll is correct. */ +#define CHECK_STRTOX_RESULT() \ + /* Did an overflow occur? */ \ + if (errno == ERANGE) \ + goto err; \ + /* Was at least one character converted? */ \ + if (endptr == s) \ + goto err; \ + /* Were there unexpected unconverted characters? */ \ + if (!next && *endptr) \ + goto err; \ + /* Illogical (max, min) inputs? */ \ + if (max < min) \ + goto err; \ + /* Is r within limits? */ \ + if (r < min || r > max) \ + goto err; \ + if (ok) *ok = 1; \ + if (next) *next = endptr; \ + return r; \ + err: \ + if (ok) *ok = 0; \ + if (next) *next = endptr; \ + return 0 + +/** Extract a long from the start of <b>s</b>, in the given numeric + * <b>base</b>. If <b>base</b> is 0, <b>s</b> is parsed as a decimal, + * octal, or hex number in the syntax of a C integer literal. If + * there is unconverted data and <b>next</b> is provided, set + * *<b>next</b> to the first unconverted character. An error has + * occurred if no characters are converted; or if there are + * unconverted characters and <b>next</b> is NULL; or if the parsed + * value is not between <b>min</b> and <b>max</b>. When no error + * occurs, return the parsed value and set *<b>ok</b> (if provided) to + * 1. When an error occurs, return 0 and set *<b>ok</b> (if provided) + * to 0. + */ +long +tor_parse_long(const char *s, int base, long min, long max, + int *ok, char **next) +{ + char *endptr; + long r; + + if (base < 0) { + if (ok) + *ok = 0; + return 0; + } + + errno = 0; + r = strtol(s, &endptr, base); + CHECK_STRTOX_RESULT(); +} + +/** As tor_parse_long(), but return an unsigned long. */ +unsigned long +tor_parse_ulong(const char *s, int base, unsigned long min, + unsigned long max, int *ok, char **next) +{ + char *endptr; + unsigned long r; + + if (base < 0) { + if (ok) + *ok = 0; + return 0; + } + + errno = 0; + r = strtoul(s, &endptr, base); + CHECK_STRTOX_RESULT(); +} + +/** As tor_parse_long(), but return a double. */ +double +tor_parse_double(const char *s, double min, double max, int *ok, char **next) +{ + char *endptr; + double r; + + errno = 0; + r = strtod(s, &endptr); + CHECK_STRTOX_RESULT(); +} + +/** As tor_parse_long, but return a uint64_t. Only base 10 is guaranteed to + * work for now. */ +uint64_t +tor_parse_uint64(const char *s, int base, uint64_t min, + uint64_t max, int *ok, char **next) +{ + char *endptr; + uint64_t r; + + if (base < 0) { + if (ok) + *ok = 0; + return 0; + } + + errno = 0; +#ifdef HAVE_STRTOULL + r = (uint64_t)strtoull(s, &endptr, base); +#elif defined(_WIN32) + r = (uint64_t)_strtoui64(s, &endptr, base); +#elif SIZEOF_LONG == 8 + r = (uint64_t)strtoul(s, &endptr, base); +#else +#error "I don't know how to parse 64-bit numbers." +#endif /* defined(HAVE_STRTOULL) || ... */ + + CHECK_STRTOX_RESULT(); +} diff --git a/src/lib/string/parse_int.h b/src/lib/string/parse_int.h new file mode 100644 index 0000000000..6f56fc32a8 --- /dev/null +++ b/src/lib/string/parse_int.h @@ -0,0 +1,20 @@ +/* Copyright (c) 2003, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_PARSE_INT_H +#define TOR_PARSE_INT_H + +#include "lib/cc/torint.h" + +long tor_parse_long(const char *s, int base, long min, + long max, int *ok, char **next); +unsigned long tor_parse_ulong(const char *s, int base, unsigned long min, + unsigned long max, int *ok, char **next); +double tor_parse_double(const char *s, double min, double max, int *ok, + char **next); +uint64_t tor_parse_uint64(const char *s, int base, uint64_t min, + uint64_t max, int *ok, char **next); + +#endif |