1 /*************************************************************************/ 2 /* ring_buffer.h */ 3 /*************************************************************************/ 4 /* This file is part of: */ 5 /* GODOT ENGINE */ 6 /* https://godotengine.org */ 7 /*************************************************************************/ 8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ 9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ 10 /* */ 11 /* Permission is hereby granted, free of charge, to any person obtaining */ 12 /* a copy of this software and associated documentation files (the */ 13 /* "Software"), to deal in the Software without restriction, including */ 14 /* without limitation the rights to use, copy, modify, merge, publish, */ 15 /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 /* permit persons to whom the Software is furnished to do so, subject to */ 17 /* the following conditions: */ 18 /* */ 19 /* The above copyright notice and this permission notice shall be */ 20 /* included in all copies or substantial portions of the Software. */ 21 /* */ 22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 /*************************************************************************/ 30 #ifndef RINGBUFFER_H 31 #define RINGBUFFER_H 32 33 #include "vector.h" 34 35 template <typename T> 36 class RingBuffer { 37 38 Vector<T> data; 39 int read_pos; 40 int write_pos; 41 int size_mask; 42 inc(int & p_var,int p_size)43 inline int inc(int &p_var, int p_size) { 44 int ret = p_var; 45 p_var += p_size; 46 p_var = p_var & size_mask; 47 return ret; 48 }; 49 50 public: read()51 T read() { 52 ERR_FAIL_COND_V(space_left() < 1, T()); 53 return data[inc(read_pos, 1)]; 54 }; 55 56 int read(T *p_buf, int p_size, bool p_advance = true) { 57 int left = data_left(); 58 p_size = MIN(left, p_size); 59 int pos = read_pos; 60 int to_read = p_size; 61 int dst = 0; 62 while (to_read) { 63 int end = pos + to_read; 64 end = MIN(end, size()); 65 int total = end - pos; 66 for (int i = 0; i < total; i++) { 67 p_buf[dst++] = data[pos + i]; 68 }; 69 to_read -= total; 70 pos = 0; 71 }; 72 if (p_advance) { 73 inc(read_pos, p_size); 74 }; 75 return p_size; 76 }; 77 copy(T * p_buf,int p_offset,int p_size)78 int copy(T *p_buf, int p_offset, int p_size) { 79 80 int left = data_left(); 81 if ((p_offset + p_size) > left) { 82 p_size -= left - p_offset; 83 if (p_size <= 0) 84 return 0; 85 } 86 p_size = MIN(left, p_size); 87 int pos = read_pos; 88 inc(pos, p_offset); 89 int to_read = p_size; 90 int dst = 0; 91 while (to_read) { 92 int end = pos + to_read; 93 end = MIN(end, size()); 94 int total = end - pos; 95 for (int i = 0; i < total; i++) { 96 p_buf[dst++] = data[pos + i]; 97 }; 98 to_read -= total; 99 pos = 0; 100 }; 101 return p_size; 102 }; 103 advance_read(int p_n)104 inline int advance_read(int p_n) { 105 p_n = MIN(p_n, data_left()); 106 inc(read_pos, p_n); 107 return p_n; 108 }; 109 write(const T & p_v)110 Error write(const T &p_v) { 111 ERR_FAIL_COND_V(space_left() < 1, FAILED); 112 data[inc(write_pos, 1)] = p_v; 113 return OK; 114 }; 115 write(const T * p_buf,int p_size)116 int write(const T *p_buf, int p_size) { 117 118 int left = space_left(); 119 p_size = MIN(left, p_size); 120 121 int pos = write_pos; 122 int to_write = p_size; 123 int src = 0; 124 while (to_write) { 125 126 int end = pos + to_write; 127 end = MIN(end, size()); 128 int total = end - pos; 129 130 for (int i = 0; i < total; i++) { 131 data[pos + i] = p_buf[src++]; 132 }; 133 to_write -= total; 134 pos = 0; 135 }; 136 137 inc(write_pos, p_size); 138 return p_size; 139 }; 140 space_left()141 inline int space_left() { 142 int left = read_pos - write_pos; 143 if (left < 0) { 144 return size() + left - 1; 145 }; 146 if (left == 0) { 147 return size() - 1; 148 }; 149 return left - 1; 150 }; data_left()151 inline int data_left() { 152 return size() - space_left() - 1; 153 }; 154 size()155 inline int size() { 156 return data.size(); 157 }; 158 clear()159 inline void clear() { 160 read_pos = 0; 161 write_pos = 0; 162 } 163 resize(int p_power)164 void resize(int p_power) { 165 int old_size = size(); 166 int new_size = 1 << p_power; 167 int mask = new_size - 1; 168 data.resize(1 << p_power); 169 if (old_size < new_size && read_pos > write_pos) { 170 for (int i = 0; i < write_pos; i++) { 171 data[(old_size + i) & mask] = data[i]; 172 }; 173 write_pos = (old_size + write_pos) & mask; 174 } else { 175 read_pos = read_pos & mask; 176 write_pos = write_pos & mask; 177 }; 178 179 size_mask = mask; 180 }; 181 182 RingBuffer<T>(int p_power = 0) { 183 read_pos = 0; 184 write_pos = 0; 185 resize(p_power); 186 }; 187 ~RingBuffer<T>(){}; 188 }; 189 190 #endif 191