| 1 |
#ifndef RING_BUFFER_H |
| 2 |
#define RING_BUFFER_H |
| 3 |
|
| 4 |
/*! |
| 5 |
\file |
| 6 |
\brief リングバッファ |
| 7 |
|
| 8 |
\author Satofumi KAMIMURA |
| 9 |
|
| 10 |
$Id$ |
| 11 |
*/ |
| 12 |
|
| 13 |
#include <vector> |
| 14 |
#include <cstring> |
| 15 |
|
| 16 |
|
| 17 |
namespace beego { |
| 18 |
/*! |
| 19 |
\brief リングバッファ |
| 20 |
*/ |
| 21 |
template<class T> class RingBuffer { |
| 22 |
RingBuffer(const RingBuffer& rhs); |
| 23 |
RingBuffer& operator = (const RingBuffer& rhs); |
| 24 |
|
| 25 |
std::vector<T> ring_buffer; |
| 26 |
size_t buffer_size; |
| 27 |
size_t first; |
| 28 |
size_t last; |
| 29 |
|
| 30 |
size_t free_size(void) { |
| 31 |
return buffer_size -1 - size(); |
| 32 |
} |
| 33 |
|
| 34 |
public: |
| 35 |
explicit RingBuffer(size_t defaultSize = 0) |
| 36 |
: buffer_size(0), first(0), last(0) { |
| 37 |
if (defaultSize > 0) { |
| 38 |
size_t buffer_size = 1; |
| 39 |
while (buffer_size < defaultSize) { |
| 40 |
buffer_size *= 2; |
| 41 |
} |
| 42 |
ring_buffer.resize(buffer_size); |
| 43 |
} |
| 44 |
} |
| 45 |
|
| 46 |
|
| 47 |
~RingBuffer(void) { |
| 48 |
} |
| 49 |
|
| 50 |
size_t size(void) { |
| 51 |
return (last >= first) ? last - first : buffer_size - (first - last); |
| 52 |
} |
| 53 |
|
| 54 |
bool empty(void) { |
| 55 |
return (first == last) ? true : false; |
| 56 |
} |
| 57 |
|
| 58 |
void put(const T* data, size_t size) { |
| 59 |
|
| 60 |
long need_size = size - free_size(); |
| 61 |
if (need_size > 0) { |
| 62 |
// バッファに入りきらない場合、拡張 |
| 63 |
size_t extend_size = (buffer_size == 0) ? 1 : buffer_size; |
| 64 |
while (need_size > 0) { |
| 65 |
need_size -= extend_size; |
| 66 |
extend_size *= 2; |
| 67 |
} |
| 68 |
ring_buffer.resize(extend_size); |
| 69 |
|
| 70 |
// 拡張サイズに合わせてデータを移動 |
| 71 |
if (first > last) { |
| 72 |
// 0 から last までのデータを、buffer_size 以降に移動させる |
| 73 |
memmove(&ring_buffer[buffer_size], |
| 74 |
&ring_buffer[0], last * sizeof(T)); |
| 75 |
last += buffer_size; |
| 76 |
} |
| 77 |
buffer_size = extend_size; |
| 78 |
} |
| 79 |
// データ配置 |
| 80 |
if (first <= last) { |
| 81 |
// last から buffer_size 終端までに配置 |
| 82 |
size_t to_end = buffer_size - last; |
| 83 |
size_t move_size = (to_end > size) ? size : to_end; |
| 84 |
memmove(&ring_buffer[last], data, move_size * sizeof(T)); |
| 85 |
last += move_size; |
| 86 |
last &= (buffer_size -1); |
| 87 |
|
| 88 |
long left_size = size - move_size; |
| 89 |
if (left_size > 0) { |
| 90 |
// 0 から first の前までを配置 |
| 91 |
memmove(&ring_buffer[0], &data[move_size], left_size * sizeof(T)); |
| 92 |
last = left_size; |
| 93 |
} |
| 94 |
} else { |
| 95 |
// last から first の前まで配置 |
| 96 |
memmove(&ring_buffer[last], data, size * sizeof(T)); |
| 97 |
last += size; |
| 98 |
} |
| 99 |
} |
| 100 |
|
| 101 |
size_t get(T* data, size_t size) { |
| 102 |
// データ取得 |
| 103 |
size_t return_size = (size <= this->size()) ? size : this->size(); |
| 104 |
|
| 105 |
if (first <= last) { |
| 106 |
memmove(data, &ring_buffer[first], return_size * sizeof(T)); |
| 107 |
first += return_size; |
| 108 |
} else { |
| 109 |
// first から buffer_size 終端までを配置 |
| 110 |
size_t to_end = buffer_size - first; |
| 111 |
size_t move_size = (to_end > return_size) ? return_size : to_end; |
| 112 |
memmove(data, &ring_buffer[first], move_size * sizeof(T)); |
| 113 |
first += move_size; |
| 114 |
first &= (buffer_size -1); |
| 115 |
|
| 116 |
long left_size = return_size - move_size; |
| 117 |
if (left_size > 0) { |
| 118 |
// 0 から last の前までを配置 |
| 119 |
memmove(&data[move_size], &ring_buffer[0], left_size * sizeof(T)); |
| 120 |
first = left_size; |
| 121 |
} |
| 122 |
} |
| 123 |
return return_size; |
| 124 |
} |
| 125 |
|
| 126 |
void clear(void) { |
| 127 |
first = 0; |
| 128 |
last = 0; |
| 129 |
} |
| 130 |
}; |
| 131 |
}; |
| 132 |
|
| 133 |
#endif /* !RING_BUFFER_H */ |