ring_buffer.h
1 /*************************************************************************/
2 /* ring_buffer.h */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* http://www.godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
9 /* */
10 /* Permission is hereby granted, free of charge, to any person obtaining */
11 /* a copy of this software and associated documentation files (the */
12 /* "Software"), to deal in the Software without restriction, including */
13 /* without limitation the rights to use, copy, modify, merge, publish, */
14 /* distribute, sublicense, and/or sell copies of the Software, and to */
15 /* permit persons to whom the Software is furnished to do so, subject to */
16 /* the following conditions: */
17 /* */
18 /* The above copyright notice and this permission notice shall be */
19 /* included in all copies or substantial portions of the Software. */
20 /* */
21 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
22 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
23 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
24 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
25 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
26 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
27 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
28 /*************************************************************************/
29 #ifndef RINGBUFFER_H
30 #define RINGBUFFER_H
31 
32 #include "vector.h"
33 
34 template <typename T>
35 class RingBuffer {
36 
37  Vector<T> data;
38  int read_pos;
39  int write_pos;
40  int size_mask;
41 
42  inline int inc(int& p_var, int p_size) {
43  int ret = p_var;
44  p_var += p_size;
45  p_var = p_var&size_mask;
46  return ret;
47  };
48 
49 public:
50 
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 
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 
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 
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 
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 
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  };
151  inline int data_left() {
152  return size() - space_left() - 1;
153  };
154 
155  inline int size() {
156  return data.size();
157  };
158 
159  inline void clear() {
160  read_pos = 0;
161  write_pos = 0;
162 
163  }
164 
165  void resize(int p_power) {
166  int old_size = size();
167  int new_size = 1<<p_power;
168  int mask = new_size - 1;
169  data.resize(1<<p_power);
170  if (old_size < new_size && read_pos > write_pos) {
171  for (int i=0; i<write_pos; i++) {
172  data[(old_size + i)&mask] = data[i];
173  };
174  write_pos = (old_size + write_pos) & mask;
175  } else {
176  read_pos = read_pos & mask;
177  write_pos = write_pos & mask;
178  };
179 
180  size_mask = mask;
181  };
182 
183  RingBuffer<T>(int p_power=0) {
184  read_pos = 0;
185  write_pos = 0;
186  resize(p_power);
187  };
188  ~RingBuffer<T>() {};
189 };
190 
191 #endif
Definition: ring_buffer.h:35
Definition: vector.h:43