From e460978379cc477e806251ba38cb426b2aa9fddf Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Wed, 30 Jul 2014 10:24:30 +0200 Subject: [PATCH] time: Added sdb_strpunit() to parse a time unit. --- src/core/time.c | 28 +++++++++++++++++++++++++++- src/frontend/scanner.l | 6 ++++++ src/include/core/time.h | 13 +++++++++++++ t/unit/core/time_test.c | 39 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/core/time.c b/src/core/time.c index 762ffd0..5d34e18 100644 --- a/src/core/time.c +++ b/src/core/time.c @@ -41,7 +41,7 @@ * public API */ -/* 1 second (in micro-seconds) */ +/* 1 second (in nano-seconds) */ #define SEC 1000000000L const sdb_time_t SDB_INTERVAL_YEAR = 3652425L * 24L * 60L * 60L * 100000L; @@ -147,5 +147,31 @@ sdb_strfinterval(char *s, size_t len, sdb_time_t interval) return n; } /* sdb_strfinterval */ +sdb_time_t +sdb_strpunit(const char *s) +{ + struct { + const char *s; + sdb_time_t unit; + } units[] = { + { "Y", SDB_INTERVAL_YEAR }, + { "M", SDB_INTERVAL_MONTH }, + { "D", SDB_INTERVAL_DAY }, + { "h", SDB_INTERVAL_HOUR }, + { "m", SDB_INTERVAL_MINUTE }, + { "s", SDB_INTERVAL_SECOND }, + { "ms", SDB_INTERVAL_SECOND / 1000L }, + { "us", SDB_INTERVAL_SECOND / 1000000L }, + { "ns", 1 }, + }; + + size_t i; + + for (i = 0; i < SDB_STATIC_ARRAY_LEN(units); ++i) + if (! strcmp(s, units[i].s)) + return units[i].unit; + return 0; +} /* sdb_strpunit */ + /* vim: set tw=78 sw=4 ts=4 noexpandtab : */ diff --git a/src/frontend/scanner.l b/src/frontend/scanner.l index 5e80368..f45fbe7 100644 --- a/src/frontend/scanner.l +++ b/src/frontend/scanner.l @@ -75,10 +75,16 @@ csc_start \/\* csc_inside ([^*/]+|[^*]\/|\*[^/]) csc_end \*\/ +/* + * Strings and identifiers. + */ identifier ([A-Za-z_][A-Za-z_0-9$]*) /* TODO: fully support SQL strings */ string ('[^']*') +/* + * Numeric constants. + */ dec ([\+\-]?[0-9]+) exp ([\+\-]?[0-9]+[Ee]\+?[0-9]+) integer ({dec}|{exp}) diff --git a/src/include/core/time.h b/src/include/core/time.h index 7515af3..c97e121 100644 --- a/src/include/core/time.h +++ b/src/include/core/time.h @@ -79,6 +79,19 @@ sdb_strftime(char *s, size_t len, const char *format, sdb_time_t); size_t sdb_strfinterval(char *s, size_t len, sdb_time_t interval); +/* + * sdb_strpunit: + * Parse the specified string as a time unit. + * "Y" (year), "M" (month), "D" (day), "h" (hour), "m" (minute), "s" (second), + * "ms" (milli-second), "us" (micro-second), "ns" (nano-second). + * + * Returns: + * - the time interval corresponding to the specified unit on success + * - 0 else + */ +sdb_time_t +sdb_strpunit(const char *s); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/t/unit/core/time_test.c b/t/unit/core/time_test.c index f1f4c94..8be2214 100644 --- a/t/unit/core/time_test.c +++ b/t/unit/core/time_test.c @@ -34,7 +34,6 @@ START_TEST(test_strfinterval) { char buf[1024]; size_t check; - size_t i; struct { sdb_time_t interval; @@ -59,6 +58,8 @@ START_TEST(test_strfinterval) + 1234, "1Y1M1D1h1m1.000001234s" }, }; + size_t i; + /* this should return the number of bytes which would have been written; * most notably, it should not segfault ;-) */ check = sdb_strfinterval(NULL, 0, 4711); /* expected: .000004711s */ @@ -82,6 +83,41 @@ START_TEST(test_strfinterval) } END_TEST +START_TEST(test_strpunit) +{ + struct { + const char *s; + sdb_time_t expected; + } golden_data[] = { + { "Y", SDB_INTERVAL_YEAR }, + { "M", SDB_INTERVAL_MONTH }, + { "D", SDB_INTERVAL_DAY }, + { "h", SDB_INTERVAL_HOUR }, + { "m", SDB_INTERVAL_MINUTE }, + { "s", SDB_INTERVAL_SECOND }, + { "ms", 1000000L }, + { "us", 1000L }, + { "ns", 1L }, + /* invalid units */ + { "y", 0 }, + { "d", 0 }, + { "H", 0 }, + { "S", 0 }, + { "ps", 0 }, + }; + + size_t i; + + for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) { + sdb_time_t check = sdb_strpunit(golden_data[i].s); + + fail_unless(check == golden_data[i].expected, + "sdb_strpunit(%s) = %"PRIsdbTIME"; expected: %"PRIsdbTIME, + golden_data[i].s, check, golden_data[i].expected); + } +} +END_TEST + Suite * core_time_suite(void) { @@ -90,6 +126,7 @@ core_time_suite(void) tc = tcase_create("core"); tcase_add_test(tc, test_strfinterval); + tcase_add_test(tc, test_strpunit); suite_add_tcase(s, tc); return s; -- 2.30.2