[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] [tor/master] Make tor_sscanf handle %x
Author: Nick Mathewson <nickm@xxxxxxxxxxxxxx>
Date: Mon, 11 Oct 2010 10:50:47 -0400
Subject: Make tor_sscanf handle %x
Commit: 8f76f31761f051d5b6a3280462db6adf95b19233
---
src/common/util.c | 22 +++++++++++++---------
src/test/test_util.c | 12 ++++++++++++
2 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/src/common/util.c b/src/common/util.c
index b5a3ade..fd6956c 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -2498,18 +2498,21 @@ digit_to_num(char d)
* success, store the result in <b>out</b>, advance bufp to the next
* character, and return 0. On failure, return -1. */
static int
-scan_unsigned(const char **bufp, unsigned *out, int width)
+scan_unsigned(const char **bufp, unsigned *out, int width, int base)
{
unsigned result = 0;
int scanned_so_far = 0;
+ const int hex = base==16;
+ tor_assert(base == 10 || base == 16);
if (!bufp || !*bufp || !out)
return -1;
if (width<0)
width=MAX_SCANF_WIDTH;
- while (**bufp && TOR_ISDIGIT(**bufp) && scanned_so_far < width) {
- int digit = digit_to_num(*(*bufp)++);
- unsigned new_result = result * 10 + digit;
+ while (**bufp && (hex?TOR_ISXDIGIT(**bufp):TOR_ISDIGIT(**bufp))
+ && scanned_so_far < width) {
+ int digit = hex?hex_decode_digit(*(*bufp)++):digit_to_num(*(*bufp)++);
+ unsigned new_result = result * base + digit;
if (new_result > UINT32_MAX || new_result < result)
return -1; /* over/underflow. */
result = new_result;
@@ -2571,11 +2574,12 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap)
if (!width) /* No zero-width things. */
return -1;
}
- if (*pattern == 'u') {
+ if (*pattern == 'u' || *pattern == 'x') {
unsigned *u = va_arg(ap, unsigned *);
+ const int base = (*pattern == 'u') ? 10 : 16;
if (!*buf)
return n_matched;
- if (scan_unsigned(&buf, u, width)<0)
+ if (scan_unsigned(&buf, u, width, base)<0)
return n_matched;
++pattern;
++n_matched;
@@ -2612,9 +2616,9 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap)
/** Minimal sscanf replacement: parse <b>buf</b> according to <b>pattern</b>
* and store the results in the corresponding argument fields. Differs from
- * sscanf in that it: Only handles %u and %Ns. Does not handle arbitrarily
- * long widths. %u does not consume any space. Is locale-independent.
- * Returns -1 on malformed patterns.
+ * sscanf in that it: Only handles %u and %x and %Ns. Does not handle
+ * arbitrarily long widths. %u and %x do not consume any space. Is
+ * locale-independent. Returns -1 on malformed patterns.
*
* (As with other locale-independent functions, we need this to parse data that
* is in ASCII without worrying that the C library's locale-handling will make
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 68a0ca2..5701f12 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -833,6 +833,18 @@ test_util_sscanf(void)
test_eq(u2, 3u);
test_eq(u3, 99u);
+ /* %x should work. */
+ r = tor_sscanf("1234 02aBcdEf", "%x %x", &u1, &u2);
+ test_eq(r, 2);
+ test_eq(u1, 0x1234);
+ test_eq(u2, 0x2ABCDEF);
+ /* Width works on %x */
+ r = tor_sscanf("f00dcafe444", "%4x%4x%u", &u1, &u2, &u3);
+ test_eq(r, 3);
+ test_eq(u1, 0xf00d);
+ test_eq(u2, 0xcafe);
+ test_eq(u3, 444);
+
r = tor_sscanf("99% fresh", "%3u%% fresh", &u1); /* percents are scannable.*/
test_eq(r, 1);
test_eq(u1, 99);
--
1.7.1