summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 6e4d3da)
raw | patch | inline | side by side (parent: 6e4d3da)
author | Sebastian Harl <sh@tokkee.org> | |
Thu, 3 Apr 2014 13:04:30 +0000 (15:04 +0200) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Thu, 3 Apr 2014 13:04:30 +0000 (15:04 +0200) |
This function formats a time interval using the format 1Y2M3D4h5m6.7s.
src/core/time.c | patch | blob | history | |
src/include/core/time.h | patch | blob | history | |
t/Makefile.am | patch | blob | history | |
t/core/time_test.c | [new file with mode: 0644] | patch | blob |
t/libsysdb_test.c | patch | blob | history | |
t/libsysdb_test.h | patch | blob | history |
diff --git a/src/core/time.c b/src/core/time.c
index 877feb1de9cfe95824063b46e64c5a28b8445680..fe57384a2aac81572021925b3c09e0eda75c9167 100644 (file)
--- a/src/core/time.c
+++ b/src/core/time.c
# include "config.h"
#endif /* HAVE_CONFIG_H */
+#include "sysdb.h"
#include "core/time.h"
#include <time.h>
+#include <stdio.h>
#include <string.h>
/*
* public API
*/
+/* 1 second (in micro-seconds) */
+#define SEC 1000000000L
+
+const sdb_time_t SDB_INTERVAL_YEAR = 3652425L * 24L * 60L * 60L * 100000L;
+const sdb_time_t SDB_INTERVAL_MONTH = 30436875L * 24L * 60L * 60L * 1000L;
+const sdb_time_t SDB_INTERVAL_DAY = 24L * 60L * 60L * SEC;
+const sdb_time_t SDB_INTERVAL_HOUR = 60L * 60L * SEC;
+const sdb_time_t SDB_INTERVAL_MINUTE = 60L * SEC;
+const sdb_time_t SDB_INTERVAL_SECOND = SEC;
+
sdb_time_t
sdb_gettime(void)
{
return strftime(s, len, format, &tm);
} /* sdb_strftime */
+size_t
+sdb_strfinterval(char *s, size_t len, sdb_time_t interval)
+{
+ size_t n = 0;
+ size_t i;
+
+ /* special case the optional fractional part for seconds */
+ _Bool have_seconds = 0;
+
+ struct {
+ sdb_time_t interval;
+ const char *suffix;
+ } specs[] = {
+ { SDB_INTERVAL_YEAR, "Y" },
+ { SDB_INTERVAL_MONTH, "M" },
+ { SDB_INTERVAL_DAY, "D" },
+ { SDB_INTERVAL_HOUR, "h" },
+ { SDB_INTERVAL_MINUTE, "m" },
+ { SDB_INTERVAL_SECOND, "" },
+ };
+
+#define LEN (len > n ? len - n : 0)
+ for (i = 0; i < SDB_STATIC_ARRAY_LEN(specs); ++i) {
+ if (interval >= specs[i].interval) {
+ n += snprintf(s + n, LEN, "%"PRIscTIME"%s",
+ interval / specs[i].interval, specs[i].suffix);
+ interval %= specs[i].interval;
+ if (i == SDB_STATIC_ARRAY_LEN(specs) - 1)
+ have_seconds = 1;
+ }
+ }
+
+ if (interval) {
+ n += snprintf(s + n, LEN, ".%09"PRIscTIME, interval);
+ have_seconds = 1;
+
+ /* removing trailing zeroes */
+ if (n <= len)
+ while (s[n - 1] == '0')
+ s[n--] = '\0';
+ }
+
+ if (! n) {
+ n = snprintf(s, len, "0");
+ have_seconds = 1;
+ }
+
+ if (have_seconds)
+ n += snprintf(s + n, LEN, "s");
+#undef LEN
+
+ if (len)
+ s[len - 1] = '\0';
+ return n;
+} /* sdb_strfinterval */
+
/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
index 30e920b6a0905de566874e3a9afddceaee4259cb..f1a1dd5f9e17add0c03ef2f4fd9ca1f151d5330c 100644 (file)
--- a/src/include/core/time.h
+++ b/src/include/core/time.h
#define TIMESPEC_TO_SDB_TIME(ts) (SECS_TO_SDB_TIME((ts).tv_sec) \
+ NSECS_TO_SDB_TIME((ts).tv_nsec))
+/*
+ * Interval constants:
+ * Each constant specifies the time interval, in nano-seconds, of the named
+ * time-frame. Year, month, and day are approximations which do not work well
+ * for very large time intervals.
+ */
+extern const sdb_time_t SDB_INTERVAL_YEAR;
+extern const sdb_time_t SDB_INTERVAL_MONTH;
+extern const sdb_time_t SDB_INTERVAL_DAY;
+extern const sdb_time_t SDB_INTERVAL_HOUR;
+extern const sdb_time_t SDB_INTERVAL_MINUTE;
+extern const sdb_time_t SDB_INTERVAL_SECOND;
+
sdb_time_t
sdb_gettime(void);
size_t
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);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/t/Makefile.am b/t/Makefile.am
index 611b4a9d31b4eb70d69bbc167e91e1d3b01a4ac9..c63a2bb21d0c8f9a8e1ee25836723266f70fbebe 100644 (file)
--- a/t/Makefile.am
+++ b/t/Makefile.am
core/object_test.c \
core/store_test.c \
core/store_lookup_test.c \
+ core/time_test.c \
frontend/parser_test.c \
frontend/sock_test.c \
utils/channel_test.c \
diff --git a/t/core/time_test.c b/t/core/time_test.c
--- /dev/null
+++ b/t/core/time_test.c
@@ -0,0 +1,99 @@
+/*
+ * SysDB - t/core/time_test.c
+ * Copyright (C) 2014 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core/time.h"
+#include "libsysdb_test.h"
+
+#include <check.h>
+
+START_TEST(test_strfinterval)
+{
+ char buf[1024];
+ size_t check;
+ size_t i;
+
+ struct {
+ sdb_time_t interval;
+ const char *expected;
+ } golden_data[] = {
+ { 0, "0s" },
+ { 4711, ".000004711s" },
+ { 1000123400, "1.0001234s" },
+ { 47940228000000000L, "1Y6M7D" },
+ { SDB_INTERVAL_YEAR, "1Y" },
+ { SDB_INTERVAL_MONTH, "1M" },
+ { SDB_INTERVAL_DAY, "1D" },
+ { SDB_INTERVAL_HOUR, "1h" },
+ { SDB_INTERVAL_MINUTE, "1m" },
+ { SDB_INTERVAL_SECOND, "1s" },
+ { SDB_INTERVAL_YEAR
+ + SDB_INTERVAL_MONTH
+ + SDB_INTERVAL_DAY
+ + SDB_INTERVAL_HOUR
+ + SDB_INTERVAL_MINUTE
+ + SDB_INTERVAL_SECOND
+ + 1234, "1Y1M1D1h1m1.000001234s" },
+ };
+
+ /* 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 */
+ fail_unless(check == 11,
+ "sdb_strfinterval(NULL, 0, 4711) = %zu; expected: 11", check);
+
+ for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
+ check = sdb_strfinterval(buf, sizeof(buf), golden_data[i].interval);
+ fail_unless(check > 0,
+ "sdb_strfinterval(<buf>, <size>, %"PRIscTIME") = %zu; "
+ "expected: >0", golden_data[i].interval, check);
+ fail_unless(!strcmp(buf, golden_data[i].expected),
+ "sdb_strfinterval(<buf>, <size>, %"PRIscTIME") did not "
+ "format interval correctly; got: '%s'; expected: '%s'",
+ golden_data[i].interval, buf, golden_data[i].expected);
+ fail_unless(check == strlen(golden_data[i].expected),
+ "sdb_strfinterval(<buf>, <size>, %"PRIscTIME") = %zu; "
+ "expected: %zu", golden_data[i].interval, check,
+ strlen(golden_data[i].expected));
+ }
+}
+END_TEST
+
+Suite *
+core_time_suite(void)
+{
+ Suite *s = suite_create("core::time");
+ TCase *tc;
+
+ tc = tcase_create("core");
+ tcase_add_test(tc, test_strfinterval);
+ suite_add_tcase(s, tc);
+
+ return s;
+} /* core_time_suite */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+
diff --git a/t/libsysdb_test.c b/t/libsysdb_test.c
index 8e5f2f4b23249625547e05feac44d819acbabb69..5b1b34df36b261621743eceb43f537b1e05cefa9 100644 (file)
--- a/t/libsysdb_test.c
+++ b/t/libsysdb_test.c
{ core_object_suite, NULL },
{ core_store_suite, NULL },
{ core_store_lookup_suite, NULL },
+ { core_time_suite, NULL },
{ fe_parser_suite, NULL },
{ fe_sock_suite, NULL },
{ util_channel_suite, NULL },
diff --git a/t/libsysdb_test.h b/t/libsysdb_test.h
index 9d28fa0d229b4b951064209ceb9c24aa73d0d111..3357260f6a52559ac0d70906aff2e5a927cd08cf 100644 (file)
--- a/t/libsysdb_test.h
+++ b/t/libsysdb_test.h
Suite *
core_store_lookup_suite(void);
+/* t/core/time_test */
+Suite *
+core_time_suite(void);
+
/* t/frontend/parser_test */
Suite *
fe_parser_suite(void);