[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] [tor/master] Revise parsing of time and memory units to handle spaces.



Author: Nick Mathewson <nickm@xxxxxxxxxxxxxx>
Date: Mon, 31 Aug 2009 00:18:55 -0400
Subject: Revise parsing of time and memory units to handle spaces.
Commit: 00b37f071d2c96612892340f5f883b869033d6a1

When we added support for fractional units (like 1.5 MB) I broke
support for giving units with no space (like 2MB).  This patch should
fix that.  It also adds a propoer tor_parse_double().

Fix for bug 1076.  Bugfix on 0.2.2.1-alpha.
---
 ChangeLog         |    2 ++
 src/common/util.c |   11 +++++++++++
 src/common/util.h |    2 ++
 src/or/config.c   |   33 +++++++++++++--------------------
 4 files changed, 28 insertions(+), 20 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index fe07b9e..545f49a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,8 @@ Changes in version 0.2.2.2-alpha - 2009-09-??
     - Fix an extremely rare infinite recursion bug that could occur if
       we tried to log a message after shutting down the log subsystem.
       Found by Matt Edman. Bugfix on 0.2.0.16-alpha.
+    - Fix parsing for memory or time units given without a space between
+      the number and the unit.  Bugfix on 0.2.2.1-alpha; fixes bug 1076.
 
 
 Changes in version 0.2.2.1-alpha - 2009-08-26
diff --git a/src/common/util.c b/src/common/util.c
index 234180c..19839e2 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -735,6 +735,17 @@ tor_parse_ulong(const char *s, int base, unsigned long min,
   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;
+
+  r = strtod(s, &endptr);
+  CHECK_STRTOX_RESULT();
+}
+
 /** As tor_parse_log, but return a unit64_t.  Only base 10 is guaranteed to
  * work for now. */
 uint64_t
diff --git a/src/common/util.h b/src/common/util.h
index c7741a6..bb384a2 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -182,6 +182,8 @@ 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);
 const char *hex_str(const char *from, size_t fromlen) ATTR_NONNULL((1));
diff --git a/src/or/config.c b/src/or/config.c
index b7317c7..b475a33 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -4860,35 +4860,28 @@ config_parse_units(const char *val, struct unit_table_t *u, int *ok)
   uint64_t v = 0;
   double d = 0;
   int use_float = 0;
-
-  smartlist_t *sl;
+  char *cp;
 
   tor_assert(ok);
-  sl = smartlist_create();
-  smartlist_split_string(sl, val, NULL,
-                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
 
-  if (smartlist_len(sl) < 1 || smartlist_len(sl) > 2) {
-    *ok = 0;
-    goto done;
-  }
-
-  v = tor_parse_uint64(smartlist_get(sl,0), 10, 0, UINT64_MAX, ok, NULL);
-  if (!*ok) {
-    int r = sscanf(smartlist_get(sl,0), "%lf", &d);
-    if (r == 0 || d < 0)
+  v = tor_parse_uint64(val, 10, 0, UINT64_MAX, ok, &cp);
+  if (!*ok || (cp && *cp == '.')) {
+    d = tor_parse_double(val, 0, UINT64_MAX, ok, &cp);
+    if (!*ok)
       goto done;
     use_float = 1;
   }
 
-  if (smartlist_len(sl) == 1) {
+  if (!cp) {
     *ok = 1;
     v = use_float ? DBL_TO_U64(d) :  v;
     goto done;
   }
 
+  cp = (char*) eat_whitespace(cp);
+
   for ( ;u->unit;++u) {
-    if (!strcasecmp(u->unit, smartlist_get(sl,1))) {
+    if (!strcasecmp(u->unit, cp)) {
       if (use_float)
         v = u->multiplier * d;
       else
@@ -4897,11 +4890,9 @@ config_parse_units(const char *val, struct unit_table_t *u, int *ok)
       goto done;
     }
   }
-  log_warn(LD_CONFIG, "Unknown unit '%s'.", (char*)smartlist_get(sl,1));
+  log_warn(LD_CONFIG, "Unknown unit '%s'.", cp);
   *ok = 0;
  done:
-  SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
-  smartlist_free(sl);
 
   if (*ok)
     return v;
@@ -4916,7 +4907,9 @@ config_parse_units(const char *val, struct unit_table_t *u, int *ok)
 static uint64_t
 config_parse_memunit(const char *s, int *ok)
 {
-  return config_parse_units(s, memory_units, ok);
+  uint64_t u = config_parse_units(s, memory_units, ok);
+  printf("%s -> %d\n", s, (int)u);
+  return u;
 }
 
 /** Parse a string in the format "number unit", where unit is a unit of time.
-- 
1.5.6.5