| 1 | /* |
| 2 | SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net> |
| 3 | SPDX-FileContributor: 2010 Stephen Kelly <stephen@kdab.com> |
| 4 | |
| 5 | SPDX-License-Identifier: LGPL-2.0-or-later |
| 6 | */ |
| 7 | |
| 8 | #ifndef KVOIDPOINTERFACTORY_P_H |
| 9 | #define KVOIDPOINTERFACTORY_P_H |
| 10 | |
| 11 | #include <cstddef> |
| 12 | #include <cstdlib> |
| 13 | #include <vector> |
| 14 | |
| 15 | #define DEFAULT_BLOCK_SIZE 256 |
| 16 | |
| 17 | /* |
| 18 | * A Class for managing void pointers for use in QModelIndexes. |
| 19 | * |
| 20 | * This class creates void pointers pointing to individual blocks of memory. |
| 21 | * The pointed-to memory contains zeros. |
| 22 | * |
| 23 | * Memory is allocated in blocks of size \a blockSize times sizeof(void*) at a time. The used |
| 24 | * memory is automatically freed and can be cleared manually. |
| 25 | * |
| 26 | * The void pointers should not be dereferenced, but only used as a unique |
| 27 | * identifier suitable for use with createIndex() and for comparison with other void pointers. |
| 28 | */ |
| 29 | template<std::size_t blockSize = DEFAULT_BLOCK_SIZE> |
| 30 | class KVoidPointerFactory |
| 31 | { |
| 32 | // a class with size 1. |
| 33 | class Bit |
| 34 | { |
| 35 | bool bit; |
| 36 | }; |
| 37 | |
| 38 | public: |
| 39 | KVoidPointerFactory() |
| 40 | : m_previousPointer(nullptr) |
| 41 | , m_finalPointer(nullptr) |
| 42 | { |
| 43 | } |
| 44 | |
| 45 | KVoidPointerFactory(const KVoidPointerFactory<blockSize> &other) |
| 46 | { |
| 47 | *this = other; |
| 48 | } |
| 49 | |
| 50 | KVoidPointerFactory<blockSize> &operator=(const KVoidPointerFactory<blockSize> &other) |
| 51 | { |
| 52 | m_previousPointer = other.m_previousPointer; |
| 53 | m_finalPointer = other.m_finalPointer; |
| 54 | m_blocks = other.m_blocks; |
| 55 | return *this; |
| 56 | } |
| 57 | |
| 58 | ~KVoidPointerFactory() |
| 59 | { |
| 60 | clear(); |
| 61 | } |
| 62 | |
| 63 | void clear() |
| 64 | { |
| 65 | typename std::vector<Bit *>::const_iterator it = m_blocks.begin(); |
| 66 | const typename std::vector<Bit *>::const_iterator end = m_blocks.end(); |
| 67 | for (; it != end; ++it) { |
| 68 | free(*it); |
| 69 | } |
| 70 | m_blocks.clear(); |
| 71 | m_finalPointer = nullptr; |
| 72 | m_previousPointer = nullptr; |
| 73 | } |
| 74 | |
| 75 | void *createPointer() const |
| 76 | { |
| 77 | if (m_previousPointer == m_finalPointer) { |
| 78 | static const std::size_t pointer_size = sizeof(Bit *); |
| 79 | Bit *const bit = static_cast<Bit *>(calloc(nmemb: blockSize, size: pointer_size)); |
| 80 | m_blocks.push_back(bit); |
| 81 | m_finalPointer = bit + (blockSize * pointer_size) - 1; |
| 82 | m_previousPointer = bit; |
| 83 | return bit; |
| 84 | } |
| 85 | return ++m_previousPointer; |
| 86 | } |
| 87 | |
| 88 | private: |
| 89 | mutable std::vector<Bit *> m_blocks; |
| 90 | mutable Bit *m_previousPointer; |
| 91 | mutable Bit *m_finalPointer; |
| 92 | }; |
| 93 | |
| 94 | // Disable factory with 0 blockSize |
| 95 | template<> |
| 96 | class KVoidPointerFactory<0> |
| 97 | { |
| 98 | public: |
| 99 | KVoidPointerFactory(); |
| 100 | |
| 101 | void clear(); |
| 102 | void *createPointer(); |
| 103 | }; |
| 104 | |
| 105 | #endif |
| 106 | |