1/*
2 * Copyright 2004-2008, Fran��ois Revol, <revol@free.fr>.
3 * Distributed under the terms of the MIT License.
4 */
5
6#define _BUILDING_fs 1
7
8//#define TEST_RB
9
10#include <sys/param.h>
11#ifndef TEST_RB
12//#include "lock.h"
13#include "websearchfs.h"
14#endif
15
16#ifdef TEST_RB
17#include <OS.h>
18struct ring_buffer {
19        size_t size;
20        size_t current; /* index of next byte to read */
21        size_t avail;   /* number of bytes in */
22        unsigned char data[0];
23};
24#define ASSERT(op) if (!(op)) debugger("ASSERT: " #op " in " __FILE__ ":" __FUNCTION__)
25#else
26#define ASSERT(op) if (!(op)) panic("ASSERT: %s in %s:%s", #op, __FILE__, __FUNCTION__)
27#endif
28
29void rb_init(struct ring_buffer *rb, size_t size)
30{
31	rb->size = size;
32	rb->current = 0;
33	rb->avail = 0;
34}
35
36void rb_clear(struct ring_buffer *rb)
37{
38	rb->avail = 0;
39	rb->current = 0;
40}
41
42size_t rb_can_write(struct ring_buffer *rb)
43{
44	if (!rb)
45		return 0;
46	return (rb->size - rb->avail);
47}
48
49size_t rb_can_read(struct ring_buffer *rb)
50{
51	if (!rb)
52		return 0;
53	return rb->avail;
54}
55
56size_t rb_write(struct ring_buffer *rb, void *data, size_t len)
57{
58	size_t index, towrite, written;
59	if (!rb)
60		return 0;
61	index = (rb->current + rb->avail) % rb->size;
62	towrite = rb_can_write(rb);
63	towrite = MIN(len, towrite);
64	if (towrite < 1)
65		return 0;
66	len = rb->size - index;
67	len = MIN(len, towrite);
68	memcpy(((char *)rb->data)+index, data, len);
69	rb->avail += len;
70	written = len;
71	if (len < towrite) {
72		towrite -= len;
73		len = MIN(towrite, rb_can_write(rb));
74		index = 0;
75		memcpy(((char *)rb->data)+index, ((char *)data)+written, len);
76		rb->avail += len;
77		written += len;
78	}
79	ASSERT(rb->avail <= rb->size);
80	return written;
81}
82
83size_t rb_read(struct ring_buffer *rb, void *data, size_t len)
84{
85	size_t index, toread, got;
86	if (!rb)
87		return 0;
88	index = rb->current;
89	toread = rb_can_read(rb);
90	toread = MIN(len, toread);
91	if (toread < 1)
92		return 0;
93	len = rb->size - index;
94	len = MIN(len, toread);
95	memcpy(data, ((char *)rb->data)+index, len);
96	rb->avail -= len;
97	rb->current += len;
98	got = len;
99	if (len < toread) {
100		toread -= len;
101		len = MIN(toread, rb_can_read(rb));
102		index = 0;
103		memcpy(((char *)data)+got, ((char *)rb->data)+index, len);
104		rb->current = len;
105		rb->avail -= len;
106		got += len;
107	}
108	ASSERT(rb->avail <= rb->size);
109	return got;
110}
111
112#ifdef TEST_RB
113int main(void)
114{
115	struct _myrb {
116		struct ring_buffer rb;
117		char buff[10];
118	} myrb;
119	char buffer[10];
120	char obuffer[10];
121	int got, tow;
122	rb_init(&myrb.rb, 10);
123	while ((got = read(0, buffer, 10))) {
124		int len, olen;
125		len = rb_write(&myrb.rb, buffer, got);
126		olen = rb_read(&myrb.rb, obuffer, 10);
127		write(1, obuffer, olen);
128	}
129	return 1;
130}
131#endif
132
133
134