⛏️ index : haiku.git

/*
 * Copyright 2004-2008, FranΓ§ois Revol, <revol@free.fr>.
 * Distributed under the terms of the MIT License.
 */

#define _BUILDING_fs 1

//#define TEST_RB

#include <sys/param.h>
#ifndef TEST_RB
//#include "lock.h"
#include "websearchfs.h"
#endif

#ifdef TEST_RB
#include <OS.h>
struct ring_buffer {
        size_t size;
        size_t current; /* index of next byte to read */
        size_t avail;   /* number of bytes in */
        unsigned char data[0];
};
#define ASSERT(op) if (!(op)) debugger("ASSERT: " #op " in " __FILE__ ":" __FUNCTION__)
#else
#define ASSERT(op) if (!(op)) panic("ASSERT: %s in %s:%s", #op, __FILE__, __FUNCTION__)
#endif

void rb_init(struct ring_buffer *rb, size_t size)
{
	rb->size = size;
	rb->current = 0;
	rb->avail = 0;
}

void rb_clear(struct ring_buffer *rb)
{
	rb->avail = 0;
	rb->current = 0;
}

size_t rb_can_write(struct ring_buffer *rb)
{
	if (!rb)
		return 0;
	return (rb->size - rb->avail);
}

size_t rb_can_read(struct ring_buffer *rb)
{
	if (!rb)
		return 0;
	return rb->avail;
}

size_t rb_write(struct ring_buffer *rb, void *data, size_t len)
{
	size_t index, towrite, written;
	if (!rb)
		return 0;
	index = (rb->current + rb->avail) % rb->size;
	towrite = rb_can_write(rb);
	towrite = MIN(len, towrite);
	if (towrite < 1)
		return 0;
	len = rb->size - index;
	len = MIN(len, towrite);
	memcpy(((char *)rb->data)+index, data, len);
	rb->avail += len;
	written = len;
	if (len < towrite) {
		towrite -= len;
		len = MIN(towrite, rb_can_write(rb));
		index = 0;
		memcpy(((char *)rb->data)+index, ((char *)data)+written, len);
		rb->avail += len;
		written += len;
	}
	ASSERT(rb->avail <= rb->size);
	return written;
}

size_t rb_read(struct ring_buffer *rb, void *data, size_t len)
{
	size_t index, toread, got;
	if (!rb)
		return 0;
	index = rb->current;
	toread = rb_can_read(rb);
	toread = MIN(len, toread);
	if (toread < 1)
		return 0;
	len = rb->size - index;
	len = MIN(len, toread);
	memcpy(data, ((char *)rb->data)+index, len);
	rb->avail -= len;
	rb->current += len;
	got = len;
	if (len < toread) {
		toread -= len;
		len = MIN(toread, rb_can_read(rb));
		index = 0;
		memcpy(((char *)data)+got, ((char *)rb->data)+index, len);
		rb->current = len;
		rb->avail -= len;
		got += len;
	}
	ASSERT(rb->avail <= rb->size);
	return got;
}

#ifdef TEST_RB
int main(void)
{
	struct _myrb {
		struct ring_buffer rb;
		char buff[10];
	} myrb;
	char buffer[10];
	char obuffer[10];
	int got, tow;
	rb_init(&myrb.rb, 10);
	while ((got = read(0, buffer, 10))) {
		int len, olen;
		len = rb_write(&myrb.rb, buffer, got);
		olen = rb_read(&myrb.rb, obuffer, 10);
		write(1, obuffer, olen);
	}
	return 1;
}
#endif