#ifndef UTIL_UTIL_H_
#define UTIL_UTIL_H_

#include <stdint.h>
#include <stddef.h>

#define _DIV_ROUNDUP(num, div) ((num + div - 1) / div)
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define LEN(X) (sizeof(X)/sizeof(X[0]))

#define LL_APPEND(head, new) \
  do { \
    if ((new) != NULL) { \
      if ((head) != NULL) { \
        typeof((head)) __tmp; \
        (new)->next = NULL; \
        __tmp = (head); \
        while (__tmp->next != NULL) { \
          __tmp = __tmp->next; \
        } \
        __tmp->next = (new); \
      } else { \
        (new)->next = NULL; \
        (head) = (new); \
      } \
    } \
  } while(0)

#define LL_REMOVE(head, ele) \
  do { \
    if ((head) != NULL && (ele) != NULL) { \
      typeof((head)) __cur = (head); \
      typeof((head)) __prev = NULL; \
      while (__cur != NULL && __cur != (ele)) { \
        __prev = __cur; \
        __cur = __cur->next; \
      } \
      if (__cur == (ele)) { \
        if (__prev != NULL) { \
          __prev->next = __cur->next; \
        } else { \
          (head) = __cur->next; \
        } \
        (ele)->next = NULL; \
      } \
    } \
  } while(0)

#define LL_FINDPROP(head, out, propname, propvalue) \
  do { \
    (out) = NULL; \
    typeof((head)) __tmp = (head); \
    while (__tmp) { \
      if (__tmp->propname == (propvalue)) { \
        (out) = __tmp; \
        break; \
      } \
      __tmp = __tmp->next; \
    } \
  } while(0)

#define LL_FOREACH_SAFE(head, var, tmp) \
  for (var = (head), tmp = (var ? var->next : NULL); \
      var != NULL; \
      var = tmp, tmp = (var ? var->next : NULL) \
      )

#define LL_FOREACH_SAFE_IDX(head, var, tmp, idx) \
  for ((idx) = 0, var = (head), tmp = (var ? var->next : NULL); \
       var != NULL; \
       var = tmp, tmp = (var ? var->next : NULL), (idx)++)

#define LL_FOREACH_SAFE_IDX_LIMIT(head, var, tmp, idx, max) \
  for ((idx) = 0, var = (head), tmp = (var ? var->next : NULL); \
       var != NULL && (idx) < (max); \
       var = tmp, tmp = (var ? var->next : NULL), (idx)++)

char *util_get_filename(char *path);
const char *human_size(uint64_t bytes, char *buf, size_t bufsize);

#endif // UTIL_UTIL_H_
