diff options
Diffstat (limited to 'src/ot_scan.c')
| -rw-r--r-- | src/ot_scan.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/ot_scan.c b/src/ot_scan.c new file mode 100644 index 0000000..3b8e87c --- /dev/null +++ b/src/ot_scan.c | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | /* This software was written by Dirk Engling <erdgeist@erdgeist.org> | ||
| 2 | It is considered beerware. Prost. Skol. Cheers or whatever. */ | ||
| 3 | |||
| 4 | /* System */ | ||
| 5 | #include <errno.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include <stdlib.h> | ||
| 8 | |||
| 9 | /* Opentracker */ | ||
| 10 | #include "ot_scan.h" | ||
| 11 | |||
| 12 | size_t scan_uint(const char *src, uint64_t *dest, uint64_t max) { | ||
| 13 | unsigned long long value; | ||
| 14 | char *end; | ||
| 15 | |||
| 16 | if (*src < '0' || *src > '9') | ||
| 17 | return 0; | ||
| 18 | |||
| 19 | errno = 0; | ||
| 20 | value = strtoull(src, &end, 10); | ||
| 21 | |||
| 22 | if (errno == ERANGE || value > (unsigned long long)max) | ||
| 23 | return 0; | ||
| 24 | |||
| 25 | *dest = (uint64_t)value; | ||
| 26 | return (size_t)(end - src); | ||
| 27 | } | ||
| 28 | |||
| 29 | size_t scan_uint_bencode(const char *src, uint64_t *dest, uint64_t max) { | ||
| 30 | uint64_t value; | ||
| 31 | size_t consumed = scan_uint(src, &value, max); | ||
| 32 | |||
| 33 | /* bencode writes no leading zeros, so anything longer than a single digit | ||
| 34 | must not begin with one. */ | ||
| 35 | if (consumed > 1 && *src == '0') | ||
| 36 | return 0; | ||
| 37 | |||
| 38 | if (consumed) | ||
| 39 | *dest = value; | ||
| 40 | |||
| 41 | return consumed; | ||
| 42 | } | ||
| 43 | |||
| 44 | int scan_int(const char *src, size_t len, int64_t *dest) { | ||
| 45 | int64_t value = 0; | ||
| 46 | int negate = 0; | ||
| 47 | |||
| 48 | if (len && *src == '-') | ||
| 49 | --len, ++src, negate = 1; | ||
| 50 | if (!len) | ||
| 51 | return -1; | ||
| 52 | |||
| 53 | while (len--) { | ||
| 54 | if (*src < '0' || *src > '9') | ||
| 55 | return -1; | ||
| 56 | /* A twenty character field of nines does not fit, and silently wrapping | ||
| 57 | would magically heal a nonsense announce */ | ||
| 58 | if (value > (INT64_MAX - (*src - '0')) / 10) | ||
| 59 | return -1; | ||
| 60 | value = 10 * value + (*src++ - '0'); | ||
| 61 | } | ||
| 62 | |||
| 63 | *dest = negate ? -value : value; | ||
| 64 | return 0; | ||
| 65 | } | ||
