// Copyright (C) 2016 Jochen Becher // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #include "handle.h" #include "qmt/infrastructure/qmtassert.h" #include #include namespace qmt { template class Handles { public: typedef QList> value_type; typedef typename value_type::iterator iterator; typedef typename value_type::const_iterator const_iterator; explicit Handles(bool takeOwnership = false) : m_takesOwnership(takeOwnership) { } Handles(const Handles &rhs) : m_handleList(rhs.m_handleList) { } Handles(const Handles &rhs, bool takeOwnership) : m_handleList(rhs.m_handleList), m_takesOwnership(takeOwnership) { if (m_takesOwnership && rhs.m_takesOwnership) const_cast &>(rhs).m_handleList.clear(); } ~Handles() { reset(); } Handles operator=(const Handles &rhs) { if (this != &rhs) { m_handleList = rhs.m_handleList; if (m_takesOwnership && rhs.m_takesOwnership) const_cast &>(rhs).m_handleList.clear(); } return *this; } bool takesOwnership() const { return m_takesOwnership; } bool isEmpty() const { return m_handleList.empty(); } int size() const { return m_handleList.size(); } bool contains(const Uid &uid) const { for (const Handle &handle : std::as_const(m_handleList)) { if (handle.uid() == uid) return true; } return false; } bool contains(const T *t) const { QMT_ASSERT(t, return false); return contains(t->uid()); } T *find(const Uid &uid) const { for (const Handle &handle : std::as_const(m_handleList)) { if (handle.uid() == uid) return handle.target(); } return nullptr; } T *at(int index) const { QMT_ASSERT(index >= 0 && index < m_handleList.size(), return nullptr); return m_handleList.at(index).target(); } T *at(int index) { QMT_ASSERT(index >= 0 && index < m_handleList.size(), return nullptr); return m_handleList.at(index); } int indexOf(const Uid &uid) const { int index = 0; for (const Handle &handle : std::as_const(m_handleList)) { if (handle.uid() == uid) return index; ++index; } return -1; } int indexOf(const T *t) const { QMT_ASSERT(t, return -1); return indexOf(t->uid()); } const value_type &get() const { return m_handleList; } value_type take() { value_type handles = m_handleList; m_handleList.clear(); return handles; } void set(const value_type &handles) { reset(); m_handleList = handles; } void reset() { if (m_takesOwnership) { for (const Handle &handle : std::as_const(m_handleList)) delete handle.target(); } m_handleList.clear(); } iterator begin() { return m_handleList.begin(); } iterator end() { return m_handleList.end(); } const_iterator begin() const { return m_handleList.begin(); } const_iterator end() const { return m_handleList.end(); } void add(const Uid &uid) { QMT_CHECK(uid.isValid()); m_handleList.append(Handle(uid)); } void add(T *t) { QMT_ASSERT(t, return); m_handleList.append(Handle(t)); } void insert(int beforeIndex, const Uid &uid) { QMT_ASSERT(beforeIndex >= 0 && beforeIndex <= m_handleList.size(), return); QMT_ASSERT(uid.isValid(), return); m_handleList.insert(beforeIndex, Handle(uid)); } void insert(int beforeIndex, T *t) { QMT_ASSERT(beforeIndex >= 0 && beforeIndex <= m_handleList.size(), return); QMT_ASSERT(t, return); m_handleList.insert(beforeIndex, Handle(t)); } void remove(int index) { QMT_ASSERT(index >= 0 && index < size(), return); if (m_takesOwnership) { T *t = m_handleList.at(index).target(); m_handleList.removeAt(index); delete t; } else { m_handleList.removeAt(index); } } void remove(const Uid &uid) { remove(indexOf(uid)); } void remove(T *t) { QMT_ASSERT(t, return); remove(indexOf(t)); } T * take(int index) { QMT_ASSERT(index >= 0 && index < size(), return nullptr); T *t = m_handleList.at(index).target(); m_handleList.removeAt(index); return t; } T *take(const Uid &uid) { return take(indexOf(uid)); } T *take(T *t) { QMT_ASSERT(t, return nullptr); return take(indexOf(t)); } friend bool operator==(const Handles &lhs, const Handles &rhs) { return lhs.get() == rhs.get(); } friend bool operator!=(const Handles &lhs, const Handles &rhs) { return !(lhs == rhs); } private: value_type m_handleList; bool m_takesOwnership = false; }; } // namespace qmt