File indexing completed on 2024-12-22 05:17:14
0001 /* 0002 * This file is part of the KDE wacomtablet project. For copyright 0003 * information and license terms see the AUTHORS and COPYING files 0004 * in the top-level directory of this distribution. 0005 * 0006 * This program is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU General Public License as 0008 * published by the Free Software Foundation; either version 2 of 0009 * the License, or (at your option) any later version. 0010 * 0011 * This program is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 * GNU General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU General Public License 0017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0018 */ 0019 0020 #ifndef ENUM_H 0021 #define ENUM_H 0022 0023 #include <QList> 0024 0025 namespace Wacom 0026 { 0027 0028 /** 0029 * A typesafe enumeration template class. It can be used as a comfortable replacement 0030 * for C++ enums and supports the following features: 0031 * 0032 * - enumerators can be listed and iterated over 0033 * - enumerator lists are sorted by a given comparator 0034 * - enumerators can have a key assigned 0035 * - enumerator keys can be listed and searched for 0036 * 0037 * NOTICE 0038 * This class uses template specialization to store a static set of all instances. 0039 * Thereofore a specialization of the private instances member 'instances' has 0040 * to be declared and instantiated before this template can be used. 0041 * 0042 * \tparam D The derived sub class type. This is the class which contains the enum instances. 0043 * \tparam K The key type used for these instances. 0044 * \tparam L A "less than" functor which can compare objects of type D*. 0045 * \tparam E A "equal to" functor which can compare objects of type K. 0046 */ 0047 template<class D, class K, class L, class E> 0048 class Enum 0049 { 0050 private: 0051 typedef QList<const D *> Container; 0052 typedef typename Container::const_iterator ContainerConstIterator; 0053 0054 public: 0055 typedef typename Container::size_type size_type; 0056 0057 /** 0058 * A constant iterator which can be used to iterator over all known Enum instances. 0059 */ 0060 class const_iterator 0061 { 0062 public: 0063 const_iterator() 0064 { 0065 } 0066 const_iterator(const const_iterator &iter) 0067 { 0068 operator=(iter); 0069 } 0070 const_iterator(const ContainerConstIterator &iter) 0071 { 0072 m_iter = iter; 0073 } 0074 0075 const D &operator*() const 0076 { 0077 return **m_iter; 0078 } 0079 const D *operator->() const 0080 { 0081 return *m_iter; 0082 } 0083 const_iterator &operator=(const const_iterator &iter) 0084 { 0085 m_iter = iter.m_iter; 0086 return *this; 0087 } 0088 bool operator==(const const_iterator &iter) const 0089 { 0090 return (m_iter == iter.m_iter); 0091 } 0092 bool operator!=(const const_iterator &iter) const 0093 { 0094 return (m_iter != iter.m_iter); 0095 } 0096 const_iterator &operator++() 0097 { 0098 ++m_iter; 0099 return *this; 0100 } 0101 const_iterator operator++(int) 0102 { 0103 const_iterator copy(*this); 0104 ++(*this); 0105 return copy; 0106 } 0107 const_iterator &operator--() 0108 { 0109 --m_iter; 0110 return *this; 0111 } 0112 const_iterator operator--(int) 0113 { 0114 const_iterator copy(*this); 0115 --(*this); 0116 return copy; 0117 } 0118 0119 private: 0120 ContainerConstIterator m_iter; 0121 }; 0122 0123 /** 0124 * Equal-Compare Operator. 0125 */ 0126 bool operator==(const Enum<D, K, L, E> &that) const 0127 { 0128 return (m_derived == that.m_derived); 0129 } 0130 0131 /** 0132 * Not-Equal-Compare Operator. 0133 */ 0134 bool operator!=(const Enum<D, K, L, E> &that) const 0135 { 0136 return (m_derived != that.m_derived); 0137 } 0138 0139 /** 0140 * @return A constant iterator to the first element. 0141 */ 0142 static const_iterator begin() 0143 { 0144 // force the use of const_iterator - fixes compile problem with some containers 0145 const Enum<D, K, L, E>::Container *container = &Enum<D, K, L, E>::instances; 0146 return const_iterator(container->begin()); 0147 } 0148 0149 /** 0150 * @return A constant iterator to the last element. 0151 */ 0152 static const_iterator end() 0153 { 0154 // force the use of const_iterator - fixes compile problem with some containers 0155 const Enum<D, K, L, E>::Container *container = &Enum<D, K, L, E>::instances; 0156 return const_iterator(container->end()); 0157 } 0158 0159 /** 0160 * Searches for the enumeration instance by key. 0161 * 0162 * @param key The key of the instance to search. 0163 * 0164 * @return A constant pointer to the instance or nullptr if not found. 0165 */ 0166 static const D *find(const K &key) 0167 { 0168 E comp; 0169 for (const_iterator i = begin(); i != end(); ++i) { 0170 if (comp(i->key(), key)) { 0171 return &(*i); 0172 } 0173 } 0174 return nullptr; 0175 } 0176 0177 /** 0178 * @return A list of all valid enum instances of this specialization. 0179 */ 0180 static QList<D> list() 0181 { 0182 QList<D> enums; 0183 for (const_iterator i = begin(); i != end(); ++i) { 0184 enums.push_back(*i); 0185 } 0186 return enums; 0187 } 0188 0189 /** 0190 * @return The key of this enum instance. 0191 */ 0192 const K &key() const 0193 { 0194 return m_key; 0195 } 0196 0197 /** 0198 * Returns a list of all instances' keys of this specialization. 0199 * 0200 * @return A list of keys sorted by the less-than-functor. 0201 */ 0202 static QList<K> keys() 0203 { 0204 QList<K> keys; 0205 for (const_iterator i = begin(); i != end(); ++i) { 0206 keys.push_back(i->key()); 0207 } 0208 return keys; 0209 } 0210 0211 /** 0212 * @return The number of enum instances of this specialization. 0213 */ 0214 static size_type size() 0215 { 0216 return Enum<D, K, L, E>::instances.size(); 0217 } 0218 0219 protected: 0220 /** 0221 * Initialization constructor. 0222 * Used to initialize class-static members. Never make this constructor 0223 * available to the public! Never use it for normal instances! It may 0224 * only be used to instantiate class-static Enum instances. 0225 * 0226 * @param derived A const pointer to the derived class of this instance. 0227 * @param key The key of this class-static Enum instance. 0228 */ 0229 explicit Enum(const D *derived, const K &key) 0230 : m_key(key) 0231 { 0232 m_derived = derived; 0233 insert(derived); 0234 } 0235 0236 /** 0237 * \return A const pointer to the derived class of this instance. 0238 */ 0239 const D *derived() const 0240 { 0241 return m_derived; 0242 } 0243 0244 private: 0245 /** 0246 * Inserts an element into to the static instances container. 0247 * This method should only be called by the constructor! 0248 * 0249 * \param derived An instance of the derived class, never NULL. 0250 */ 0251 void insert(const D *derived) 0252 { 0253 L comp; 0254 typename Enum<D, K, L, E>::Container::iterator i = this->instances.begin(); 0255 0256 for (; i != this->instances.end(); ++i) { 0257 if (comp(derived, *i)) { 0258 this->instances.insert(i, derived); 0259 return; 0260 } 0261 } 0262 0263 this->instances.push_back(derived); 0264 } 0265 0266 K m_key; /**< The key of this instance */ 0267 const D *m_derived; /**< Pointer to derived class for fast comparison */ 0268 0269 /** 0270 * A static container with all the class-static Enum instances. 0271 * Every specialization of this template has to declare and instantiate 0272 * the specialization of this member variable! 0273 */ 0274 static Container instances; 0275 0276 }; // CLASS 0277 } // NAMESPACE 0278 #endif // HEADER PROTECTION