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