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
rb_init(struct ring_buffer * rb,size_t size)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
rb_clear(struct ring_buffer * rb)36 void rb_clear(struct ring_buffer *rb)
37 {
38 rb->avail = 0;
39 rb->current = 0;
40 }
41
rb_can_write(struct ring_buffer * rb)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
rb_can_read(struct ring_buffer * rb)49 size_t rb_can_read(struct ring_buffer *rb)
50 {
51 if (!rb)
52 return 0;
53 return rb->avail;
54 }
55
rb_write(struct ring_buffer * rb,void * data,size_t len)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
rb_read(struct ring_buffer * rb,void * data,size_t len)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
main(void)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