btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / src / add-ons / kernel / file_systems / googlefs / ringbuff.c
blob684e8ae1a0a2bb7e9e88bec48efe99d58b73135e
1 /*
2 * Copyright 2004-2008, François Revol, <revol@free.fr>.
3 * Distributed under the terms of the MIT License.
4 */
6 #define _BUILDING_fs 1
8 //#define TEST_RB
10 #include <sys/param.h>
11 #ifndef TEST_RB
12 //#include "lock.h"
13 #include "googlefs.h"
14 #endif
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];
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
29 void rb_init(struct ring_buffer *rb, size_t size)
31 rb->size = size;
32 rb->current = 0;
33 rb->avail = 0;
36 void rb_clear(struct ring_buffer *rb)
38 rb->avail = 0;
39 rb->current = 0;
42 size_t rb_can_write(struct ring_buffer *rb)
44 if (!rb)
45 return 0;
46 return (rb->size - rb->avail);
49 size_t rb_can_read(struct ring_buffer *rb)
51 if (!rb)
52 return 0;
53 return rb->avail;
56 size_t rb_write(struct ring_buffer *rb, void *data, size_t len)
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;
79 ASSERT(rb->avail <= rb->size);
80 return written;
83 size_t rb_read(struct ring_buffer *rb, void *data, size_t len)
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;
108 ASSERT(rb->avail <= rb->size);
109 return got;
112 #ifdef TEST_RB
113 int main(void)
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);
129 return 1;
131 #endif