Program Listing for File time.h

Return to documentation for file (include_public/anj/time.h)

        ANJ_TIME_DURATION_AS_STRING(timeout, ANJ_TIME_UNIT_MS));
/*
 * Copyright 2023-2026 AVSystem <avsystem@avsystem.com>
 * AVSystem Anjay Lite LwM2M SDK
 * All rights reserved.
 *
 * Licensed under AVSystem Anjay Lite LwM2M Client SDK - Non-Commercial License.
 * See the attached LICENSE file for details.
 */

#include <anj/init.h>

#ifndef ANJ_TIME_H
#    define ANJ_TIME_H

#    include <inttypes.h>
#    include <math.h>
#    include <stdbool.h>
#    include <stddef.h>
#    include <stdint.h>

#    ifdef __cplusplus
extern "C" {
#    endif

typedef enum {
    ANJ_TIME_UNIT_DAY,

    ANJ_TIME_UNIT_HOUR,

    ANJ_TIME_UNIT_MIN,

    ANJ_TIME_UNIT_S,

    ANJ_TIME_UNIT_MS,

    ANJ_TIME_UNIT_US,
} anj_time_unit_t;

#    define ANJ_TIME_US_MAX INT64_MAX

#    define ANJ_TIME_DURATION_AS_STRING_MAX_LEN (sizeof("-9223372036854775808"))

typedef struct {
    int64_t us;
} anj_time_duration_t;

typedef struct {
    anj_time_duration_t since_monotonic_epoch;
} anj_time_monotonic_t;

typedef struct {
    anj_time_duration_t since_real_epoch;
} anj_time_real_t;

extern const anj_time_duration_t ANJ_TIME_DURATION_ZERO;
extern const anj_time_real_t ANJ_TIME_REAL_ZERO;
extern const anj_time_monotonic_t ANJ_TIME_MONOTONIC_ZERO;
extern const anj_time_duration_t ANJ_TIME_DURATION_INVALID;
extern const anj_time_real_t ANJ_TIME_REAL_INVALID;
extern const anj_time_monotonic_t ANJ_TIME_MONOTONIC_INVALID;

anj_time_duration_t anj_time_duration_new(int64_t scalar, anj_time_unit_t unit);

anj_time_duration_t anj_time_duration_fnew(double scalar, anj_time_unit_t unit);

int64_t anj_time_duration_to_scalar(anj_time_duration_t duration,
                                    anj_time_unit_t unit);

double anj_time_duration_to_fscalar(anj_time_duration_t duration,
                                    anj_time_unit_t unit);

static inline bool anj_time_duration_is_valid(anj_time_duration_t duration) {
    if (duration.us == ANJ_TIME_US_MAX) {
        return false;
    }
    return true;
}

static inline anj_time_duration_t
anj_time_duration_add(const anj_time_duration_t lhs,
                      const anj_time_duration_t rhs) {
    if (!anj_time_duration_is_valid(lhs) || !anj_time_duration_is_valid(rhs)) {
        return ANJ_TIME_DURATION_INVALID;
    }

    const anj_time_duration_t result = { lhs.us + rhs.us };
    return result;
}

static inline anj_time_duration_t
anj_time_duration_sub(const anj_time_duration_t lhs,
                      const anj_time_duration_t rhs) {
    if (!anj_time_duration_is_valid(lhs) || !anj_time_duration_is_valid(rhs)) {
        return ANJ_TIME_DURATION_INVALID;
    }

    const anj_time_duration_t result = { lhs.us - rhs.us };
    return result;
}

static inline anj_time_duration_t
anj_time_duration_mul(const anj_time_duration_t duration,
                      const int32_t factor) {
    if (!anj_time_duration_is_valid(duration) || factor == INT32_MAX) {
        return ANJ_TIME_DURATION_INVALID;
    }
    const anj_time_duration_t result = { duration.us * factor };
    return result;
}

static inline anj_time_duration_t
anj_time_duration_fmul(const anj_time_duration_t duration,
                       const double factor) {
    if (!anj_time_duration_is_valid(duration) || isinf(factor)
            || isnan(factor)) {
        return ANJ_TIME_DURATION_INVALID;
    }

    const anj_time_duration_t result = { (int64_t) ((double) duration.us
                                                    * factor) };
    return result;
}

static inline anj_time_duration_t
anj_time_duration_div(const anj_time_duration_t duration,
                      const int32_t divisor) {
    if (!anj_time_duration_is_valid(duration) || divisor == 0) {
        return ANJ_TIME_DURATION_INVALID;
    }

    const anj_time_duration_t result = { duration.us / divisor };
    return result;
}

static inline bool anj_time_duration_eq(const anj_time_duration_t lhs,
                                        const anj_time_duration_t rhs) {
    if (!anj_time_duration_is_valid(lhs) || !anj_time_duration_is_valid(rhs)) {
        return false;
    }

    return lhs.us == rhs.us;
}
static inline bool anj_time_duration_lt(const anj_time_duration_t lhs,
                                        const anj_time_duration_t rhs) {
    if (!anj_time_duration_is_valid(lhs) || !anj_time_duration_is_valid(rhs)) {
        return false;
    }

    return lhs.us < rhs.us;
}
static inline bool anj_time_duration_gt(const anj_time_duration_t lhs,
                                        const anj_time_duration_t rhs) {
    if (!anj_time_duration_is_valid(lhs) || !anj_time_duration_is_valid(rhs)) {
        return false;
    }

    return lhs.us > rhs.us;
}
static inline bool anj_time_duration_leq(const anj_time_duration_t lhs,
                                         const anj_time_duration_t rhs) {
    if (!anj_time_duration_is_valid(lhs) || !anj_time_duration_is_valid(rhs)) {
        return false;
    }

    return lhs.us <= rhs.us;
}
static inline bool anj_time_duration_geq(const anj_time_duration_t lhs,
                                         const anj_time_duration_t rhs) {
    if (!anj_time_duration_is_valid(lhs) || !anj_time_duration_is_valid(rhs)) {
        return false;
    }

    return lhs.us >= rhs.us;
}

const char *_anj_time_duration_as_string_impl(
        const anj_time_duration_t duration,
        const anj_time_unit_t unit,
        char (*buffer)[ANJ_TIME_DURATION_AS_STRING_MAX_LEN]);
#    define ANJ_TIME_DURATION_AS_STRING(duration, unit) \
        (_anj_time_duration_as_string_impl(             \
                duration,                               \
                unit,                                   \
                &(char[ANJ_TIME_DURATION_AS_STRING_MAX_LEN]){ "" }))

static inline anj_time_monotonic_t
anj_time_monotonic_from_duration(const anj_time_duration_t duration) {
    const anj_time_monotonic_t result = { duration };
    return result;
}

static inline anj_time_duration_t
anj_time_monotonic_to_duration(const anj_time_monotonic_t time) {
    return time.since_monotonic_epoch;
}

static inline anj_time_monotonic_t
anj_time_monotonic_new(const int64_t scalar, const anj_time_unit_t unit) {
    return anj_time_monotonic_from_duration(
            anj_time_duration_new(scalar, unit));
}

static inline anj_time_monotonic_t
anj_time_monotonic_fnew(const double scalar, const anj_time_unit_t unit) {
    return anj_time_monotonic_from_duration(
            anj_time_duration_fnew(scalar, unit));
}

static inline bool
anj_time_monotonic_is_valid(const anj_time_monotonic_t time) {
    return anj_time_duration_is_valid(anj_time_monotonic_to_duration(time));
}

static inline int64_t
anj_time_monotonic_to_scalar(const anj_time_monotonic_t time,
                             const anj_time_unit_t unit) {
    return anj_time_duration_to_scalar(anj_time_monotonic_to_duration(time),
                                       unit);
}

static inline double
anj_time_monotonic_to_fscalar(const anj_time_monotonic_t time,
                              const anj_time_unit_t unit) {
    return anj_time_duration_to_fscalar(anj_time_monotonic_to_duration(time),
                                        unit);
}

static inline anj_time_monotonic_t
anj_time_monotonic_add(const anj_time_monotonic_t start,
                       const anj_time_duration_t duration) {
    return anj_time_monotonic_from_duration(anj_time_duration_add(
            anj_time_monotonic_to_duration(start), duration));
}

static inline anj_time_monotonic_t
anj_time_monotonic_sub(const anj_time_monotonic_t start,
                       const anj_time_duration_t duration) {
    return anj_time_monotonic_from_duration(anj_time_duration_sub(
            anj_time_monotonic_to_duration(start), duration));
}

static inline anj_time_duration_t
anj_time_monotonic_diff(const anj_time_monotonic_t end,
                        const anj_time_monotonic_t start) {
    return anj_time_duration_sub(anj_time_monotonic_to_duration(end),
                                 anj_time_monotonic_to_duration(start));
}

static inline bool anj_time_monotonic_lt(const anj_time_monotonic_t lhs,
                                         const anj_time_monotonic_t rhs) {
    return anj_time_duration_lt(anj_time_monotonic_to_duration(lhs),
                                anj_time_monotonic_to_duration(rhs));
}
static inline bool anj_time_monotonic_gt(const anj_time_monotonic_t lhs,
                                         const anj_time_monotonic_t rhs) {
    return anj_time_duration_gt(anj_time_monotonic_to_duration(lhs),
                                anj_time_monotonic_to_duration(rhs));
}
static inline bool anj_time_monotonic_eq(const anj_time_monotonic_t lhs,
                                         const anj_time_monotonic_t rhs) {
    return anj_time_duration_eq(anj_time_monotonic_to_duration(lhs),
                                anj_time_monotonic_to_duration(rhs));
}
static inline bool anj_time_monotonic_leq(const anj_time_monotonic_t lhs,
                                          const anj_time_monotonic_t rhs) {
    return anj_time_duration_leq(anj_time_monotonic_to_duration(lhs),
                                 anj_time_monotonic_to_duration(rhs));
}
static inline bool anj_time_monotonic_geq(const anj_time_monotonic_t lhs,
                                          const anj_time_monotonic_t rhs) {
    return anj_time_duration_geq(anj_time_monotonic_to_duration(lhs),
                                 anj_time_monotonic_to_duration(rhs));
}

#    define ANJ_TIME_MONOTONIC_AS_STRING(time, unit) \
        (_anj_time_duration_as_string_impl(          \
                time.since_monotonic_epoch,          \
                unit,                                \
                &(char[ANJ_TIME_DURATION_AS_STRING_MAX_LEN]){ "" }))

static inline anj_time_real_t
anj_time_real_from_duration(const anj_time_duration_t duration) {
    const anj_time_real_t result = { duration };
    return result;
}

static inline anj_time_duration_t
anj_time_real_to_duration(const anj_time_real_t time) {
    return time.since_real_epoch;
}

static inline anj_time_real_t anj_time_real_new(const int64_t scalar,
                                                const anj_time_unit_t unit) {
    return anj_time_real_from_duration(anj_time_duration_new(scalar, unit));
}

static inline anj_time_real_t anj_time_real_fnew(const double scalar,
                                                 const anj_time_unit_t unit) {
    return anj_time_real_from_duration(anj_time_duration_fnew(scalar, unit));
}

static inline int64_t anj_time_real_to_scalar(const anj_time_real_t time,
                                              const anj_time_unit_t unit) {
    return anj_time_duration_to_scalar(anj_time_real_to_duration(time), unit);
}

static inline double anj_time_real_to_fscalar(const anj_time_real_t time,
                                              const anj_time_unit_t unit) {
    return anj_time_duration_to_fscalar(anj_time_real_to_duration(time), unit);
}

static inline bool anj_time_real_is_valid(const anj_time_real_t time) {
    return anj_time_duration_is_valid(anj_time_real_to_duration(time));
}

static inline anj_time_real_t
anj_time_real_add(const anj_time_real_t start,
                  const anj_time_duration_t duration) {
    return anj_time_real_from_duration(
            anj_time_duration_add(anj_time_real_to_duration(start), duration));
}

static inline anj_time_real_t
anj_time_real_sub(const anj_time_real_t start,
                  const anj_time_duration_t duration) {
    return anj_time_real_from_duration(
            anj_time_duration_sub(anj_time_real_to_duration(start), duration));
}

static inline anj_time_duration_t
anj_time_real_diff(const anj_time_real_t end, const anj_time_real_t start) {
    return anj_time_duration_sub(anj_time_real_to_duration(end),
                                 anj_time_real_to_duration(start));
}

static inline bool anj_time_real_lt(const anj_time_real_t lhs,
                                    const anj_time_real_t rhs) {
    return anj_time_duration_lt(anj_time_real_to_duration(lhs),
                                anj_time_real_to_duration(rhs));
}
static inline bool anj_time_real_gt(const anj_time_real_t lhs,
                                    const anj_time_real_t rhs) {
    return anj_time_duration_gt(anj_time_real_to_duration(lhs),
                                anj_time_real_to_duration(rhs));
}
static inline bool anj_time_real_eq(const anj_time_real_t lhs,
                                    const anj_time_real_t rhs) {
    return anj_time_duration_eq(anj_time_real_to_duration(lhs),
                                anj_time_real_to_duration(rhs));
}
static inline bool anj_time_real_leq(const anj_time_real_t lhs,
                                     const anj_time_real_t rhs) {
    return anj_time_duration_leq(anj_time_real_to_duration(lhs),
                                 anj_time_real_to_duration(rhs));
}
static inline bool anj_time_real_geq(const anj_time_real_t lhs,
                                     const anj_time_real_t rhs) {
    return anj_time_duration_geq(anj_time_real_to_duration(lhs),
                                 anj_time_real_to_duration(rhs));
}

#    define ANJ_TIME_REAL_AS_STRING(time, unit) \
        (_anj_time_duration_as_string_impl(     \
                time.since_real_epoch,          \
                unit,                           \
                &(char[ANJ_TIME_DURATION_AS_STRING_MAX_LEN]){ "" }))

#    ifdef __cplusplus
}
#    endif

#endif // ANJ_TIME_H