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 | * @brief 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 @p 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 | |