File indexing completed on 2024-05-12 05:40:46

0001 /***************************************************************************
0002  *  Copyright (C) 2022 by Renaud Guezennec                               *
0003  *   http://www.rolisteam.org/contact                                      *
0004  *                                                                         *
0005  *   This software is free software; you can redistribute it and/or modify *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 #ifndef DIRECTACCESSDATASTRUCTURE_H
0021 #define DIRECTACCESSDATASTRUCTURE_H
0022 
0023 #include "utils/utils_global.h"
0024 #include <QHash>
0025 #include <QList>
0026 #include <QReadLocker>
0027 #include <QReadWriteLock>
0028 #include <QWriteLocker>
0029 
0030 template <class T, class Y>
0031 class DirectAccessDataStructure
0032 {
0033 public:
0034     DirectAccessDataStructure(){};
0035 
0036     void reserve(qsizetype size)
0037     {
0038         QWriteLocker locker(&m_lock);
0039         m_keys.reserve(size);
0040         m_data.reserve(size);
0041     };
0042 
0043     auto begin() const { return m_data.keyValueBegin(); };
0044     auto end() const { return m_data.keyValueEnd(); };
0045 
0046     Y operator[](qsizetype idx) const
0047     {
0048         QReadLocker locker(&m_lock);
0049         return m_data[m_keys[idx]];
0050     };
0051 
0052     Y operator[](const T& key) const
0053     {
0054         QReadLocker locker(&m_lock);
0055         return m_data[key];
0056     };
0057 
0058     Y value(const T& key) const
0059     {
0060         QReadLocker locker(&m_lock);
0061         return m_data[key];
0062     };
0063 
0064     void changeKey(const T& oldkey, const T& newkey, const Y& child)
0065     {
0066         QWriteLocker locker(&m_lock);
0067         m_keys.replace(m_keys.indexOf(oldkey), newkey);
0068         m_data.remove(oldkey);
0069         m_data.insert(newkey, child);
0070     }
0071 
0072     bool isEmpty() const { return m_data.isEmpty(); };
0073 
0074     qsizetype size() const { return m_data.size(); };
0075     const T key(qsizetype idx) const
0076     {
0077         QReadLocker locker(&m_lock);
0078         return m_keys[idx];
0079     };
0080 
0081     void append(const T& key, const Y& value)
0082     {
0083         QWriteLocker locker(&m_lock);
0084         m_data.insert(key, value);
0085         m_keys.append(key);
0086     };
0087 
0088     void swapItemsAt(qsizetype i, qsizetype j)
0089     {
0090         if(i < 0 || i > m_keys.size() || j > m_keys.size() || j < 0)
0091             return;
0092 
0093         QWriteLocker locker(&m_lock);
0094         m_keys.swapItemsAt(i, j);
0095     }
0096 
0097     void remove(const T& key)
0098     {
0099         QWriteLocker locker(&m_lock);
0100         if(m_data.remove(key))
0101         {
0102             m_keys.removeAll(key);
0103         }
0104     }
0105 
0106     bool contains(const T& key) const { return m_data.contains(key); }
0107     typename QHash<T, Y>::iterator find(const T& key) { return m_data.find(key); }
0108     typename QHash<T, Y>::const_iterator find(const T& key) const { return m_data.find(key); }
0109     typename QHash<T, Y>::iterator keyEnd() { return m_data.end(); }
0110     typename QHash<T, Y>::const_iterator keyConstEnd() const { return m_data.cend(); }
0111     typename QHash<T, Y>::iterator keyBegin() { return m_data.begin(); }
0112     typename QHash<T, Y>::const_iterator keyConstBegin() const { return m_data.cbegin(); }
0113 
0114     typename QList<T>::iterator orderedBegin() { return m_keys.begin(); }
0115     typename QList<T>::const_iterator orderedConstBegin() const { return m_keys.cbegin(); }
0116     typename QList<T>::iterator orderedEnd() { return m_keys.end(); }
0117     typename QList<T>::const_iterator orderedConstEnd() const { return m_keys.cend(); }
0118 
0119     qsizetype index(const T& key) const { return m_keys.indexOf(key); }
0120 
0121     template <typename Container, std::enable_if_t<std::is_same_v<QList<T>, Container>, bool> = true>
0122     Container keys() const
0123     {
0124         return m_keys;
0125     }
0126 
0127     template <typename Container, std::enable_if_t<std::is_same_v<QList<Y>, Container>, bool> = true>
0128     Container values() const
0129     {
0130         return m_data.values();
0131     }
0132 
0133     template <typename Container, std::enable_if_t<!std::is_same_v<QList<T>, Container>, bool> = true>
0134     Container keys() const
0135     {
0136         return {m_keys.cbegin(), m_keys.cend()};
0137     }
0138 
0139     void clear()
0140     {
0141         QWriteLocker locker(&m_lock);
0142         m_data.clear();
0143         m_keys.clear();
0144     };
0145 
0146     bool isValid() const { return m_keys.size() == m_data.size(); }
0147 
0148 private:
0149     QList<T> m_keys;
0150     QHash<T, Y> m_data;
0151     mutable QReadWriteLock m_lock;
0152 };
0153 
0154 #endif // DIRECTACCESSDATASTRUCTURE_H