/* Jellyfish * Copyright (C) 2012 Genome group at University of Maryland. * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef __SIMPLE_CIRCULAR_BUFFER_H__ #define __SIMPLE_CIRCULAR_BUFFER_H__ #include namespace jellyfish { namespace simple_circular_buffer { // T: type of element in container. D: type of derived class for // CRTP. A: allocator type. template class base { public: explicit base(T* data) : data_(data), front_(0), back_(0), full_(false) { } // Return true if empty bool empty() const { return front_ == back_ && !full(); } // Return true if full bool full() const { return full_; } void clear() { front_ = back_; full_ = false; } // Valid only if empty() is false T& front() { return data_[front_]; } // Valid only if empty() is false T& back() { return data_[prev_index(back_)]; } // Unlike the corresponding method on list or deqeue, push_back may // fail if full() is true. Then false is returned. bool push_back(const T& x) { if(full()) return false; data_[back_] = x; back_ = next_index(back_); full_ = back_ == front_; return true; } bool push_back() { if(full()) return false; back_ = next_index(back_); full_ = back_ == front_; return true; } // Pop an element from the front. It has no effect if empty() is true void pop_front() { if(empty()) return; front_ = next_index(front_); full_ = false; } int size() const { if(full()) return static_cast(this)->capacity(); int s = back_ - front_; return s < 0 ? s + static_cast(this)->capacity() : s; } protected: int next_index(int i) const { return (i + 1) % static_cast(this)->capacity(); } int prev_index(int i) const { return i ? i - 1 : static_cast(this)->capacity() - 1; } T* data() const { return data_; } T* data_; int front_, back_; bool full_; }; template class pre_alloc : public base > { typedef base > super; public: static const int capacityConstant = capa; explicit pre_alloc(T* data) : super(data) { } static int capacity() { return capa; } }; // template > // class fixed : public base, A> { // typedef base, A> super; // public: // explicit fixed(const T v = T()) : super(capa, v) { } // // fixed(const int ignored_size, const T v = T()) : super(capa, v) { } // int capacity() const { return capa; } // }; // template > // class dyn : public base, A> { // typedef base, A> super; // public: // explicit dyn(int size, const T v = T()) : super(size, v), capa_(size) { } // int capacity() const { return capa_; } // int capa_; // }; } } #endif /* __SIMPLE_CIRCULAR_BUFFER_H__ */