#ifndef _KERNEL_LIBK_RINGBUFFER_H
#define _KERNEL_LIBK_RINGBUFFER_H

#include <libk/std.h>

struct ringbuffer {
  void* buffer;
  size_t tail;
  size_t head;
  size_t capacity;
  size_t count;
  bool full;
};

bool ringbuffer_init (struct ringbuffer* rb, size_t capacity, size_t type_size);
void ringbuffer_fini (struct ringbuffer* rb);

#define ringbuffer_pop(type, rb, data)                                                             \
  do {                                                                                             \
    if ((rb)->count != 0) {                                                                        \
      *(data) = ((type*)(rb)->buffer)[(rb)->tail];                                                 \
      (rb)->tail = ((rb)->tail + 1) % (rb)->capacity;                                              \
      (rb)->count--;                                                                               \
    }                                                                                              \
  } while (0)

#define ringbuffer_push(type, rb, data)                                                            \
  do {                                                                                             \
    if ((rb)->count != (rb)->capacity) {                                                           \
      ((type*)(rb)->buffer)[(rb)->head] = (data);                                                  \
      (rb)->head = ((rb)->head + 1) % (rb)->capacity;                                              \
      (rb)->count++;                                                                               \
    }                                                                                              \
  } while (0)

#endif // _KERNEL_LIBK_RINGBUFFER_H
