/
githubmirror
/
aria2
Обзор
Документация
Войти
/
githubmirror
/
aria2
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/IndexedList.h
600 строк
20 KB
Tatsuhiro Tsujikawa
clang-format-3.9
15 окт 2016, 13:02
15 окт 2016, 13:02
aa4ea88
Код
Авторство
О чём код?
/* <!-- copyright */ /* * aria2 - The high speed download utility * * Copyright (C) 2012 Tatsuhiro Tsujikawa * * 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; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. If you * do not wish to do so, delete this exception statement from your * version. If you delete this exception statement from all source * files in the program, then also delete it here. */ /* copyright --> */ #ifndef D_INDEXED_LIST_H #define D_INDEXED_LIST_H #include "common.h" #include <deque> #include <unordered_map> #include <vector> #include <algorithm> #include <aria2/aria2.h> namespace aria2 { template <typename SeqType, typename ValueType, typename ReferenceType, typename PointerType, typename SeqIteratorType> struct IndexedListIterator { typedef IndexedListIterator<SeqType, ValueType, ValueType&, ValueType*, typename SeqType::iterator> iterator; typedef IndexedListIterator<SeqType, ValueType, const ValueType&, const ValueType*, typename SeqType::const_iterator> const_iterator; typedef typename SeqIteratorType::iterator_category iterator_category; typedef ValueType value_type; typedef PointerType pointer; typedef ReferenceType reference; typedef typename SeqType::size_type size_type; typedef typename SeqType::difference_type difference_type; typedef IndexedListIterator SelfType; IndexedListIterator() = default; IndexedListIterator(const iterator& other) : p(other.p) {} IndexedListIterator(const SeqIteratorType& p) : p(p) {} reference operator*() const { return (*p).second; } pointer operator->() const { return &(*p).second; } SelfType& operator++() { ++p; return *this; } SelfType operator++(int) { SelfType copy = *this; ++*this; return copy; } SelfType& operator--() { --p; return *this; } SelfType operator--(int) { SelfType copy = *this; --*this; return copy; } SelfType& operator+=(difference_type n) { std::advance(p, n); return *this; } SelfType operator+(difference_type n) const { SelfType copy = *this; return copy += n; } SelfType& operator-=(difference_type n) { std::advance(p, -n); return *this; } SelfType operator-(difference_type n) const { SelfType copy = *this; return copy -= n; } reference operator[](size_type n) const { return p[n].second; } SeqIteratorType p; }; template <typename SeqType, typename ValueType, typename ReferenceType, typename PointerType, typename SeqIteratorType> bool operator==(const IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>& lhs, const IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>& rhs) { return lhs.p == rhs.p; } template <typename SeqType, typename ValueType, typename ReferenceTypeL, typename PointerTypeL, typename SeqIteratorTypeL, typename ReferenceTypeR, typename PointerTypeR, typename SeqIteratorTypeR> bool operator==(const IndexedListIterator<SeqType, ValueType, ReferenceTypeL, PointerTypeL, SeqIteratorTypeL>& lhs, const IndexedListIterator<SeqType, ValueType, ReferenceTypeR, PointerTypeR, SeqIteratorTypeR>& rhs) { return lhs.p == rhs.p; } template <typename SeqType, typename ValueType, typename ReferenceType, typename PointerType, typename SeqIteratorType> bool operator!=(const IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>& lhs, const IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>& rhs) { return lhs.p != rhs.p; } template <typename SeqType, typename ValueType, typename ReferenceTypeL, typename PointerTypeL, typename SeqIteratorTypeL, typename ReferenceTypeR, typename PointerTypeR, typename SeqIteratorTypeR> bool operator!=(const IndexedListIterator<SeqType, ValueType, ReferenceTypeL, PointerTypeL, SeqIteratorTypeL>& lhs, const IndexedListIterator<SeqType, ValueType, ReferenceTypeR, PointerTypeR, SeqIteratorTypeR>& rhs) { return lhs.p != rhs.p; } template <typename SeqType, typename ValueType, typename ReferenceType, typename PointerType, typename SeqIteratorType> bool operator<(const IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>& lhs, const IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>& rhs) { return lhs.p < rhs.p; } template <typename SeqType, typename ValueType, typename ReferenceTypeL, typename PointerTypeL, typename SeqIteratorTypeL, typename ReferenceTypeR, typename PointerTypeR, typename SeqIteratorTypeR> bool operator<(const IndexedListIterator<SeqType, ValueType, ReferenceTypeL, PointerTypeL, SeqIteratorTypeL>& lhs, const IndexedListIterator<SeqType, ValueType, ReferenceTypeR, PointerTypeR, SeqIteratorTypeR>& rhs) { return lhs.p < rhs.p; } template <typename SeqType, typename ValueType, typename ReferenceType, typename PointerType, typename SeqIteratorType> bool operator>(const IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>& lhs, const IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>& rhs) { return lhs.p > rhs.p; } template <typename SeqType, typename ValueType, typename ReferenceTypeL, typename PointerTypeL, typename SeqIteratorTypeL, typename ReferenceTypeR, typename PointerTypeR, typename SeqIteratorTypeR> bool operator>(const IndexedListIterator<SeqType, ValueType, ReferenceTypeL, PointerTypeL, SeqIteratorTypeL>& lhs, const IndexedListIterator<SeqType, ValueType, ReferenceTypeR, PointerTypeR, SeqIteratorTypeR>& rhs) { return lhs.p > rhs.p; } template <typename SeqType, typename ValueType, typename ReferenceType, typename PointerType, typename SeqIteratorType> bool operator<=(const IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>& lhs, const IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>& rhs) { return lhs.p <= rhs.p; } template <typename SeqType, typename ValueType, typename ReferenceTypeL, typename PointerTypeL, typename SeqIteratorTypeL, typename ReferenceTypeR, typename PointerTypeR, typename SeqIteratorTypeR> bool operator<=(const IndexedListIterator<SeqType, ValueType, ReferenceTypeL, PointerTypeL, SeqIteratorTypeL>& lhs, const IndexedListIterator<SeqType, ValueType, ReferenceTypeR, PointerTypeR, SeqIteratorTypeR>& rhs) { return lhs.p <= rhs.p; } template <typename SeqType, typename ValueType, typename ReferenceType, typename PointerType, typename SeqIteratorType> bool operator>=(const IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>& lhs, const IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>& rhs) { return lhs.p >= rhs.p; } template <typename SeqType, typename ValueType, typename ReferenceTypeL, typename PointerTypeL, typename SeqIteratorTypeL, typename ReferenceTypeR, typename PointerTypeR, typename SeqIteratorTypeR> bool operator>=(const IndexedListIterator<SeqType, ValueType, ReferenceTypeL, PointerTypeL, SeqIteratorTypeL>& lhs, const IndexedListIterator<SeqType, ValueType, ReferenceTypeR, PointerTypeR, SeqIteratorTypeR>& rhs) { return lhs.p >= rhs.p; } template <typename SeqType, typename ValueType, typename ReferenceType, typename PointerType, typename SeqIteratorType> IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType> operator+( typename IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>::difference_type n, const IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>& lhs) { return lhs + n; } template <typename SeqType, typename ValueType, typename ReferenceType, typename PointerType, typename SeqIteratorType> typename IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>::difference_type operator-(const IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>& lhs, const IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>& rhs) { return typename IndexedListIterator<SeqType, ValueType, ReferenceType, PointerType, SeqIteratorType>::difference_type(lhs.p - rhs.p); } template <typename SeqType, typename ValueType, typename ReferenceTypeL, typename PointerTypeL, typename SeqIteratorTypeL, typename ReferenceTypeR, typename PointerTypeR, typename SeqIteratorTypeR> typename IndexedListIterator<SeqType, ValueType, ReferenceTypeL, PointerTypeL, SeqIteratorTypeL>::difference_type operator-(const IndexedListIterator<SeqType, ValueType, ReferenceTypeL, PointerTypeL, SeqIteratorTypeL>& lhs, const IndexedListIterator<SeqType, ValueType, ReferenceTypeR, PointerTypeR, SeqIteratorTypeR>& rhs) { return typename IndexedListIterator<SeqType, ValueType, ReferenceTypeL, PointerTypeL, SeqIteratorTypeL>::difference_type(lhs.p - rhs.p); } template <typename KeyType, typename ValuePtrType> class IndexedList { public: IndexedList() = default; ~IndexedList() = default; typedef KeyType key_type; typedef ValuePtrType value_type; typedef std::unordered_map<KeyType, ValuePtrType> IndexType; typedef std::deque<std::pair<KeyType, ValuePtrType>> SeqType; typedef IndexedListIterator<SeqType, ValuePtrType, ValuePtrType&, ValuePtrType*, typename SeqType::iterator> iterator; typedef IndexedListIterator<SeqType, ValuePtrType, const ValuePtrType&, const ValuePtrType*, typename SeqType::const_iterator> const_iterator; ValuePtrType& operator[](size_t n) { return seq_[n].second; } const ValuePtrType& operator[](size_t n) const { return seq_[n].second; } // Inserts (|key|, |value|) to the end of the list. If the same key // has been already added, this function fails. This function // returns true if it succeeds. Complexity: O(1) bool push_back(KeyType key, ValuePtrType value) { auto i = index_.find(key); if (i == std::end(index_)) { index_.insert({key, value}); seq_.emplace_back(key, value); return true; } else { return false; } } // Inserts (|key|, |value|) to the front of the list. If the same // key has been already added, this function fails. This function // returns true if it succeeds. Complexity: O(1) bool push_front(KeyType key, ValuePtrType value) { auto i = index_.find(key); if (i == std::end(index_)) { index_.insert({key, value}); seq_.emplace_front(key, value); return true; } else { return false; } } // Inserts (|key|, |value|) to the position |dest|. If the same key // has been already added, this function fails. This function // returns the iterator to the newly added element if it is // succeeds, or end(). Complexity: O(N) iterator insert(size_t dest, KeyType key, ValuePtrType value) { if (dest > size()) { return std::end(seq_); } auto i = index_.find(key); if (i == std::end(index_)) { auto j = std::begin(seq_); std::advance(j, dest); index_.insert({key, value}); return iterator(seq_.insert(j, {key, value})); } else { return iterator(std::end(seq_)); } } // Inserts (|key|, |value|) to the position |dest|. If the same key // has been already added, this function fails. This function // returns the iterator to the newly added element if it is // succeeds, or end(). Complexity: O(1) if inserted to the first or // last, otherwise O(N) iterator insert(iterator dest, KeyType key, ValuePtrType value) { auto i = index_.find(key); if (i == std::end(index_)) { index_.insert({key, value}); return iterator(seq_.insert(dest.p, {key, value})); } else { return iterator(std::end(seq_)); } } // Inserts values in iterator range [first, last). The key for each // value is retrieved by functor |keyFunc|. The insertion position // is given by |dest|. template <typename KeyFunc, typename InputIterator> void insert(iterator dest, KeyFunc keyFunc, InputIterator first, InputIterator last) { std::vector<typename SeqType::value_type> v; v.reserve(std::distance(first, last)); for (; first != last; ++first) { auto key = keyFunc(*first); auto i = index_.find(key); if (i == std::end(index_)) { index_.insert({key, *first}); v.emplace_back(key, *first); } } seq_.insert(dest.p, std::begin(v), std::end(v)); } template <typename KeyFunc, typename InputIterator> void insert(size_t pos, KeyFunc keyFunc, InputIterator first, InputIterator last) { if (pos > size()) { return; } std::vector<typename SeqType::value_type> v; v.reserve(std::distance(first, last)); for (; first != last; ++first) { auto key = keyFunc(*first); auto i = index_.find(key); if (i == std::end(index_)) { index_.insert({key, *first}); v.emplace_back(key, *first); } } seq_.insert(std::begin(seq_) + pos, std::begin(v), std::end(v)); } // Removes |key| from the list. If the element is not found, this // function fails. This function returns true if it // succeeds. Complexity: O(N) bool remove(KeyType key) { auto i = index_.find(key); if (i == std::end(index_)) { return false; } for (auto j = std::begin(seq_), eoj = std::end(seq_); j != eoj; ++j) { if ((*j).first == key) { seq_.erase(j); break; } } index_.erase(i); return true; } // Removes element pointed by iterator |k| from the list. If the // iterator must be valid. This function returns the iterator // pointing to the element following the erased element. Complexity: // O(N) iterator erase(iterator k) { index_.erase((*k.p).first); return iterator(seq_.erase(k.p)); } // Removes elements for which Pred returns true. The pred is called // against each each element once per each. template <typename Pred> void remove_if(Pred pred) { auto first = std::begin(seq_), last = std::end(seq_); for (; first != last && !pred((*first).second); ++first) ; if (first == last) { return; } index_.erase((*first).first); auto store = first; ++first; for (; first != last; ++first) { if (pred((*first).second)) { index_.erase((*first).first); } else { *store++ = *first; } } seq_.erase(store, last); } // Removes element at the front of the list. If the list is empty, // this function fails. This function returns true if it // succeeds. Complexity: O(1) bool pop_front() { if (seq_.empty()) { return false; } index_.erase(seq_.front().first); seq_.pop_front(); return true; } // Moves element with |key| to the specified position. If |how| is // OFFSET_MODE_CUR, the element is moved to the position |offset| // relative to the current position. If |how| is OFFSET_MODE_SET, // the element is moved to the position |offset|. If |how| is // OFFSET_MODE_END, the element is moved to the position |offset| // relative to the end of the list. This function returns the // position the element is moved to if it succeeds, or -1 if no // element with |key| is found or |how| is invalid. Complexity: // O(N) ssize_t move(KeyType key, ssize_t offset, OffsetMode how) { auto idxent = index_.find(key); if (idxent == std::end(index_)) { return -1; } auto x = std::begin(seq_), eseq = std::end(seq_); for (; x != eseq; ++x) { if ((*x).first == (*idxent).first) { break; } } ssize_t xp = std::distance(std::begin(seq_), x); ssize_t size = index_.size(); ssize_t dest; if (how == OFFSET_MODE_CUR) { if (offset > 0) { dest = std::min(xp + offset, static_cast<ssize_t>(size - 1)); } else { dest = std::max(xp + offset, static_cast<ssize_t>(0)); } } else { if (how == OFFSET_MODE_END) { dest = std::min(size - 1 + offset, size - 1); } else if (how == OFFSET_MODE_SET) { dest = std::min(offset, size - 1); } else { return -1; } dest = std::max(dest, static_cast<ssize_t>(0)); } auto d = std::begin(seq_); std::advance(d, dest); if (xp < dest) { std::rotate(x, x + 1, d + 1); } else { std::rotate(d, x, x + 1); } return dest; } // Returns the value associated by |key|. If it is not found, // returns ValuePtrType(). Complexity: O(1) ValuePtrType get(KeyType key) const { auto idxent = index_.find(key); if (idxent == std::end(index_)) { return ValuePtrType(); } else { return (*idxent).second; } } size_t size() const { return index_.size(); } size_t empty() const { return index_.empty(); } iterator begin() { return iterator(std::begin(seq_)); } iterator end() { return iterator(std::end(seq_)); } const_iterator begin() const { return const_iterator(std::begin(seq_)); } const_iterator end() const { return const_iterator(std::end(seq_)); } // Removes all elements from the list. void clear() { index_.clear(); seq_.clear(); } private: SeqType seq_; IndexType index_; }; } // namespace aria2 #endif // D_INDEXED_LIST_H