add units to time, use configuration time api where appropriate, fixing Mantis #1875
[oweals/gnunet.git] / src / util / strings.c
index a95981690be1f10b95f2f0bf2687937379d2e719..58a4847bcbbe8e850e1fa73057072a03705d0899 100644 (file)
 #include "gnunet_common.h"
 #include "gnunet_strings_lib.h"
 
+#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
+
+#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
+
 
 /**
  * Fill a buffer of the given size with
@@ -96,8 +100,8 @@ GNUNET_STRINGS_buffer_fill (char *buffer, size_t size, unsigned int count, ...)
  *         in the buffer, or 0 on error.
  */
 unsigned int
-GNUNET_STRINGS_buffer_tokenize (const char *buffer,
-                                size_t size, unsigned int count, ...)
+GNUNET_STRINGS_buffer_tokenize (const char *buffer, size_t size,
+                                unsigned int count, ...)
 {
   unsigned int start;
   unsigned int needed;
@@ -142,19 +146,19 @@ GNUNET_STRINGS_byte_size_fancy (unsigned long long size)
   if (size > 5 * 1024)
   {
     size = size / 1024;
-    unit = _( /* size unit */ "KiB");
+    unit = "KiB";
     if (size > 5 * 1024)
     {
       size = size / 1024;
-      unit = _( /* size unit */ "MiB");
+      unit = "MiB";
       if (size > 5 * 1024)
       {
         size = size / 1024;
-        unit = _( /* size unit */ "GiB");
+        unit = "GiB";
         if (size > 5 * 1024)
         {
           size = size / 1024;
-          unit = _( /* size unit */ "TiB");
+          unit = "TiB";
         }
       }
     }
@@ -165,6 +169,165 @@ 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, " "))
+  {
+    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))
+      {
+       GNUNET_free (in);
+        return GNUNET_SYSERR;   /* expected number */
+      }
+    }
+  }
+  ret += last;
+  *size = ret;
+  GNUNET_free (in);
+  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))
+      {
+       GNUNET_free (in);
+        return GNUNET_SYSERR;   /* expected number */
+      }
+    }
+  }
+  ret += last;
+  rtime->rel_value = (uint64_t) ret;
+  GNUNET_free (in);
+  return GNUNET_OK;
+}
+
+
 /**
  * Convert the len characters long character sequence
  * given in input that is in the given charset
@@ -188,9 +351,9 @@ GNUNET_STRINGS_to_utf8 (const char *input, size_t len, const char *charset)
   cd = iconv_open ("UTF-8", charset);
   if (cd == (iconv_t) - 1)
   {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "iconv_open");
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _("Character set requested was `%s'\n"), charset);
+    LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "iconv_open");
+    LOG (GNUNET_ERROR_TYPE_WARNING, _("Character set requested was `%s'\n"),
+         charset);
     ret = GNUNET_malloc (len + 1);
     memcpy (ret, input, len);
     ret[len] = '\0';
@@ -208,7 +371,7 @@ GNUNET_STRINGS_to_utf8 (const char *input, size_t len, const char *charset)
 #endif
              &len, &itmp, &finSize) == SIZE_MAX)
   {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "iconv");
+    LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "iconv");
     iconv_close (cd);
     GNUNET_free (tmp);
     ret = GNUNET_malloc (len + 1);
@@ -221,7 +384,7 @@ GNUNET_STRINGS_to_utf8 (const char *input, size_t len, const char *charset)
   ret[tmpSize - finSize] = '\0';
   GNUNET_free (tmp);
   if (0 != iconv_close (cd))
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "iconv_close");
+    LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "iconv_close");
   return ret;
 #else
   ret = GNUNET_malloc (len + 1);
@@ -266,9 +429,8 @@ GNUNET_STRINGS_filename_expand (const char *fil)
     fm = getenv ("HOME");
     if (fm == NULL)
     {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Failed to expand `$HOME': environment variable `HOME' not set"));
+      LOG (GNUNET_ERROR_TYPE_WARNING,
+           _("Failed to expand `$HOME': environment variable `HOME' not set"));
       return NULL;
     }
     fm = GNUNET_strdup (fm);
@@ -304,7 +466,7 @@ GNUNET_STRINGS_filename_expand (const char *fil)
     }
     if (fm == NULL)
     {
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "getcwd");
+      LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "getcwd");
       buffer = getenv ("PWD");  /* alternative */
       if (buffer != NULL)
         fm = GNUNET_strdup (buffer);
@@ -314,8 +476,7 @@ GNUNET_STRINGS_filename_expand (const char *fil)
   }
   n = strlen (fm) + 1 + strlen (fil_ptr) + 1;
   buffer = GNUNET_malloc (n);
-  GNUNET_snprintf (buffer, n, "%s%s%s",
-                   fm,
+  GNUNET_snprintf (buffer, n, "%s%s%s", fm,
                    (fm[strlen (fm) - 1] ==
                     DIR_SEPARATOR) ? "" : DIR_SEPARATOR_STR, fil_ptr);
   GNUNET_free (fm);
@@ -326,7 +487,7 @@ GNUNET_STRINGS_filename_expand (const char *fil)
   if ((lRet = plibc_conv_to_win_path (fil, fn)) != ERROR_SUCCESS)
   {
     SetErrnoFromWinError (lRet);
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "plibc_conv_to_win_path");
+    LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "plibc_conv_to_win_path");
     return NULL;
   }
   /* is the path relative? */
@@ -338,7 +499,7 @@ GNUNET_STRINGS_filename_expand (const char *fil)
     if (lRet + strlen (fn) + 1 > (MAX_PATH + 1))
     {
       SetErrnoFromWinError (ERROR_BUFFER_OVERFLOW);
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "GetCurrentDirectory");
+      LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "GetCurrentDirectory");
       return NULL;
     }
     buffer = GNUNET_malloc (MAX_PATH + 1);