#ifndef RB_SIMPLE_H
#define RB_SIMPLE_H
// simple ringbuffer with pthread locking
// Copyright 2025 Sensoray Co. Inc.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define RB_BUF_SIZE 16384

struct rb_simple {
	unsigned char buffer[RB_BUF_SIZE];
	int head;
	int tail;
	int count;
	pthread_mutex_t mutex;
};

static
void rb_simple_destroy(struct rb_simple *rb) {
    pthread_mutex_destroy(&rb->mutex);
}

static
void rb_simple_init(struct rb_simple *rb) {
    rb->head = 0;
    rb->tail = 0;
    rb->count = 0;
    pthread_mutex_init(&rb->mutex, NULL);
}

static
int rb_simple_is_empty(struct rb_simple *rb) {
    return rb->count == 0;
}

static
int rb_simple_is_full(struct rb_simple *rb) {
    return rb->count == RB_BUF_SIZE;
}

static
int rb_simple_enqueue(struct rb_simple *rb, unsigned char *buf, int len) {
	int i;

	pthread_mutex_lock(&rb->mutex);
	for (i = 0; i < len; i++) {
		if (rb_simple_is_full(rb)) {
			pthread_mutex_unlock(&rb->mutex);
			return -1;
		}
		rb->buffer[rb->tail] = buf[i];
		rb->tail = (rb->tail + 1) % RB_BUF_SIZE;
		rb->count++;
	}
	pthread_mutex_unlock(&rb->mutex);
	return 0;
}

static
int rb_simple_dequeue(struct rb_simple *rb, unsigned char *data, int len) {
	int i;
	unsigned char *pdata = data;
	pthread_mutex_lock(&rb->mutex);
	for (i = 0; i < len; i++) {
		if (rb_simple_is_empty(rb)) {
			pthread_mutex_unlock(&rb->mutex);
			return -1;
		}
		*pdata++ = rb->buffer[rb->head];
		rb->head = (rb->head + 1) % RB_BUF_SIZE;
		rb->count--;
	}
	pthread_mutex_unlock(&rb->mutex);
	return 0;
}


#ifdef DEBUG_RB_MODULE
int main() {
	unsigned char tbuf[1024];
	unsigned char tbuf2[1024];
	int i;
	struct rb_simple rb;
	unsigned char data[1024];

	memset(tbuf, 3, 1024);
	memset(tbuf2, 8, 1024);
	for (i = 0; i < 30; i++)
		tbuf[i] = i;

	rb_simple_init(&rb);
	rb_simple_enqueue(&rb, tbuf, 64);
	rb_simple_enqueue(&rb, tbuf2, 64);


	while (rb_simple_dequeue(&rb, data, 4) == 0) {
		printf("rb_result: %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3]);
	}
	rb_simple_destroy(&rb);
	return 0;
}
#endif

#endif
