[systemd-devel] [PATCH] conf parser: introduce milisecond parsing

Susant Sahani susant at redhat.com
Wed Jul 16 00:37:52 PDT 2014


Add millisecord parsing support to conf parser.

Immediate usage of this function is to parse bond options
such as MIIMonitor, UpDelayMSec, DownDelayMSec which is
represented in milli seconds.
---
 src/shared/conf-parser.c |   1 +
 src/shared/conf-parser.h |   1 +
 src/shared/time-util.c   | 108 +++++++++++++++++++++++++++++++++++++++++++++++
 src/shared/time-util.h   |   8 ++++
 4 files changed, 118 insertions(+)

diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index 1f40986..07e8c76 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -451,6 +451,7 @@ DEFINE_PARSER(unsigned, unsigned, safe_atou)
 DEFINE_PARSER(double, double, safe_atod)
 DEFINE_PARSER(nsec, nsec_t, parse_nsec)
 DEFINE_PARSER(sec, usec_t, parse_sec)
+DEFINE_PARSER(msec, msec_t, parse_msec)
 
 int config_parse_iec_size(const char* unit,
                             const char *filename,
diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h
index 3e2c784..671e207 100644
--- a/src/shared/conf-parser.h
+++ b/src/shared/conf-parser.h
@@ -106,6 +106,7 @@ int config_parse_path(const char *unit, const char *filename, unsigned line, con
 int config_parse_strv(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_sec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_nsec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_msec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_log_facility(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_log_level(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/shared/time-util.c b/src/shared/time-util.c
index fc79c56..58d8a67 100644
--- a/src/shared/time-util.c
+++ b/src/shared/time-util.c
@@ -816,6 +816,114 @@ int parse_nsec(const char *t, nsec_t *nsec) {
         return 0;
 }
 
+int parse_msec(const char *t, msec_t *msec) {
+        static const struct {
+                const char *suffix;
+                msec_t msec;
+        } table[] = {
+                { "seconds", MSEC_PER_SEC },
+                { "second", MSEC_PER_SEC },
+                { "sec", MSEC_PER_SEC },
+                { "s", MSEC_PER_SEC },
+                { "minutes", MSEC_PER_MINUTE },
+                { "minute", MSEC_PER_MINUTE },
+                { "min", MSEC_PER_MINUTE },
+                { "months", MSEC_PER_MONTH },
+                { "month", MSEC_PER_MONTH },
+                { "m", MSEC_PER_MINUTE },
+                { "hours", MSEC_PER_HOUR },
+                { "hour", MSEC_PER_HOUR },
+                { "hr", MSEC_PER_HOUR },
+                { "h", MSEC_PER_HOUR },
+                { "days", MSEC_PER_DAY },
+                { "day", MSEC_PER_DAY },
+                { "d", MSEC_PER_DAY },
+                { "weeks", MSEC_PER_WEEK },
+                { "week", MSEC_PER_WEEK },
+                { "w", MSEC_PER_WEEK },
+                { "years", MSEC_PER_YEAR },
+                { "year", MSEC_PER_YEAR },
+                { "y", MSEC_PER_YEAR },
+                { "", 1ULL }, /* default is msec */
+        };
+
+        const char *p;
+        msec_t r = 0;
+        bool something = false;
+
+        assert(t);
+        assert(msec);
+
+        p = t;
+        for (;;) {
+                long long l, z = 0;
+                char *e;
+                unsigned i, n = 0;
+
+                p += strspn(p, WHITESPACE);
+
+                if (*p == 0) {
+                        if (!something)
+                                return -EINVAL;
+
+                        break;
+                }
+
+                errno = 0;
+                l = strtoll(p, &e, 10);
+
+                if (errno > 0)
+                        return -errno;
+
+                if (l < 0)
+                        return -ERANGE;
+
+                if (*e == '.') {
+                        char *b = e + 1;
+
+                        errno = 0;
+                        z = strtoll(b, &e, 10);
+                        if (errno > 0)
+                                return -errno;
+
+                        if (z < 0)
+                                return -ERANGE;
+
+                        if (e == b)
+                                return -EINVAL;
+
+                        n = e - b;
+
+                } else if (e == p)
+                        return -EINVAL;
+
+                e += strspn(e, WHITESPACE);
+
+                for (i = 0; i < ELEMENTSOF(table); i++)
+                        if (startswith(e, table[i].suffix)) {
+                                msec_t k = (msec_t) z * table[i].msec;
+
+                                for (; n > 0; n--)
+                                        k /= 10;
+
+                                r += (msec_t) l * table[i].msec + k;
+                                p = e + strlen(table[i].suffix);
+
+                                something = true;
+                                break;
+                        }
+
+                if (i >= ELEMENTSOF(table))
+                        return -EINVAL;
+
+        }
+
+        *msec = r;
+
+        return 0;
+}
+
+
 bool ntp_synced(void) {
         struct timex txc = {};
 
diff --git a/src/shared/time-util.h b/src/shared/time-util.h
index 792cd27..3969df8 100644
--- a/src/shared/time-util.h
+++ b/src/shared/time-util.h
@@ -26,6 +26,7 @@
 
 typedef uint64_t usec_t;
 typedef uint64_t nsec_t;
+typedef uint64_t msec_t;
 
 #define NSEC_FMT "%" PRIu64
 #define USEC_FMT "%" PRIu64
@@ -46,16 +47,22 @@ typedef struct dual_timestamp {
 
 #define USEC_PER_MINUTE ((usec_t) (60ULL*USEC_PER_SEC))
 #define NSEC_PER_MINUTE ((usec_t) (60ULL*NSEC_PER_SEC))
+#define MSEC_PER_MINUTE ((usec_t) (60ULL*MSEC_PER_SEC))
 #define USEC_PER_HOUR ((usec_t) (60ULL*USEC_PER_MINUTE))
 #define NSEC_PER_HOUR ((usec_t) (60ULL*NSEC_PER_MINUTE))
+#define MSEC_PER_HOUR ((usec_t) (60ULL*MSEC_PER_MINUTE))
 #define USEC_PER_DAY ((usec_t) (24ULL*USEC_PER_HOUR))
 #define NSEC_PER_DAY ((usec_t) (24ULL*NSEC_PER_HOUR))
+#define MSEC_PER_DAY ((usec_t) (24ULL*MSEC_PER_HOUR))
 #define USEC_PER_WEEK ((usec_t) (7ULL*USEC_PER_DAY))
 #define NSEC_PER_WEEK ((usec_t) (7ULL*NSEC_PER_DAY))
+#define MSEC_PER_WEEK ((usec_t) (7ULL*MSEC_PER_DAY))
 #define USEC_PER_MONTH ((usec_t) (2629800ULL*USEC_PER_SEC))
 #define NSEC_PER_MONTH ((usec_t) (2629800ULL*NSEC_PER_SEC))
+#define MSEC_PER_MONTH ((usec_t) (2629800ULL*MSEC_PER_SEC))
 #define USEC_PER_YEAR ((usec_t) (31557600ULL*USEC_PER_SEC))
 #define NSEC_PER_YEAR ((usec_t) (31557600ULL*NSEC_PER_SEC))
+#define MSEC_PER_YEAR ((usec_t) (31557600ULL*MSEC_PER_SEC))
 
 #define FORMAT_TIMESTAMP_MAX ((4*4+1)+11+9+4+1) /* weekdays can be unicode */
 #define FORMAT_TIMESTAMP_WIDTH 28 /* when outputting, assume this width */
@@ -93,6 +100,7 @@ int parse_timestamp(const char *t, usec_t *usec);
 
 int parse_sec(const char *t, usec_t *usec);
 int parse_nsec(const char *t, nsec_t *nsec);
+int parse_msec(const char *t, msec_t *msec);
 
 bool ntp_synced(void);
 
-- 
1.9.3



More information about the systemd-devel mailing list