#pragma once #include BEGIN_APPLEMIDI_NAMESPACE template class Deque { // class iterator; private: int _head, _tail; T _data[Size]; public: Deque() { clear(); }; size_t free(); const size_t size() const; const size_t max_size() const; T & front(); const T & front() const; T & back(); const T & back() const; void push_front(const T &); void push_back(const T &); size_t push_back(const T *, size_t); size_t copy_out(T *, size_t) const; void pop_front(); void pop_back(); T& operator[](size_t); const T& operator[](size_t) const; T& at(size_t); const T& at(size_t) const; void clear(); // iterator begin(); // iterator end(); void erase(size_t); void erase(size_t, size_t); bool empty() const { return size() == 0; } bool full() const { return (size() == Size); } }; template size_t Deque::free() { return Size - size(); } template const size_t Deque::size() const { if (_tail < 0) return 0; // empty else if (_head > _tail) return _head - _tail; else return Size - _tail + _head; } template const size_t Deque::max_size() const { return Size; } template T & Deque::front() { return _data[_tail]; } template const T & Deque::front() const { return _data[_tail]; } template T & Deque::back() { int idx = _head - 1; if (idx < 0) idx = Size - 1; return _data[idx]; } template const T & Deque::back() const { int idx = _head - 1; if (idx < 0) idx = Size - 1; return _data[idx]; } template void Deque::push_front(const T &value) { //if container is full, do nothing. if (free()){ if (--_tail < 0) _tail = Size - 1; _data[_tail] = value; } } template void Deque::push_back(const T &value) { //if container is full, do nothing. if (free()){ _data[_head] = value; if (empty()) _tail = _head; if (++_head >= Size) _head %= Size; } } template size_t Deque::push_back(const T *values, size_t count) { if (values == nullptr || count == 0) return 0; const size_t available = free(); if (available == 0) return 0; const size_t toWrite = (count < available) ? count : available; if (empty()) _tail = _head; size_t first = toWrite; if (_head + first > Size) first = Size - _head; memcpy(&_data[_head], values, first * sizeof(T)); _head = (_head + first) % Size; const size_t remaining = toWrite - first; if (remaining > 0) { memcpy(&_data[_head], values + first, remaining * sizeof(T)); _head = (_head + remaining) % Size; } return toWrite; } template size_t Deque::copy_out(T *dest, size_t count) const { if (dest == nullptr || count == 0) return 0; const size_t available = size(); if (available == 0) return 0; const size_t toCopy = (count < available) ? count : available; const size_t start = (size_t)_tail; size_t first = toCopy; if (start + first > Size) first = Size - start; memcpy(dest, &_data[start], first * sizeof(T)); const size_t remaining = toCopy - first; if (remaining > 0) memcpy(dest + first, &_data[0], remaining * sizeof(T)); return toCopy; } template void Deque::pop_front() { if (empty()) // if empty, do nothing. return; if (++_tail >= Size) _tail %= Size; if (_tail == _head) clear(); } template void Deque::pop_back() { if (empty()) // if empty, do nothing. return; if (--_head < 0) _head = Size - 1; if (_head == _tail) //now buffer is empty clear(); } template void Deque::erase(size_t position) { if (position >= size()) // out-of-range! return; // do nothing. for (size_t i = position; i < size() - 1; i++){ at(i) = at(i + 1); } pop_back(); } template void Deque::erase(size_t first, size_t last) { if (first > last // invalid arguments || first >= size()) // out-of-range return; //do nothing. size_t tgt = first; for (size_t i = last + 1; i < size(); i++){ at(tgt++) = at(i); } for (size_t i = first; i <= last; i++){ pop_back(); } } template T& Deque::operator[](size_t index) { auto i = _tail + index; if (i >= Size) i %= Size; return _data[i]; } template const T& Deque::operator[](size_t index) const { auto i = _tail + index; if (i >= Size) i %= Size; return _data[i]; } template T& Deque::at(size_t index) { auto i = _tail + index; if (i >= Size) i %= Size; return _data[i]; } template const T& Deque::at(size_t index) const { auto i = _tail + index; if (i >= Size) i %= Size; return _data[i]; } template void Deque::clear() { _tail = -1; _head = 0; } END_APPLEMIDI_NAMESPACE