Support standard timestamp formats for begin/end
[babeltrace.git] / plugins / trimmer / trimmer.c
index 23fe713481e67676941545bfe2db5e514b90cf14..a68828931aa40988022e6aa7ecd3a9bbdf383387 100644 (file)
@@ -63,37 +63,214 @@ void destroy_trimmer(struct bt_component *component)
        destroy_trimmer_data(data);
 }
 
+/*
+ * Parses a timestamp, figuring out its format.
+ *
+ * Returns a negative value if anything goes wrong.
+ *
+ * Expected formats:
+ *
+ *   YYYY-MM-DD hh:mm:ss.ns
+ *   hh:mm:ss.ns
+ *   -ss.ns
+ *   ss.ns
+ *   YYYY-MM-DD hh:mm:ss
+ *   hh:mm:ss
+ *   -ss
+ *   ss
+ */
 static
-void init_from_params(struct trimmer *trimmer, struct bt_value *params)
+int timestamp_from_arg(const char *arg,
+               struct trimmer_bound *result_bound, bool gmt)
+{
+       int ret;
+       int64_t value;
+       unsigned int year, month, day, hh, mm, ss, ns;
+
+       /* YYYY-MM-DD hh:mm:ss.ns */
+       ret = sscanf(arg, "%u-%u-%u %u:%u:%u.%u",
+               &year, &month, &day, &hh, &mm, &ss, &ns);
+       if (ret == 7) {
+               struct tm tm = {
+                       .tm_sec = ss,
+                       .tm_min = mm,
+                       .tm_hour = hh,
+                       .tm_mday = day,
+                       .tm_mon = month - 1,
+                       .tm_year = year - 1900,
+                       .tm_isdst = -1,
+               };
+               time_t result;
+
+               if (gmt) {
+                       result = timegm(&tm);
+                       if (result < 0) {
+                               return -1;
+                       }
+               } else {
+                       result = mktime(&tm);
+                       if (result < 0) {
+                               return -1;
+                       }
+               }
+               value = (int64_t) result;
+               value *= NSEC_PER_SEC;
+               value += ns;
+               goto set;
+       }
+       /* hh:mm:ss.ns */
+       ret = sscanf(arg, "%u:%u:%u.%u",
+               &hh, &mm, &ss, &ns);
+       if (ret == 4) {
+               /* We don't know which day until we get an event. */
+               result_bound->lazy_values.hh = hh;
+               result_bound->lazy_values.mm = mm;
+               result_bound->lazy_values.ss = ss;
+               result_bound->lazy_values.ns = ns;
+               result_bound->lazy_values.gmt = gmt;
+               goto lazy;
+       }
+       /* -ss.ns */
+       ret = sscanf(arg, "-%u.%u",
+               &ss, &ns);
+       if (ret == 2) {
+               value = -ss * NSEC_PER_SEC;
+               value -= ns;
+               goto set;
+       }
+       /* ss.ns */
+       ret = sscanf(arg, "%u.%u",
+               &ss, &ns);
+       if (ret == 2) {
+               value = ss * NSEC_PER_SEC;
+               value += ns;
+               goto set;
+       }
+
+       /* YYYY-MM-DD hh:mm:ss */
+       ret = sscanf(arg, "%u-%u-%u %u:%u:%u",
+               &year, &month, &day, &hh, &mm, &ss);
+       if (ret == 6) {
+               struct tm tm = {
+                       .tm_sec = ss,
+                       .tm_min = mm,
+                       .tm_hour = hh,
+                       .tm_mday = day,
+                       .tm_mon = month - 1,
+                       .tm_year = year - 1900,
+                       .tm_isdst = -1,
+               };
+
+               if (gmt) {
+                       value = timegm(&tm);
+                       if (value < 0) {
+                               return -1;
+                       }
+               } else {
+                       value = mktime(&tm);
+                       if (value < 0) {
+                               return -1;
+                       }
+               }
+               value *= NSEC_PER_SEC;
+               goto set;
+       }
+       /* hh:mm:ss */
+       ret = sscanf(arg, "%u:%u:%u",
+               &hh, &mm, &ss);
+       if (ret == 3) {
+               /* We don't know which day until we get an event. */
+               result_bound->lazy_values.hh = hh;
+               result_bound->lazy_values.mm = mm;
+               result_bound->lazy_values.ss = ss;
+               result_bound->lazy_values.ns = 0;
+               result_bound->lazy_values.gmt = gmt;
+               goto lazy;
+       }
+       /* -ss */
+       ret = sscanf(arg, "-%u",
+               &ss);
+       if (ret == 1) {
+               value = -ss * NSEC_PER_SEC;
+               goto set;
+       }
+       /* ss */
+       ret = sscanf(arg, "%u",
+               &ss);
+       if (ret == 1) {
+               value = ss * NSEC_PER_SEC;
+               goto set;
+       }
+
+       /* Not found. */
+       return -1;
+
+set:
+       result_bound->value = value;
+       result_bound->set = true;
+       return 0;
+
+lazy:
+       result_bound->lazy = true;
+       return 0;
+}
+
+static
+enum bt_component_status init_from_params(struct trimmer *trimmer, struct bt_value *params)
 {
        struct bt_value *value = NULL;
+       bool gmt = false;
+       enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
 
        assert(params);
 
-        value = bt_value_map_get(params, "begin_ns_epoch");
-       if (value && bt_value_is_integer(value)) {
+        value = bt_value_map_get(params, "clock-gmt");
+       if (value) {
                enum bt_value_status value_ret;
 
-               value_ret = bt_value_integer_get(value, &trimmer->begin.value);
-               if (!value_ret) {
-                       trimmer->begin.set = true;
-               } else {
-                       printf_error("Failed to retrieve begin_ns_epoch value\n");
+               value_ret = bt_value_bool_get(value, &gmt);
+               if (value_ret) {
+                       ret = BT_COMPONENT_STATUS_INVALID;
+                       printf_error("Failed to retrieve clock-gmt value. Expecting a boolean.\n");
                }
        }
        bt_put(value);
-        value = bt_value_map_get(params, "end_ns_epoch");
-       if (value && bt_value_is_integer(value)) {
+       if (ret != BT_COMPONENT_STATUS_OK) {
+               goto end;
+       }
+
+        value = bt_value_map_get(params, "begin");
+       if (value) {
                enum bt_value_status value_ret;
+               const char *str;
 
-               value_ret = bt_value_integer_get(value, &trimmer->end.value);
-               if (!value_ret) {
-                       trimmer->end.set = true;
-               } else {
-                       printf_error("Failed to retrieve end_ns_epoch value\n");
+               value_ret = bt_value_string_get(value, &str);
+               if (value_ret || timestamp_from_arg(str,
+                               &trimmer->begin, gmt)) {
+                       ret = BT_COMPONENT_STATUS_INVALID;
+                       printf_error("Failed to retrieve begin value. Expecting a timestamp string.\n");
                }
        }
        bt_put(value);
+       if (ret != BT_COMPONENT_STATUS_OK) {
+               goto end;
+       }
+
+        value = bt_value_map_get(params, "end");
+       if (value) {
+               enum bt_value_status value_ret;
+               const char *str;
+
+               value_ret = bt_value_string_get(value, &str);
+               if (value_ret || timestamp_from_arg(str,
+                               &trimmer->end, gmt)) {
+                       ret = BT_COMPONENT_STATUS_INVALID;
+                       printf_error("Failed to retrieve end value. Expecting a timestamp string.\n");
+               }
+       }
+       bt_put(value);
+end:
+       return ret;
 }
 
 enum bt_component_status trimmer_component_init(
@@ -124,7 +301,7 @@ enum bt_component_status trimmer_component_init(
                goto error;
        }
 
-       init_from_params(trimmer, params);
+       ret = init_from_params(trimmer, params);
 end:
        return ret;
 error:
This page took 0.025714 seconds and 4 git commands to generate.