rlm@1: /*************************************************************************** rlm@1: * Copyright (C) 2008 by Sindre AamÄs * rlm@1: * aamas@stud.ntnu.no * rlm@1: * * rlm@1: * This program is free software; you can redistribute it and/or modify * rlm@1: * it under the terms of the GNU General Public License version 2 as * rlm@1: * published by the Free Software Foundation. * rlm@1: * * rlm@1: * This program is distributed in the hope that it will be useful, * rlm@1: * but WITHOUT ANY WARRANTY; without even the implied warranty of * rlm@1: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * rlm@1: * GNU General Public License version 2 for more details. * rlm@1: * * rlm@1: * You should have received a copy of the GNU General Public License * rlm@1: * version 2 along with this program; if not, write to the * rlm@1: * Free Software Foundation, Inc., * rlm@1: * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * rlm@1: ***************************************************************************/ rlm@1: #ifndef RINGBUFFER_H rlm@1: #define RINGBUFFER_H rlm@1: rlm@1: #include "Array.h" rlm@1: #include rlm@1: #include rlm@1: #include rlm@1: rlm@1: template rlm@1: class RingBuffer { rlm@1: Array buf; rlm@1: std::size_t sz; rlm@1: std::size_t rpos; rlm@1: std::size_t wpos; rlm@1: rlm@1: public: rlm@1: RingBuffer(const std::size_t sz_in = 0) : sz(0), rpos(0), wpos(0) { reset(sz_in); } rlm@1: rlm@1: std::size_t avail() const { rlm@1: return (wpos < rpos ? 0 : sz) + rpos - wpos - 1; rlm@1: } rlm@1: rlm@1: void clear() { rlm@1: wpos = rpos = 0; rlm@1: } rlm@1: rlm@1: void fill(T value); rlm@1: rlm@1: void read(T *out, std::size_t num); rlm@1: rlm@1: void reset(std::size_t sz_in); rlm@1: rlm@1: std::size_t size() const { rlm@1: return sz - 1; rlm@1: } rlm@1: rlm@1: std::size_t used() const { rlm@1: return (wpos < rpos ? sz : 0) + wpos - rpos; rlm@1: } rlm@1: rlm@1: void write(const T *in, std::size_t num); rlm@1: }; rlm@1: rlm@1: template rlm@1: void RingBuffer::fill(const T value) { rlm@1: std::fill(buf + 0, buf + sz, value); rlm@1: rpos = 0; rlm@1: wpos = sz - 1; rlm@1: } rlm@1: rlm@1: template rlm@1: void RingBuffer::read(T *out, std::size_t num) { rlm@1: if (rpos + num > sz) { rlm@1: const std::size_t n = sz - rpos; rlm@1: rlm@1: std::memcpy(out, buf + rpos, n * sizeof(T)); rlm@1: rlm@1: rpos = 0; rlm@1: num -= n; rlm@1: out += n; rlm@1: } rlm@1: rlm@1: std::memcpy(out, buf + rpos, num * sizeof(T)); rlm@1: rlm@1: if ((rpos += num) == sz) rlm@1: rpos = 0; rlm@1: } rlm@1: rlm@1: template rlm@1: void RingBuffer::reset(const std::size_t sz_in) { rlm@1: sz = sz_in + 1; rlm@1: rpos = wpos = 0; rlm@1: buf.reset(sz_in ? sz : 0); rlm@1: } rlm@1: rlm@1: template rlm@1: void RingBuffer::write(const T *in, std::size_t num) { rlm@1: if (wpos + num > sz) { rlm@1: const std::size_t n = sz - wpos; rlm@1: rlm@1: std::memcpy(buf + wpos, in, n * sizeof(T)); rlm@1: rlm@1: wpos = 0; rlm@1: num -= n; rlm@1: in += n; rlm@1: } rlm@1: rlm@1: std::memcpy(buf + wpos, in, num * sizeof(T)); rlm@1: rlm@1: if ((wpos += num) == sz) rlm@1: wpos = 0; rlm@1: } rlm@1: rlm@1: #endif