File indexing completed on 2024-07-21 06:38:23

0001 /*
0002     SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
0003     SPDX-FileContributor: 2010 Stephen Kelly <stephen@kdab.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #ifndef KVOIDPOINTERFACTORY_P_H
0009 #define KVOIDPOINTERFACTORY_P_H
0010 
0011 #include <cstddef>
0012 #include <cstdlib>
0013 #include <vector>
0014 
0015 #define DEFAULT_BLOCK_SIZE 256
0016 
0017 /**
0018  * @brief A Class for managing void pointers for use in QModelIndexes.
0019  *
0020  * This class creates void pointers pointing to individual blocks of memory.
0021  * The pointed-to memory contains zeros.
0022  *
0023  * Memory is allocated in blocks of size @p blockSize times sizeof(void*) at a time. The used
0024  * memory is automatically freed and can be cleared manually.
0025  *
0026  * The void pointers should not be dereferenced, but only used as a unique
0027  * identifier suitable for use with createIndex() and for comparison with other void pointers.
0028  */
0029 template<std::size_t blockSize = DEFAULT_BLOCK_SIZE>
0030 class KVoidPointerFactory
0031 {
0032     // a class with size 1.
0033     class Bit
0034     {
0035         bool bit;
0036     };
0037 
0038 public:
0039     KVoidPointerFactory()
0040         : m_previousPointer(nullptr)
0041         , m_finalPointer(nullptr)
0042     {
0043     }
0044 
0045     KVoidPointerFactory(const KVoidPointerFactory<blockSize> &other)
0046     {
0047         *this = other;
0048     }
0049 
0050     KVoidPointerFactory<blockSize> &operator=(const KVoidPointerFactory<blockSize> &other)
0051     {
0052         m_previousPointer = other.m_previousPointer;
0053         m_finalPointer = other.m_finalPointer;
0054         m_blocks = other.m_blocks;
0055         return *this;
0056     }
0057 
0058     ~KVoidPointerFactory()
0059     {
0060         clear();
0061     }
0062 
0063     void clear()
0064     {
0065         typename std::vector<Bit *>::const_iterator it = m_blocks.begin();
0066         const typename std::vector<Bit *>::const_iterator end = m_blocks.end();
0067         for (; it != end; ++it) {
0068             free(*it);
0069         }
0070         m_blocks.clear();
0071         m_finalPointer = nullptr;
0072         m_previousPointer = nullptr;
0073     }
0074 
0075     void *createPointer() const
0076     {
0077         if (m_previousPointer == m_finalPointer) {
0078             static const std::size_t pointer_size = sizeof(Bit *);
0079             Bit *const bit = static_cast<Bit *>(calloc(blockSize, pointer_size));
0080             m_blocks.push_back(bit);
0081             m_finalPointer = bit + (blockSize * pointer_size) - 1;
0082             m_previousPointer = bit;
0083             return bit;
0084         }
0085         return ++m_previousPointer;
0086     }
0087 
0088 private:
0089     mutable std::vector<Bit *> m_blocks;
0090     mutable Bit *m_previousPointer;
0091     mutable Bit *m_finalPointer;
0092 };
0093 
0094 // Disable factory with 0 blockSize
0095 template<>
0096 class KVoidPointerFactory<0>
0097 {
0098 public:
0099     KVoidPointerFactory();
0100 
0101     void clear();
0102     void *createPointer();
0103 };
0104 
0105 #endif