From e89ec31ae5d65596bc542078b7d43109844c44eb Mon Sep 17 00:00:00 2001 From: John W Higgins Date: Sat, 23 Mar 2024 11:51:43 -0700 Subject: [PATCH] Add additional format options for os/clock --- src/core/os.c | 52 +++++++++++++++++++++++++++++---------------- test/suite-os.janet | 13 +++++++++++- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/core/os.c b/src/core/os.c index 7d1d70e1..6c3cfcca 100644 --- a/src/core/os.c +++ b/src/core/os.c @@ -1564,34 +1564,50 @@ JANET_CORE_FN(os_time, } JANET_CORE_FN(os_clock, - "(os/clock &opt source)", - "Return the number of whole + fractional seconds of the requested clock source.\n\n" + "(os/clock &opt source format)", + "Return the current time of the requested clock source.\n\n" "The `source` argument selects the clock source to use, when not specified the default " "is `:realtime`:\n" "- :realtime: Return the real (i.e., wall-clock) time. This clock is affected by discontinuous " " jumps in the system time\n" "- :monotonic: Return the number of whole + fractional seconds since some fixed point in " " time. The clock is guaranteed to be non-decreasing in real time.\n" - "- :cputime: Return the CPU time consumed by this process (i.e. all threads in the process)\n") { + "- :cputime: Return the CPU time consumed by this process (i.e. all threads in the process)\n" + "The `format` argument selects the type of output, when not specified the default is `:double`:\n" + "- :double: Return the number of seconds + fractional seconds as a double\n" + "- :int: Return the number of seconds as am integer\n" + "- :tuple: Return a 2 integer tuple {seconds, nanoseconds}\n") { + enum JanetTimeSource source; janet_sandbox_assert(JANET_SANDBOX_HRTIME); - janet_arity(argc, 0, 1); - enum JanetTimeSource source = JANET_TIME_REALTIME; - if (argc == 1) { - JanetKeyword sourcestr = janet_getkeyword(argv, 0); - if (janet_cstrcmp(sourcestr, "realtime") == 0) { - source = JANET_TIME_REALTIME; - } else if (janet_cstrcmp(sourcestr, "monotonic") == 0) { - source = JANET_TIME_MONOTONIC; - } else if (janet_cstrcmp(sourcestr, "cputime") == 0) { - source = JANET_TIME_CPUTIME; - } else { - janet_panicf("expected :realtime, :monotonic, or :cputime, got %v", argv[0]); - } + janet_arity(argc, 0, 2); + + JanetKeyword sourcestr = janet_optkeyword(argv, argc, 0, (const uint8_t *) "realtime"); + if (janet_cstrcmp(sourcestr, "realtime") == 0) { + source = JANET_TIME_REALTIME; + } else if (janet_cstrcmp(sourcestr, "monotonic") == 0) { + source = JANET_TIME_MONOTONIC; + } else if (janet_cstrcmp(sourcestr, "cputime") == 0) { + source = JANET_TIME_CPUTIME; + } else { + janet_panicf("expected :realtime, :monotonic, or :cputime, got %v", argv[0]); } + struct timespec tv; if (janet_gettime(&tv, source)) janet_panic("could not get time"); - double dtime = tv.tv_sec + (tv.tv_nsec / 1E9); - return janet_wrap_number(dtime); + + JanetKeyword formatstr = janet_optkeyword(argv, argc, 1 , (const uint8_t *) "double"); + if (janet_cstrcmp(formatstr, "double") == 0) { + double dtime = tv.tv_sec + (tv.tv_nsec / 1E9); + return janet_wrap_number(dtime); + } else if (janet_cstrcmp(formatstr, "int") == 0) { + return janet_wrap_number(tv.tv_sec); + } else if (janet_cstrcmp(formatstr, "tuple") == 0) { + Janet tup[2] = {janet_wrap_integer(tv.tv_sec), + janet_wrap_integer(tv.tv_nsec)}; + return janet_wrap_tuple(janet_tuple_n(tup, 2)); + } else { + janet_panicf("expected :double, :int, or :tuple, got %v", argv[1]); + } } JANET_CORE_FN(os_sleep, diff --git a/test/suite-os.janet b/test/suite-os.janet index e9bd465e..fdc623da 100644 --- a/test/suite-os.janet +++ b/test/suite-os.janet @@ -96,11 +96,23 @@ (assert (= (in buf 0) 0) "cryptorand doesn't overwrite buffer") (assert (= (length buf) 2) "cryptorand appends to buffer")) +(assert-no-error "realtime clock" (os/clock)) +(assert-no-error "realtime clock" (os/clock nil)) +(assert-no-error "realtime clock" (os/clock nil nil)) + # 80db68210 (assert-no-error "realtime clock" (os/clock :realtime)) (assert-no-error "cputime clock" (os/clock :cputime)) (assert-no-error "monotonic clock" (os/clock :monotonic)) +(assert-no-error "realtime clock double output" (os/clock nil :double)) +(assert-no-error "realtime clock int output" (os/clock nil :int)) +(assert-no-error "realtime clock tuple output" (os/clock nil :tuple)) + +(assert-error "invalid clock" (os/clock :a)) +(assert-error "invalid output" (os/clock :realtime :b)) +(assert-error "invalid clock and output" (os/clock :a :b)) + (def before (os/clock :monotonic)) (def after (os/clock :monotonic)) (assert (>= after before) "monotonic clock is monotonic") @@ -148,4 +160,3 @@ {:out dn :err dn}))) (end-suite) -