/** \brief dynamic_list_impl.h */ // -*-c++-*- // Copyright (C) 2010 Daniel Burrows // // 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 2 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; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 59 Temple Place - Suite 330, // Boston, MA 02111-1307, USA. #ifndef DYNAMIC_LIST_IMPL_H #define DYNAMIC_LIST_IMPL_H #include "dynamic_list.h" #include #include namespace aptitude { namespace util { /** \brief A basic implementation of the dynamic_list interface. */ template class dynamic_list_impl : public writable_dynamic_list, public std::enable_shared_from_this > { typedef std::vector collection; collection entries; public: dynamic_list_impl(); /** \brief Retrieve the size of this list. */ std::size_t size(); /** \brief Get the idxth element of this list. * * \param idx A nonnegative integer less than size(), giving * the index within this list of the desired * element. */ T get_at(std::size_t idx); /** \brief Create an empty list. */ static std::shared_ptr create(); void insert(const T &t, std::size_t position); void remove(std::size_t position); void move(std::size_t from, std::size_t to); }; template dynamic_list_impl::dynamic_list_impl() { } template std::shared_ptr > dynamic_list_impl::create() { return std::make_shared(); } template std::size_t dynamic_list_impl::size() { return entries.size(); } template T dynamic_list_impl::get_at(std::size_t idx) { return entries[idx]; } template void dynamic_list_impl::insert(const T &t, std::size_t position) { entries.insert(entries.begin() + position, t); this->signal_inserted(t, position); } template void dynamic_list_impl::remove(std::size_t position) { T val = entries[position]; entries.erase(entries.begin() + position); this->signal_removed(val, position); } template void dynamic_list_impl::move(std::size_t from, std::size_t to) { // Don't do anything at all, don't even emit a signal, if a // value is being moved to the same location that it already // occupies. if(from == to) return; // Simple approach: insert the value at its new location, then // delete it from its old location. // Defensive copy in case inserting into a vector from itself // does anything weird. Pure paranoia. T val = entries[from]; // If from < to, then we need to insert one entry farther than // the target location, since the entry will shift left when we // remove its old location. const std::size_t idx_to_insert = from < to ? to + 1 : to; entries.insert(entries.begin() + idx_to_insert, val); // Note that if to < from, we just changed the index of the // source of the move! Fix it up. const std::size_t idx_to_delete = to < from ? from + 1 : from; entries.erase(entries.begin() + idx_to_delete); this->signal_moved(val, from, to); } } } #endif // DYNAMIC_LIST_IMPL_H