diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | src/plist.c | 20 | ||||
| -rw-r--r-- | test/Makefile.am | 5 | ||||
| -rw-r--r-- | test/date_val.c | 42 | ||||
| -rwxr-xr-x | test/date_val.test | 5 |
5 files changed, 68 insertions, 5 deletions
@@ -54,6 +54,7 @@ test/plist_btest test/plist_jtest test/plist_otest test/integer_set_test +test/date_val_test test/xml_behavior_test test/bplist_behavior_test test/data/*.out diff --git a/src/plist.c b/src/plist.c index 677e94e..85c2338 100644 --- a/src/plist.c +++ b/src/plist.c @@ -1889,13 +1889,23 @@ void plist_get_date_val(plist_t node, int32_t * sec, int32_t * usec) return; plist_get_type_and_value(node, &type, (void *) &val, &length); assert(length == sizeof(double)); + /* Inverse of plist_set_date_val (val = sec + usec / 1000000): + * whole seconds rounded down, the fraction rounded to microseconds. */ + double whole = floor(val); + double frac_usec = round((val - whole) * 1000000); + if (frac_usec >= 1000000) { + whole += 1; + frac_usec -= 1000000; + } + /* keep the int32_t conversion defined */ + if (whole > INT32_MAX) + whole = INT32_MAX; + else if (whole < INT32_MIN) + whole = INT32_MIN; if (sec) - *sec = (int32_t)val; + *sec = (int32_t)whole; if (usec) - { - val = fabs((val - (int64_t)val) * 1000000); - *usec = (int32_t)val; - } + *usec = (int32_t)frac_usec; } void plist_get_unix_date_val(plist_t node, int64_t *sec) diff --git a/test/Makefile.am b/test/Makefile.am index 1d98349..2e2b04e 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -11,6 +11,7 @@ noinst_PROGRAMS = \ plist_test \ plist_test++ \ integer_set_test \ + date_val_test \ plist_btest \ plist_jtest \ plist_otest \ @@ -31,6 +32,9 @@ plist_test_LDADD = $(top_builddir)/src/libplist-2.0.la integer_set_test_SOURCES = integer_set.c integer_set_test_LDADD = $(top_builddir)/src/libplist-2.0.la +date_val_test_SOURCES = date_val.c +date_val_test_LDADD = $(top_builddir)/src/libplist-2.0.la + plist_btest_SOURCES = plist_btest.c plist_btest_LDADD = $(top_builddir)/src/libplist-2.0.la @@ -47,6 +51,7 @@ bplist_behavior_test_SOURCES = bplist_behavior_test.c bplist_behavior_test_LDADD = $(top_builddir)/src/libplist-2.0.la TESTS = \ + date_val.test \ empty.test \ small.test \ medium.test \ diff --git a/test/date_val.c b/test/date_val.c new file mode 100644 index 0000000..127e194 --- /dev/null +++ b/test/date_val.c @@ -0,0 +1,42 @@ +#include <stdio.h> +#include <stdint.h> +#include <plist/plist.h> + +/* plist_get_date_val must return exactly what plist_set_date_val stored, + * including dates before the epoch (negative seconds). */ + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + +static int check(int32_t sec, int32_t usec) +{ + int32_t s = 0, u = 0; + plist_t d = plist_new_date(0, 0); + plist_set_date_val(d, sec, usec); + plist_get_date_val(d, &s, &u); + plist_free(d); + if (s != sec || u != usec) { + printf("set(%d, %d) -> get(%d, %d)\n", sec, usec, s, u); + return 1; + } + return 0; +} + +int main(int argc, char** argv) +{ + int err = 0; + int32_t sec, usec; + + err |= check(5, 6); + err |= check(0, 999999); + err |= check(-3, 250000); + err |= check(-1, 1); + err |= check(1000000000, 123456); + for (sec = -2; sec <= 2 && !err; sec++) { + for (usec = 0; usec < 1000000 && !err; usec += 7) { + err |= check(sec, usec); + } + } + return err; +} diff --git a/test/date_val.test b/test/date_val.test new file mode 100755 index 0000000..9cdf504 --- /dev/null +++ b/test/date_val.test @@ -0,0 +1,5 @@ +## -*- sh -*- + +set -e + +$top_builddir/test/date_val_test |
