Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Factorize code for parsing values with units.
[simgrid.git] / src / surf / surfxml_parse.c
index a8d507a..95080a4 100644 (file)
@@ -4,6 +4,8 @@
 /* This program is free software; you can redistribute it and/or modify it
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
+#include <errno.h>
+#include <math.h>
 #include <stdarg.h> /* va_arg */
 
 #include "xbt/misc.h"
@@ -61,173 +63,96 @@ int surf_parse_get_int(const char *string) {
   return res;
 }
 
-double surf_parse_get_time(const char *string) {
-  size_t len = strlen(string);
-  char* tmp = xbt_malloc(sizeof(char) * (len + 1));
-  strcpy(tmp, string);
-  if (!strcmp(tmp + len - 2, "ps")) {
-    tmp[len-2] = 0;
-    return surf_parse_get_double(tmp) * 1E-12;
-  }
-  if (!strcmp(tmp + len - 2, "ns")) {
-    tmp[len-2] = 0;
-    return surf_parse_get_double(tmp) * 1E-9;
-  }
-  if (!strcmp(tmp + len - 2, "us")) {
-    tmp[len-2] = 0;
-    return surf_parse_get_double(tmp) * 1E-6;
-  }
-  if (!strcmp(tmp + len - 2, "ms")) {
-    tmp[len-2] = 0;
-    return surf_parse_get_double(tmp) * 1E-3;
-  }
-  if (!strcmp(tmp + len - 1, "s")) {
-    tmp[len-1] = 0;    
-    return surf_parse_get_double(tmp);
-  }
-  if (!strcmp(tmp + len - 1, "m")) {
-    tmp[len-1] = 0;    
-    return surf_parse_get_double(tmp) * 60;
-  }
-  if (!strcmp(tmp + len - 1, "h")) {
-    tmp[len-1] = 0;    
-    return surf_parse_get_double(tmp) * 3600;
-  }
-  if (!strcmp(tmp + len - 1, "d")) {
-    tmp[len-1] = 0;    
-    return surf_parse_get_double(tmp) * 86400;
-  }
-  if (!strcmp(tmp + len - 1, "w")) {
-    tmp[len-1] = 0;    
-    return surf_parse_get_double(tmp) * 604800;
+struct unit_scale {
+  const char *unit;
+  double scale;
+};
+
+/* Note: field `unit' for the last element of parametre `units' should be
+ * NULL. */
+static double surf_parse_get_value_with_unit(const char *string,
+                                             const struct unit_scale *units)
+{
+  char* ptr;
+  double res;
+  int i;
+  errno = 0;
+  res = strtod(string, &ptr);
+  if (errno == ERANGE)
+    surf_parse_error("value out of range: %s", string);
+  if (ptr == string)
+    surf_parse_error("cannot parse number: %s", string);
+  for (i = 0; units[i].unit != NULL && strcmp(ptr, units[i].unit) != 0; i++) {
   }
-  return surf_parse_get_double(tmp);
+  if (units[i].unit != NULL)
+    res *= units[i].scale;
+  else
+    surf_parse_error("unknown unit: %s", ptr);
+  return res;
 }
 
-double surf_parse_get_bandwidth(const char *string) {
-  size_t len = strlen(string);
-  char* tmp = xbt_malloc(sizeof(char) * (len + 1));
-  strcpy(tmp, string);
-  if (!strcmp(tmp + len - 4, "KBps")) {
-    tmp[len-4] = 0;
-    return surf_parse_get_double(tmp) * 1E3;
-  }
-  if (!strcmp(tmp + len - 4, "MBps")) {
-    tmp[len-4] = 0;
-    return surf_parse_get_double(tmp) * 1E6;
-  }
-  if (!strcmp(tmp + len - 4, "GBps")) {
-    tmp[len-4] = 0;
-    return surf_parse_get_double(tmp) * 1E9;
-  }
-  if (!strcmp(tmp + len - 4, "TBps")) {
-    tmp[len-4] = 0;
-    return surf_parse_get_double(tmp) * 1E12;
-  }
-  if (!strcmp(tmp + len - 3, "Bps")) {
-    tmp[len-3] = 0;
-    return surf_parse_get_double(tmp);
-  }
-  if (!strcmp(tmp + len - 4, "kbps")) {
-    tmp[len-4] = 0;
-    return surf_parse_get_double(tmp) * 0.125 * 1E3;
-  }
-  if (!strcmp(tmp + len - 4, "mbps")) {
-    tmp[len-4] = 0;
-    return surf_parse_get_double(tmp) * 0.125 * 1E6;
-  }
-  if (!strcmp(tmp + len - 4, "gbps")) {
-    tmp[len-4] = 0;
-    return surf_parse_get_double(tmp) * 0.125 * 1E9;
-  }
-  if (!strcmp(tmp + len - 4, "tbps")) {
-    tmp[len-4] = 0;
-    return surf_parse_get_double(tmp) * 0.125 * 1E12;
-  }
-  if (!strcmp(tmp + len - 3, "bps")) {
-    tmp[len-3] = 0;
-    return surf_parse_get_double(tmp) * 0.125;
-  }
-  return surf_parse_get_double(tmp);
+double surf_parse_get_time(const char *string)
+{
+  const struct unit_scale units[] = {
+    { "w",  7 * 24 * 60 * 60 },
+    { "d",  24 * 60 * 60 },
+    { "h",  60 * 60 },
+    { "m",  60 },
+    { "s",  1.0 },
+    { "",   1.0 },              /* default unit is seconds */
+    { "ms", 1e-3 },
+    { "us", 1e-6 },
+    { "ns", 1e-9 },
+    { "ps", 1e-12 },
+    { NULL, 0 }
+  };
+  return surf_parse_get_value_with_unit(string, units);
 }
 
-double surf_parse_get_power(const char *string) {
-  size_t len = strlen(string);
-  char* tmp = xbt_malloc(sizeof(char) * (len + 1));
-  strcpy(tmp, string);
-  if (!strcmp(tmp + len - 9, "kiloflops")) {
-    tmp[len-9] = 0;
-    return surf_parse_get_double(tmp) * 1E3;
-  }
-  if (!strcmp(tmp + len - 9, "megaflops")) {
-    tmp[len-9] = 0;
-    return surf_parse_get_double(tmp) * 1E6;
-  }
-  if (!strcmp(tmp + len - 9, "gigaflops")) {
-    tmp[len-9] = 0;
-    return surf_parse_get_double(tmp) * 1E9;
-  }
-  if (!strcmp(tmp + len - 9, "teraflops")) {
-    tmp[len-9] = 0;
-    return surf_parse_get_double(tmp) * 1E12;
-  }
-  if (!strcmp(tmp + len - 9, "petaflops")) {
-    tmp[len-9] = 0;
-    return surf_parse_get_double(tmp) * 1E15;
-  }
-  if (!strcmp(tmp + len - 9, "exaflops")) {
-    tmp[len-9] = 0;
-    return surf_parse_get_double(tmp) * 1E18;
-  }
-  if (!strcmp(tmp + len - 9, "zettaflops")) {
-    tmp[len-9] = 0;
-    return surf_parse_get_double(tmp) * 1E21;
-  }
-  if (!strcmp(tmp + len - 9, "yottaflops")) {
-    tmp[len-9] = 0;
-    return surf_parse_get_double(tmp) * 1E24;
-  }
-  if (!strcmp(tmp + len - 5, "flops")) {
-    tmp[len-5] = 0;
-    return surf_parse_get_double(tmp);
-  }
-  if (!strcmp(tmp + len - 2, "kf")) {
-    tmp[len-2] = 0;
-    return surf_parse_get_double(tmp) * 1E3;
-  }
-  if (!strcmp(tmp + len - 2, "mf")) {
-    tmp[len-2] = 0;
-    return surf_parse_get_double(tmp) * 1E6;
-  }
-  if (!strcmp(tmp + len - 2, "gf")) {
-    tmp[len-2] = 0;
-    return surf_parse_get_double(tmp) * 1E9;
-  }
-  if (!strcmp(tmp + len - 2, "tf")) {
-    tmp[len-2] = 0;
-    return surf_parse_get_double(tmp) * 1E12;
-  }
-  if (!strcmp(tmp + len - 2, "pf")) {
-    tmp[len-2] = 0;
-    return surf_parse_get_double(tmp) * 1E15;
-  }
-  if (!strcmp(tmp + len - 2, "ef")) {
-    tmp[len-2] = 0;
-    return surf_parse_get_double(tmp) * 1E18;
-  }
-  if (!strcmp(tmp + len - 2, "zf")) {
-    tmp[len-2] = 0;
-    return surf_parse_get_double(tmp) * 1E21;
-  }
-  if (!strcmp(tmp + len - 2, "yf")) {
-    tmp[len-2] = 0;
-    return surf_parse_get_double(tmp) * 1E24;
-  }
-  if (!strcmp(tmp + len - 1, "f")) {
-    tmp[len-1] = 0;
-    return surf_parse_get_double(tmp);
-  }
-  return surf_parse_get_double(tmp);
+double surf_parse_get_bandwidth(const char *string)
+{
+  const struct unit_scale units[] = {
+    { "TBps",  1e12 },
+    { "GBps",  1e9 },
+    { "MBps",  1e6 },
+    { "KBps",  1e3 },
+    { "Bps",   1.0 },
+    { "",      1.0 },           /* default unit is bytes ber second */
+    { "tbps",  0.125 * 1e12 },
+    { "gbps",  0.125 * 1e9 },
+    { "mbps",  0.125 * 1e6 },
+    { "kbps",  0.125 * 1e3 },
+    { "bps",   0.125 },
+    { NULL,    0 }
+  };
+  return surf_parse_get_value_with_unit(string, units);
+}
+
+double surf_parse_get_power(const char *string)
+{
+  const struct unit_scale units[] = {
+    { "yottaflops", 1e24 },
+    { "yf",         1e24 },
+    { "zettaflops", 1e21 },
+    { "zf",         1e21 },
+    { "exaflops",   1e18 },
+    { "ef",         1e18 },
+    { "petaflops",  1e15 },
+    { "pf",         1e15 },
+    { "teraflops",  1e12 },
+    { "tf",         1e12 },
+    { "gigaflops",  1e9 },
+    { "gf",         1e9 },
+    { "megaflops",  1e6 },
+    { "mf",         1e6 },
+    { "kiloflops",  1e3 },
+    { "kf",         1e3 },
+    { "flops",      1.0 },
+    { "f",          1.0 },
+    { "",           1.0 },      /* default unit is flops */
+    { NULL,         0 }
+  };
+  return surf_parse_get_value_with_unit(string, units);
 }
 
 /*