Line data Source code
1 : #include <stdlib.h> 2 : #include <string.h> 3 : 4 : #include "RingBuffer.h" 5 : 6 143011 : ByteBuffer::ByteBuffer(uint32_t _size) 7 : { 8 143011 : buf = (uint8_t*)calloc(1, _size); 9 143011 : size = buf ? _size : 0; 10 143011 : external_buf = false; 11 143011 : } 12 : 13 19747 : ByteBuffer::~ByteBuffer(void) 14 : { 15 19747 : if (!external_buf) { 16 19745 : free(buf); 17 : } 18 19747 : } 19 : 20 : /* 21 : * Caller is responsible for locking in set_size() 22 : */ 23 2314 : bool ByteBuffer::set_size(uint32_t _size) 24 : { 25 2314 : if (external_buf) { 26 : // resize not supported with external buffer 27 26 : return false; 28 : } 29 2288 : head = tail = 0; 30 2288 : if (_size != size) { 31 2288 : free(buf); 32 2288 : buf = (uint8_t*)calloc(1, _size); 33 2288 : if (!buf) { 34 0 : size = 0; 35 0 : return false; 36 : } 37 : 38 2288 : size = _size; 39 : } 40 : 41 2288 : return true; 42 : } 43 : 44 : /* 45 : set buffer size, accepting a smaller size if desired size isn't achievable 46 : */ 47 4 : bool ByteBuffer::set_size_best(uint32_t _size) 48 : { 49 30 : while (_size > 0) { 50 28 : if (set_size(_size)) { 51 2 : return true; 52 : } 53 26 : _size = (3 * _size)/4; 54 : } 55 2 : return false; 56 : } 57 : 58 3805489715 : uint32_t ByteBuffer::available(void) const 59 : { 60 : /* use a copy on stack to avoid race conditions of @tail being updated by 61 : * the writer thread */ 62 3805489715 : uint32_t _tail = tail; 63 : 64 3805224495 : if (head > _tail) { 65 606455402 : return size - head + _tail; 66 : } 67 3199657231 : return _tail - head; 68 : } 69 : 70 250623 : void ByteBuffer::clear(void) 71 : { 72 250623 : head = tail = 0; 73 250623 : } 74 : 75 2115053114 : uint32_t ByteBuffer::space(void) const 76 : { 77 2115053114 : if (size == 0) { 78 0 : return 0; 79 : } 80 : 81 : /* use a copy on stack to avoid race conditions of @head being updated by 82 : * the reader thread */ 83 2115053114 : uint32_t _head = head; 84 2115050503 : uint32_t ret = 0; 85 : 86 2115050503 : if (_head <= tail) { 87 2007565329 : ret = size; 88 : } 89 : 90 2115049379 : ret += _head - tail - 1; 91 : 92 2115046991 : return ret; 93 : } 94 : 95 2874 : bool ByteBuffer::is_empty(void) const 96 : { 97 2874 : return head == tail; 98 : } 99 : 100 266382772 : uint32_t ByteBuffer::write(const uint8_t *data, uint32_t len) 101 : { 102 : ByteBuffer::IoVec vec[2]; 103 266382772 : const auto n_vec = reserve(vec, len); 104 266382633 : uint32_t ret = 0; 105 : 106 530662709 : for (int i = 0; i < n_vec; i++) { 107 264280076 : memcpy(vec[i].data, data + ret, vec[i].len); 108 264280076 : ret += vec[i].len; 109 : } 110 : 111 266382633 : commit(ret); 112 266382544 : return ret; 113 : } 114 : 115 : /* 116 : update bytes at the read pointer. Used to update an object without 117 : popping it 118 : */ 119 6 : bool ByteBuffer::update(const uint8_t *data, uint32_t len) 120 : { 121 6 : if (len > available()) { 122 2 : return false; 123 : } 124 : // perform as two memcpy calls 125 4 : uint32_t n = size - head; 126 4 : if (n > len) { 127 2 : n = len; 128 : } 129 4 : memcpy(&buf[head], data, n); 130 4 : data += n; 131 4 : if (len > n) { 132 2 : memcpy(&buf[0], data, len-n); 133 : } 134 4 : return true; 135 : } 136 : 137 1335599227 : bool ByteBuffer::advance(uint32_t n) 138 : { 139 1335599227 : if (n > available()) { 140 0 : return false; 141 : } 142 1335593225 : head = (head + n) % size; 143 1335589605 : return true; 144 : } 145 : 146 1332019218 : uint8_t ByteBuffer::peekiovec(ByteBuffer::IoVec iovec[2], uint32_t len) 147 : { 148 1332019218 : uint32_t n = available(); 149 : 150 1332012875 : if (len > n) { 151 839735034 : len = n; 152 : } 153 1332012875 : if (len == 0) { 154 837846344 : return 0; 155 : } 156 : 157 494166531 : auto b = readptr(n); 158 494175247 : if (n == 0) { 159 0 : iovec[0].data = buf; 160 0 : iovec[0].len = len; 161 0 : iovec[1].data = nullptr; 162 0 : iovec[1].len = 0; 163 0 : return 1; 164 : } 165 494175247 : if (n > len) { 166 486230413 : n = len; 167 : } 168 : 169 494175247 : iovec[0].data = const_cast<uint8_t *>(b); 170 494175247 : iovec[0].len = n; 171 : 172 494175247 : if (len <= n) { 173 493882893 : return 1; 174 : } 175 : 176 292354 : iovec[1].data = buf; 177 292354 : iovec[1].len = len - n; 178 : 179 292354 : return 2; 180 : } 181 : 182 : /* 183 : read len bytes without advancing the read pointer 184 : */ 185 1332018588 : uint32_t ByteBuffer::peekbytes(uint8_t *data, uint32_t len) 186 : { 187 : ByteBuffer::IoVec vec[2]; 188 1332018588 : const auto n_vec = peekiovec(vec, len); 189 1332013551 : uint32_t ret = 0; 190 : 191 1826481383 : for (int i = 0; i < n_vec; i++) { 192 494467832 : memcpy(data + ret, vec[i].data, vec[i].len); 193 494467832 : ret += vec[i].len; 194 : } 195 : 196 1332013551 : return ret; 197 : } 198 : 199 266382751 : uint8_t ByteBuffer::reserve(ByteBuffer::IoVec iovec[2], uint32_t len) 200 : { 201 266382751 : uint32_t n = space(); 202 : 203 266382640 : if (len > n) { 204 2220648 : len = n; 205 : } 206 : 207 266382640 : if (!len) { 208 2314358 : return 0; 209 : } 210 : 211 264068282 : iovec[0].data = &buf[tail]; 212 : 213 264068274 : n = size - tail; 214 264068289 : if (len <= n) { 215 263856379 : iovec[0].len = len; 216 263856379 : return 1; 217 : } 218 : 219 211910 : iovec[0].len = n; 220 : 221 211910 : iovec[1].data = buf; 222 211910 : iovec[1].len = len - n; 223 : 224 211910 : return 2; 225 : } 226 : 227 : /* 228 : * Advance the writer pointer by 'len' 229 : */ 230 266382487 : bool ByteBuffer::commit(uint32_t len) 231 : { 232 266382487 : if (len > space()) { 233 0 : return false; //Someone broke the agreement 234 : } 235 : 236 266382533 : tail = (tail + len) % size; 237 266382769 : return true; 238 : } 239 : 240 1329985719 : uint32_t ByteBuffer::read(uint8_t *data, uint32_t len) 241 : { 242 1329985719 : uint32_t ret = peekbytes(data, len); 243 1329981073 : advance(ret); 244 1329967725 : return ret; 245 : } 246 : 247 8 : bool ByteBuffer::read_byte(uint8_t *data) 248 : { 249 8 : if (!data) { 250 2 : return false; 251 : } 252 : 253 6 : int16_t ret = peek(0); 254 6 : if (ret < 0) { 255 2 : return false; 256 : } 257 : 258 4 : *data = ret; 259 : 260 4 : return advance(1); 261 : } 262 : 263 : /* 264 : * Returns the pointer and size to a contiguous read in the buffer 265 : */ 266 1243584146 : const uint8_t *ByteBuffer::readptr(uint32_t &available_bytes) 267 : { 268 1243584146 : uint32_t _tail = tail; 269 1243579848 : available_bytes = (head > _tail) ? size - head : _tail - head; 270 : 271 1243579103 : return available_bytes ? &buf[head] : nullptr; 272 : } 273 : 274 151512 : int16_t ByteBuffer::peek(uint32_t ofs) const 275 : { 276 151512 : if (ofs >= available()) { 277 64851 : return -1; 278 : } 279 86656 : return buf[(head+ofs)%size]; 280 : }