]> mj.ucw.cz Git - libucw.git/commitdiff
xtypes: added first shot on unit parser
authorRobert Kessl <kesslr@centrum.cz>
Wed, 23 Jul 2014 10:10:10 +0000 (12:10 +0200)
committerRobert Kessl <kesslr@centrum.cz>
Wed, 23 Jul 2014 10:10:10 +0000 (12:10 +0200)
ucw/table-test-2.c
ucw/table-types.c
ucw/xtypes-basic.c
ucw/xtypes-test.c
ucw/xtypes.c
ucw/xtypes.h

index 35688734e5852e293c0528b81e9a98ab3bcf25a0..f7d6a6ed15edcb10456cf0047efffa342cc08697 100644 (file)
@@ -81,7 +81,7 @@ static void do_test2(void)
   out = bfdopen_shared(1, 4096);
   struct table *tbl = table_init(&test_tbl2);
   table_set_col_order_by_name(tbl, "");
-  const char *err = table_set_option_value(tbl, "cols", "size[kb],size[mb],size[gb],size[tb],ts[datetime],ts[timestamp]");
+  const char *err = table_set_option_value(tbl, "cols", "size[KB],size[MB],size[GB],size[TB],ts[datetime],ts[timestamp]");
   if(err) {
     opt_failure("err in table_set_option_value: '%s'.", err);
     abort();
index bcb2abb811ec01b04bfdefb812e090aad5b8901e..db07e01c8b486245ef7695675ed03e17f5759a96 100644 (file)
 
 /** xt_size **/
 
-static const char *unit_suffix[] = {
-  [SIZE_UNIT_BYTE] = "",
-  [SIZE_UNIT_KILOBYTE] = "KB",
-  [SIZE_UNIT_MEGABYTE] = "MB",
-  [SIZE_UNIT_GIGABYTE] = "GB",
-  [SIZE_UNIT_TERABYTE] = "TB"
-};
-
-static u64 unit_div[] = {
-  [SIZE_UNIT_BYTE] = 1LLU,
-  [SIZE_UNIT_KILOBYTE] = 1024LLU,
-  [SIZE_UNIT_MEGABYTE] = 1024LLU * 1024LLU,
-  [SIZE_UNIT_GIGABYTE] = 1024LLU * 1024LLU * 1024LLU,
-  [SIZE_UNIT_TERABYTE] = 1024LLU * 1024LLU * 1024LLU * 1024LLU
+struct unit_definition xtype_units_size[] = {
+  [SIZE_UNIT_BYTE] = { "", 1LLU, 1 },
+  [SIZE_UNIT_KILOBYTE] = { "KB", 1024LLU, 1 },
+  [SIZE_UNIT_MEGABYTE] = { "MB", 1024LLU * 1024LLU, 1 },
+  [SIZE_UNIT_GIGABYTE] = { "GB", 1024LLU * 1024LLU * 1024LLU, 1 },
+  [SIZE_UNIT_TERABYTE] = { "TB", 1024LLU * 1024LLU * 1024LLU * 1024LLU, 1 },
+  { 0, 0, 0 }
 };
 
 static const char *xt_size_format(void *src, u32 fmt, struct mempool *pool)
@@ -40,20 +33,20 @@ static const char *xt_size_format(void *src, u32 fmt, struct mempool *pool)
     return mp_printf(pool, "%"PRIu64, curr_val);
   }
 
-  uint out_type = SIZE_UNIT_BYTE;
+  uint out_units = SIZE_UNIT_BYTE;
 
   if(fmt == XTYPE_FMT_DEFAULT) {
-    curr_val = curr_val / unit_div[SIZE_UNIT_BYTE];
-    out_type = SIZE_UNIT_BYTE;
+    curr_val = curr_val;
+    out_units = SIZE_UNIT_BYTE;
   } else if(fmt == XTYPE_FMT_PRETTY) {
-    curr_val = curr_val / unit_div[SIZE_UNIT_BYTE];
-    out_type = SIZE_UNIT_BYTE;
+    curr_val = curr_val;
+    out_units = SIZE_UNIT_BYTE;
   } else if((fmt & SIZE_UNITS_FIXED) != 0) {
-    curr_val = curr_val / unit_div[fmt & ~SIZE_UNITS_FIXED];
-    out_type = fmt & ~SIZE_UNITS_FIXED;
+    curr_val = curr_val / xtype_units_size[fmt & ~SIZE_UNITS_FIXED].num;
+    out_units = fmt & ~SIZE_UNITS_FIXED;
   }
 
-  return mp_printf(pool, "%"PRIu64"%s", curr_val, unit_suffix[out_type]);
+  return mp_printf(pool, "%"PRIu64"%s", curr_val, xtype_units_size[out_units].unit);
 }
 
 static const char * xt_size_fmt_parse(const char *opt_str, u32 *dest, struct mempool *pool UNUSED)
@@ -62,19 +55,18 @@ static const char * xt_size_fmt_parse(const char *opt_str, u32 *dest, struct mem
     return "NULL is not supported as a column argument.";
   }
 
-  if(strlen(opt_str) == 0 || strcasecmp(opt_str, "b") == 0 || strcasecmp(opt_str, "bytes") == 0) {
+  if(strlen(opt_str) == 0 || strcmp(opt_str, "B") == 0 || strcmp(opt_str, "Bytes") == 0) {
     *dest = SIZE_UNIT_BYTE | SIZE_UNITS_FIXED;
     return NULL;
   }
 
-  for(uint i = SIZE_UNIT_BYTE; i <= SIZE_UNIT_TERABYTE; i++) {
-    if(strcasecmp(opt_str, unit_suffix[i]) == 0) {
-      *dest = i | SIZE_UNITS_FIXED;
-      return NULL;
-    }
+  int unit_idx = xtype_unit_parser(opt_str, xtype_units_size);
+  if(unit_idx == -1) {
+    return mp_printf(pool, "Unknown option '%s'", opt_str);
   }
 
-  return "Unknown option.";
+  *dest = unit_idx | SIZE_UNITS_FIXED;
+  return NULL;
 }
 
 static const char *xt_size_parse(const char *str, void *dest, struct mempool *pool UNUSED)
@@ -85,23 +77,26 @@ static const char *xt_size_parse(const char *str, void *dest, struct mempool *po
   if(str == units_start) {
     return mp_printf(pool, "Invalid value of size: '%s'.", str);
   }
+
+  if(errno == EINVAL) {
+    return "Error occured during parsing of size.";
+  }
+  if(errno == ERANGE) {
+    return "Error: size value either too large or too small.";
+  }
+
   if(*units_start == 0) {
     *(u64*) dest = (u64) parsed;
     return NULL;
   }
 
-  if(errno == EINVAL || errno == ERANGE) {
-    return mp_printf(pool, "Invalid value of size: '%s'.", str);
-  }
-
-  for(uint i = 0; i < ARRAY_SIZE(unit_suffix); i++) {
-    if(strcmp(unit_suffix[i], units_start) == 0) {
-      *(u64*) dest = parsed * unit_div[i];
-      return NULL;
-    }
+  int unit_idx = xtype_unit_parser(units_start, xtype_units_size);
+  if(unit_idx == -1) {
+    return mp_printf(pool, "Invalid format of size: '%s'.", str);
   }
 
-  return mp_printf(pool, "Invalid format of size: '%s'.", str);
+  *(u64*) dest = parsed * xtype_units_size[unit_idx].num;
+  return NULL;
 }
 
 TABLE_COL_BODY(size, u64)
@@ -158,12 +153,48 @@ static const char * xt_timestamp_fmt_parse(const char *opt_str, u32 *dest, struc
   return mp_printf(pool, "Invalid column format option: '%s'.", opt_str);
 }
 
+static const char *xt_timestamp_parse(const char *str, void *dest, struct mempool *pool UNUSED)
+{
+  errno = 0;
+  char *parse_end = NULL;
+  u64 parsed = strtol(str, &parse_end, 10);
+  if(str == parse_end) {
+    return mp_printf(pool, "Invalid value of timestamp: '%s'.", str);
+  }
+  if(errno == EINVAL) {
+    return "Error occured during parsing of size.";
+  }
+
+  if(errno == ERANGE) {
+    return "Error: size value either too large or too small.";
+  }
+
+  if(*parse_end == 0) {
+    *(u64*) dest = (u64) parsed;
+    return NULL;
+  }
+
+
+  struct tm parsed_time;
+  errno = 0;
+  parse_end = strptime(str, "%F %T", &parsed_time);
+  if(parse_end == NULL) {
+    return mp_printf(pool, "Invalid value of timestamp: '%s'.", str);
+  }
+
+  time_t tmp_time = mktime(&parsed_time);
+  *(u64*)dest = (u64) tmp_time;
+
+  return NULL;
+}
+
+
 TABLE_COL_BODY(timestamp, u64)
 
 const struct xtype xt_timestamp = {
   .size = sizeof(u64),
   .name = "timestamp",
-  //.parse = xt_timestamp_parse,
+  .parse = xt_timestamp_parse,
   .format = xt_timestamp_format,
   .parse_fmt = xt_timestamp_fmt_parse
 };
index c3dc1d6fb7fcb2025e94aee8a7a191987ed459b4..2792cd19109dd32aca0f785d81d0d4d2ba663908 100644 (file)
@@ -69,8 +69,8 @@ static const char *xt_double_parse(const char *str, void *dest, struct mempool *
   char *endptr = NULL;
   errno = 0;
   double result = strtod(str, &endptr);
-  if(*endptr != 0 || endptr == str) return "Could not parse double.";
-  if(errno == ERANGE) return "Could not parse double.";
+  if(*endptr != 0 || endptr == str) return "Could not parse floating point number.";
+  if(errno == ERANGE) return "Could not parse floating point number.";
 
   *((double *) dest) = result;
 
index bd7411b1f33acfd7c0da586ec5bc612e3be285c1..f1376c0d8c722caa5db3f07e113fe2738fd41105 100644 (file)
@@ -16,7 +16,6 @@
 #include <stdlib.h>
 #include <inttypes.h>
 
-
 static void test_size_correct(struct fastbuf *out)
 {
   static const char *size_strs[] = {
index 8e2f63ce1ed23e7e7b6990f277ba6137c8bee913..df6eb444cfac884dbc21ea766f11ab006e5c8613 100644 (file)
@@ -45,3 +45,16 @@ const char *xtype_format_fmt(struct xtype *xt, u32 fmt, struct mempool *pool)
 
   return "";
 }
+
+int xtype_unit_parser(const char *units_str, struct unit_definition *units_def)
+{
+  int i = 0;
+  while(units_def[i].unit != NULL) {
+    if(strcmp(units_str, units_def[i].unit) == 0) {
+      return i;
+    }
+    i++;
+  }
+
+  return -1;
+}
index 5a42e46570fcb71b053205de48a60b961787e556..b1f2cc060fcb7a6f8273df227b6845c4be3cd11e 100644 (file)
@@ -59,6 +59,23 @@ typedef const char * (*xtype_fmt_parser)(const char *str, u32 *dest, struct memp
  **/
 typedef const char * (*xtype_fmt_formatter)(u32 fmt, struct mempool *pool);
 
+/**
+ * Definition of the units that are appended to an xtype value. The value with units is represented
+ * by the following string: "<value><units>". The final value of the of the string is computed using
+ * the following formula: <value> * <num>/<denom>.
+ **/
+struct unit_definition {
+  const char *unit; // string representation of unit
+  u64 num;
+  u64 denom;
+};
+
+/**
+ * Parses a unit definition in units_str and returns index into units_def array. -1 if the units
+ * were not contained in the array.
+ **/
+int xtype_unit_parser(const char *units_str, struct unit_definition *units_def);
+
 /**
  * This structure describes an xtype. Among other things, it points to callback
  * functions handling this xtype.