1// Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/
 2//
 3// SPDX-License-Identifier: BSD-2-Clause
 4
 5#ifndef COMMON_TIME_H
 6#define COMMON_TIME_H
 7
 8#include <common/limits.h>
 9
10#include <sys/time.h>
11
12#include <wasi/api.h>
13#include <stdbool.h>
14#include <time.h>
15
16#define NSEC_PER_SEC 1000000000
17
18static inline bool timespec_to_timestamp_exact(
19    const struct timespec *timespec, __wasi_timestamp_t *timestamp) {
20  // Invalid nanoseconds field.
21  if (timespec->tv_nsec < 0 || timespec->tv_nsec >= NSEC_PER_SEC)
22    return false;
23
24  // Timestamps before the Epoch are not supported.
25  if (timespec->tv_sec < 0)
26    return false;
27
28  // Make sure our timestamp does not overflow.
29  return !__builtin_mul_overflow(timespec->tv_sec, NSEC_PER_SEC, timestamp) &&
30         !__builtin_add_overflow(*timestamp, timespec->tv_nsec, timestamp);
31}
32
33static inline bool timespec_to_timestamp_clamp(
34    const struct timespec *timespec, __wasi_timestamp_t *timestamp) {
35  // Invalid nanoseconds field.
36  if (timespec->tv_nsec < 0 || timespec->tv_nsec >= NSEC_PER_SEC)
37    return false;
38
39  if (timespec->tv_sec < 0) {
40    // Timestamps before the Epoch are not supported.
41    *timestamp = 0;
42  } else if (__builtin_mul_overflow(timespec->tv_sec, NSEC_PER_SEC, timestamp) ||
43             __builtin_add_overflow(*timestamp, timespec->tv_nsec, timestamp)) {
44    // Make sure our timestamp does not overflow.
45    *timestamp = NUMERIC_MAX(__wasi_timestamp_t);
46  }
47  return true;
48}
49
50static inline struct timespec timestamp_to_timespec(
51    __wasi_timestamp_t timestamp) {
52  // Decompose timestamp into seconds and nanoseconds.
53  return (struct timespec){.tv_sec = timestamp / NSEC_PER_SEC,
54                           .tv_nsec = timestamp % NSEC_PER_SEC};
55}
56
57static inline struct timeval timestamp_to_timeval(
58    __wasi_timestamp_t timestamp) {
59  struct timespec ts = timestamp_to_timespec(timestamp);
60  return (struct timeval){.tv_sec = ts.tv_sec, ts.tv_nsec / 1000};
61}
62
63#endif