// Copyright Jean Pierre Cimalando 2018. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE or copy at // http://www.boost.org/LICENSE_1_0.txt) #include "pl_list.hpp" template pl_iterator::pl_iterator(Cell *cell) : cell_(cell) { } template bool pl_iterator::is_end() const { return cell_->next == NULL; } template Cell &pl_iterator::operator*() const { return *cell_; } template Cell *pl_iterator::operator->() const { return cell_; } template bool pl_iterator::operator==(const pl_iterator &i) const { return cell_ == i.cell_; } template bool pl_iterator::operator!=(const pl_iterator &i) const { return cell_ != i.cell_; } template pl_iterator &pl_iterator::operator++() { cell_ = cell_->next; return *this; } template pl_iterator pl_iterator::operator++(int) { pl_iterator i(cell_); cell_ = cell_->next; return i; } template pl_iterator &pl_iterator::operator--() { cell_ = cell_->prev; return *this; } template pl_iterator pl_iterator::operator--(int) { pl_iterator i(cell_); cell_ = cell_->prev; return i; } template pl_list::pl_list(std::size_t capacity) { initialize(capacity); } template pl_list::~pl_list() { if (cells_allocd_) delete[] cells_; } template pl_list::pl_list(pl_cell *cells, std::size_t ncells, external_storage_policy) { initialize(ncells, cells); } template pl_list::pl_list(const pl_list &other) { initialize(other.capacity()); for(const_iterator i = other.end(), b = other.begin(); i-- != b;) push_front(i->value); } template pl_list &pl_list::operator=(const pl_list &other) { if(this != &other) { std::size_t size = other.size(); if(size > capacity()) { pl_cell *oldcells = cells_; bool allocd = cells_allocd_; initialize(other.capacity()); if (allocd) delete[] oldcells; } clear(); for(const_iterator i = other.end(), b = other.begin(); i-- != b;) push_front(i->value); } return *this; } template std::size_t pl_list::size() const { return size_; } template std::size_t pl_list::capacity() const { return capacity_; } template bool pl_list::empty() const { return size_ == 0; } template typename pl_list::iterator pl_list::begin() { return iterator(first_); } template typename pl_list::iterator pl_list::end() { return iterator(reinterpret_cast *>(&endcell_)); } template typename pl_list::const_iterator pl_list::begin() const { return const_iterator(first_); } template typename pl_list::const_iterator pl_list::end() const { return const_iterator(reinterpret_cast *>(&endcell_)); } template void pl_list::clear() { std::size_t capacity = capacity_; pl_cell *cells = cells_; pl_cell *endcell = &*end(); size_ = 0; first_ = endcell; free_ = cells; endcell->prev = NULL; for(std::size_t i = 0; i < capacity; ++i) { cells[i].prev = (i > 0) ? &cells[i - 1] : NULL; cells[i].next = (i + 1 < capacity) ? &cells[i + 1] : NULL; cells[i].value = T(); } } template pl_cell &pl_list::front() { return *first_; } template const pl_cell &pl_list::front() const { return *first_; } template pl_cell &pl_list::back() { iterator i = end(); return *--i; } template const pl_cell &pl_list::back() const { const_iterator i = end(); return *--i; } template typename pl_list::iterator pl_list::insert(iterator pos, const T &x) { pl_cell *cell = allocate(&*pos); if (!cell) throw std::bad_alloc(); cell->value = x; return iterator(cell); } template typename pl_list::iterator pl_list::erase(iterator pos) { deallocate(&*(pos++)); return pos; } template void pl_list::push_front(const T &x) { insert(begin(), x); } template void pl_list::push_back(const T &x) { insert(end(), x); } template void pl_list::pop_front() { deallocate(first_); } template void pl_list::pop_back() { iterator i(&*end()); deallocate(&*--i); } template typename pl_list::iterator pl_list::find(const T &x) { const_iterator i = const_cast *>(this)->find(x); return iterator(&const_cast(*i)); } template typename pl_list::const_iterator pl_list::find(const T &x) const { const_iterator e = end(); for (const_iterator i = begin(); i != e; ++i) { if(i->value == x) return i; } return e; } template template typename pl_list::iterator pl_list::find_if(const Pred &p) { const_iterator i = const_cast *>(this)->find_if(p); return iterator(&const_cast(*i)); } template template typename pl_list::const_iterator pl_list::find_if(const Pred &p) const { const_iterator e = end(); for (const_iterator i = begin(); i != e; ++i) { if(p(i->value)) return i; } return e; } template void pl_list::initialize(std::size_t capacity, pl_cell *extcells) { cells_ = extcells ? extcells : new pl_cell[capacity]; cells_allocd_ = extcells ? false : true; capacity_ = capacity; endcell_.next = NULL; clear(); } template pl_cell *pl_list::allocate(pl_cell *pos) { // remove free cells front pl_cell *cell = free_; if(!cell) return NULL; free_ = cell->next; if(free_) free_->prev = NULL; // insert at position if (pos == first_) first_ = cell; cell->prev = pos->prev; if (cell->prev) cell->prev->next = cell; cell->next = pos; pos->prev = cell; ++size_; return cell; } template void pl_list::deallocate(pl_cell *cell) { if(cell->prev) cell->prev->next = cell->next; if(cell->next) cell->next->prev = cell->prev; if(cell == first_) first_ = cell->next; cell->prev = NULL; cell->next = free_; cell->value = T(); free_ = cell; --size_; }