implementing time and size parsers for #1875
authorChristian Grothoff <christian@grothoff.org>
Thu, 3 Nov 2011 21:10:27 +0000 (21:10 +0000)
committerChristian Grothoff <christian@grothoff.org>
Thu, 3 Nov 2011 21:10:27 +0000 (21:10 +0000)
src/include/gnunet_configuration_lib.h
src/include/gnunet_strings_lib.h
src/util/configuration.c
src/util/strings.c
src/util/test_configuration.c
src/util/test_configuration_data.conf

index 7167d8bd6c6c5f400a4b9c06f3f90f62623dbacc..f8f302a187b2ab675f4f21f40c79eab2cc5ad69e 100644 (file)
@@ -226,6 +226,23 @@ GNUNET_CONFIGURATION_get_value_time (const struct GNUNET_CONFIGURATION_Handle
                                      struct GNUNET_TIME_Relative *time);
 
 
+
+/**
+ * Get a configuration value that should be a size in bytes.
+ *
+ * @param cfg configuration to inspect
+ * @param section section of interest
+ * @param option option of interest
+ * @param size set to the size in bytes as stored in the configuration
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ */
+int
+GNUNET_CONFIGURATION_get_value_size (const struct GNUNET_CONFIGURATION_Handle
+                                     *cfg, const char *section,
+                                     const char *option,
+                                     unsigned long long *size);
+
+
 /**
  * Test if we have a value for a particular option
  *
@@ -337,6 +354,7 @@ GNUNET_CONFIGURATION_get_value_yesno (const struct GNUNET_CONFIGURATION_Handle
                                       *cfg, const char *section,
                                       const char *option);
 
+
 /**
  * Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR"
  * where either in the "PATHS" section or the environtment
@@ -378,6 +396,7 @@ GNUNET_CONFIGURATION_set_value_string (struct GNUNET_CONFIGURATION_Handle *cfg,
                                        const char *section, const char *option,
                                        const char *value);
 
+
 /**
  * Remove a filename from a configuration value that
  * represents a list of filenames
index 6413fb1026cd9011190b66fd61508f7c41fa21a7..637d4f7de0122f702373ff2f4e1260ec2382b8e9 100644 (file)
@@ -50,6 +50,18 @@ extern "C"
 #include "gnunet_time_lib.h"
 
 
+/**
+ * Convert a given fancy human-readable size to bytes.
+ *
+ * @param fancy_size human readable string (i.e. 1 MB)
+ * @param size set to the size in bytes
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ */
+int
+GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size,
+                                   unsigned long long *size);
+
+
 /**
  * Convert a given filesize into a fancy human-readable format.
  *
@@ -85,6 +97,7 @@ GNUNET_STRINGS_to_utf8 (const char *input, size_t len, const char *charset);
 char *
 GNUNET_STRINGS_filename_expand (const char *fil);
 
+
 /**
  * Fill a buffer of the given size with
  * count 0-terminated strings (given as varargs).
index a269ed0361eada3470552b70089205cfa070c559..ba3aa7f45fd60c596dbf483f9805c72f88555bb5 100644 (file)
@@ -731,16 +731,34 @@ GNUNET_CONFIGURATION_get_value_time (const struct GNUNET_CONFIGURATION_Handle
   e = findEntry (cfg, section, option);
   if (e == NULL)
     return GNUNET_SYSERR;
-  if ((0 == strcasecmp (e->val, "infinity")) ||
-      (0 == strcasecmp (e->val, "forever")))
-    {
-      *time = GNUNET_TIME_UNIT_FOREVER_REL;
-      return GNUNET_OK;
-    }
-  if (1 != SSCANF (e->val, "%llu", &num))
+
+  return GNUNET_STRINGS_fancy_time_to_relative (e->val,
+                                               time);
+}
+
+
+/**
+ * Get a configuration value that should be a size in bytes.
+ *
+ * @param cfg configuration to inspect
+ * @param section section of interest
+ * @param option option of interest
+ * @param size set to the size in bytes as stored in the configuration
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ */
+int
+GNUNET_CONFIGURATION_get_value_size (const struct GNUNET_CONFIGURATION_Handle
+                                     *cfg, const char *section,
+                                     const char *option,
+                                     unsigned long long *size)
+{
+  struct ConfigEntry *e;
+
+  e = findEntry (cfg, section, option);
+  if (e == NULL)
     return GNUNET_SYSERR;
-  time->rel_value = (uint64_t) num;
-  return GNUNET_OK;
+  return GNUNET_STRINGS_fancy_size_to_bytes (e->val,
+                                            size);
 }
 
 
index 9e9aac3b18e7ff2e1f10bc65d61b91369ff6e490..63ebfc1e269175459c029385d220b2076f55dcb8 100644 (file)
@@ -170,6 +170,132 @@ GNUNET_STRINGS_byte_size_fancy (unsigned long long size)
 }
 
 
+/**
+ * Convert a given fancy human-readable size to bytes.
+ *
+ * @param fancy_size human readable string (i.e. 1 MB)
+ * @param size set to the size in bytes
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ */
+int
+GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size,
+                                   unsigned long long *size)
+{
+  struct { 
+    const char *name; 
+    unsigned long long value;
+  } table[] = {
+    { "B", 1 },
+    { "KiB", 1024 },
+    { "kB",  1000 },
+    { "MiB", 1024 * 1024 },
+    { "MB",  1000 * 1000 },
+    { "GiB", 1024 * 1024 * 1024 },
+    { "GB",  1000 * 1000 * 1000 },
+    { "TiB", 1024LL * 1024LL * 1024LL * 1024LL },
+    { "TB",  1000LL * 1000LL * 1000LL * 1024LL },
+    { "PiB", 1024LL * 1024LL * 1024LL * 1024LL * 1024LL },
+    { "PB",  1000LL * 1000LL * 1000LL * 1024LL * 1000LL},
+    { "EiB", 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * 1024LL},
+    { "EB",  1000LL * 1000LL * 1000LL * 1024LL * 1000LL * 1000LL },
+    { NULL, 0 }
+  };
+  unsigned long long ret;
+  char *in;
+  const char *tok;
+  unsigned long long last;
+  unsigned int i;
+
+  ret = 0;
+  last = 0;
+  in = GNUNET_strdup (fancy_size);
+  for (tok = strtok (in, " "); tok != NULL; tok = strtok (NULL, " "))
+  {
+    fprintf (stderr, "%s - %llu %llu\n", tok, ret, last);
+    i=0;
+    while ( (table[i].name != NULL) &&
+           (0 != strcasecmp (table[i].name, tok) ) )
+      i++;
+    if (table[i].name != NULL)
+      last *= table[i].value;
+    else
+    {
+      ret += last;
+      last = 0;
+      if (1 != sscanf (tok, "%llu", &last))
+       return GNUNET_SYSERR; /* expected number */
+    }      
+  }
+  ret += last;
+  *size = ret;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Convert a given fancy human-readable time to our internal
+ * representation.
+ *
+ * @param fancy_size human readable string (i.e. 1 minute)
+ * @param rtime set to the relative time
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ */
+int
+GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_size,
+                                      struct GNUNET_TIME_Relative *rtime)
+{
+  struct { 
+    const char *name; 
+    unsigned long long value;
+  } table[] = {
+    { "ms", 1 },
+    { "s", 1000 },
+    { "\"", 1000 },
+    { "min",  60 * 1000 },
+    { "minutes", 60 * 1000 },
+    { "'", 60 * 1000 },
+    { "h", 60 * 60 * 1000 },
+    { "d", 24 * 60 * 60 * 1000 },
+    { "a", 31557600 /* year */ },
+    { NULL, 0 }
+  };
+  unsigned long long ret;
+  char *in;
+  const char *tok;
+  unsigned long long last;
+  unsigned int i;
+  
+  if ((0 == strcasecmp (fancy_size, "infinity")) ||
+      (0 == strcasecmp (fancy_size, "forever")))
+    {
+      *rtime = GNUNET_TIME_UNIT_FOREVER_REL;
+      return GNUNET_OK;
+    }
+  ret = 0;
+  last = 0;
+  in = GNUNET_strdup (fancy_size);
+  for (tok = strtok (in, " "); tok != NULL; tok = strtok (NULL, " "))
+  {
+    i=0;
+    while ( (table[i].name != NULL) &&
+           (0 != strcasecmp (table[i].name, tok) ) )
+      i++;
+    if (table[i].name != NULL)
+      last *= table[i].value;
+    else
+    {
+      ret += last;
+      last = 0;
+      if (1 != sscanf (tok, "%llu", &last))
+       return GNUNET_SYSERR; /* expected number */
+    }      
+  }
+  ret += last;
+  rtime->rel_value = (uint64_t) ret;
+  return GNUNET_OK;
+}
+
+
 /**
  * Convert the len characters long character sequence
  * given in input that is in the given charset
index 4a993923b265db5d2320f9b03a115571c2fb7713..9deb4fc35b765b2b170a33c63a80a9d7d4e63dcc 100644 (file)
@@ -337,6 +337,17 @@ testConfig ()
     }
   GNUNET_free (c);
 
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_size (cfg, "last", "size", &l))
+  {
+    GNUNET_break (0);
+    return 10;
+  }
+  if (l != 512 * 1024)
+  {
+    GNUNET_break (0);
+    return 11;
+  }
   return 0;
 }
 
index c3452c381a54c822641ec9da3d52310ce7817a93..517cbf0b0d6a44251c0061eeaf87bf7f08c1d442 100644 (file)
@@ -19,6 +19,7 @@ five=42
 test = $SUBST/world
 boom = "1 2 3 testing"
 trailing = YES 
+size = 512 KiB
 
 [FILENAMES]
 test = "/Hello /File\ Name /World"