xref: /haiku/src/add-ons/kernel/file_systems/websearchfs/ringbuff.c (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
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>
18 struct 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 
29 void rb_init(struct ring_buffer *rb, size_t size)
30 {
31 	rb->size = size;
32 	rb->current = 0;
33 	rb->avail = 0;
34 }
35 
36 void rb_clear(struct ring_buffer *rb)
37 {
38 	rb->avail = 0;
39 	rb->current = 0;
40 }
41 
42 size_t rb_can_write(struct ring_buffer *rb)
43 {
44 	if (!rb)
45 		return 0;
46 	return (rb->size - rb->avail);
47 }
48 
49 size_t rb_can_read(struct ring_buffer *rb)
50 {
51 	if (!rb)
52 		return 0;
53 	return rb->avail;
54 }
55 
56 size_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 
83 size_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
113 int 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