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