#ifndef DS_UTIL_H
#define DS_UTIL_H
+#include <stdbool.h>
#include <stdint.h>
#include <time.h>
+#include <stdlib.h>
+
+#include "libds/log.h"
+
+#ifndef DS_LIKELY
+#ifdef __GNUC__
+#define DS_LIKELY(x) (__builtin_expect(!!(x),1))
+#define DS_UNLIKELY(x) (__builtin_expect(!!(x),0))
+#else
+#define DS_LIKELY(x) (x)
+#define DS_UNLIKELY(x) (x)
+#endif
+#endif
+
+#define DS_RETURN_IF_FAIL(expr) \
+ do { \
+ if (DS_UNLIKELY(!(expr))) { \
+ ds_err("'%s' failed at %s:%u %s()\n", \
+ #expr, __FILE__, __LINE__, __func__); \
+ return; \
+ } \
+ } while (false)
+
+#define DS_RETURN_VAL_IF_FAIL(expr, val) \
+ do { \
+ if (DS_UNLIKELY(!(expr))) { \
+ ds_err("'%s' failed at %s:%u %s()\n", \
+ #expr, __FILE__, __LINE__, __func__); \
+ return (val); \
+ } \
+ } while (false)
+
+#define DS_ASSERT(expr) \
+ do { \
+ if (DS_UNLIKELY(!(expr))) { \
+ ds_err("'%s' failed at %s:%u %s()\n", \
+ #expr, __FILE__, __LINE__, __func__); \
+ abort(); \
+ } \
+ } while (false)
+
+#define DS_ASSERT_NOT_REACHED() \
+ do { \
+ ds_err("Code should not be reached at %s:%u %s()\n", \
+ __FILE__, __LINE__, __func__); \
+ abort(); \
+ } while (false)
+
+#define DS_FLAG_MASK(field, mask, flag) (((field) & (mask)) == (flag))
+#define DS_FLAG_IS_SET(field, flag) DS_FLAG_MASK(field, flag, flag)
+
+#define DS_FLAG_SET(field, flag) ((field) |= (flag))
+#define DS_FLAG_CLEAR(field, flag) ((field) &= ~(__typeof__(field))(flag))
+#define DS_FLAG_UPDATE(field, flag, val) ((val) ? \
+ DS_FLAG_SET((field), (flag)) : DS_FLAG_CLEAR((field), (flag)))
+
+#define DS_MIN(a, b) \
+({ \
+ __typeof__(a) _min_a = (a); \
+ __typeof__(b) _min_b = (b); \
+ DS_LIKELY(_min_a <= _min_b) ? _min_a : _min_b; \
+})
+
+#define DS_MAX(a, b) \
+({ \
+ __typeof__(a) _max_a = (a); \
+ __typeof__(b) _max_b = (b); \
+ DS_LIKELY(_max_a >= _max_b) ? _max_a : _max_b; \
+})
+
+#define DS_SWAP(a, b) \
+({ \
+ __typeof__(a) _t = (a); \
+ (a) = b; (b) = _t; \
+})
int64_t
timespec_to_msec(const struct timespec *a);