1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
|
/*****************************************************************************/
/* Array.h Copyright (c) Ladislav Zezula 2015 */
/*---------------------------------------------------------------------------*/
/* Common array implementation */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 30.10.15 1.00 Lad The first version of DynamicArray.h */
/* 10.08.18 1.00 Lad CLASS-ified, renamed to Array.h */
/*****************************************************************************/
#ifndef __CASC_ARRAY_H__
#define __CASC_ARRAY_H__
//-----------------------------------------------------------------------------
// Structures
class CASC_ARRAY
{
public:
CASC_ARRAY()
{
m_pItemArray = NULL;
m_ItemCountMax = 0;
m_ItemCount = 0;
m_ItemSize = 0;
}
~CASC_ARRAY()
{
Free();
}
// Creates an array with a custom element type
template<typename TYPE>
int Create(size_t ItemCountMax)
{
return Create(sizeof(TYPE), ItemCountMax);
}
// Creates an array with a custom element size
int Create(size_t ItemSize, size_t ItemCountMax)
{
// Create the array
if ((m_pItemArray = CASC_ALLOC(BYTE, ItemSize * ItemCountMax)) == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
m_ItemCountMax = ItemCountMax;
m_ItemCount = 0;
m_ItemSize = ItemSize;
return ERROR_SUCCESS;
}
// Inserts one or more items; returns pointer to the first inserted item
void * Insert(size_t NewItemCount)
{
void * pNewItems;
// Try to enlarge the buffer, if needed
if (!EnlargeArray(m_ItemCount + NewItemCount))
return NULL;
pNewItems = m_pItemArray + (m_ItemCount * m_ItemSize);
// Increment the size of the array
m_ItemCount += NewItemCount;
// Return pointer to the new item
return pNewItems;
}
// Inserts one or more items; returns pointer to the first inserted item
void * Insert(const void * NewItems, size_t NewItemCount)
{
void * pNewItem = Insert(NewItemCount);
// Copy the item(s) to the array, if any
if (pNewItem && NewItems)
memcpy(pNewItem, NewItems, (NewItemCount * m_ItemSize));
return pNewItem;
}
// Returns an item at a given index
void * ItemAt(size_t ItemIndex)
{
return (ItemIndex < m_ItemCount) ? (m_pItemArray + (ItemIndex * m_ItemSize)) : NULL;
}
void * LastItem()
{
return m_pItemArray + (m_ItemCount * m_ItemSize);
}
// Inserts an item at a given index. If there is not enough items in the array,
// the array will be enlarged. Should any gaps to be created, the function will zero them
void * InsertAt(size_t ItemIndex)
{
LPBYTE pbLastItem;
LPBYTE pbNewItem;
// Make sure we have array large enough
if(!EnlargeArray(ItemIndex + 1))
return NULL;
// Get the items range
pbLastItem = m_pItemArray + (m_ItemCount * m_ItemSize);
pbNewItem = m_pItemArray + (ItemIndex * m_ItemSize);
m_ItemCount = CASCLIB_MAX(m_ItemCount, ItemIndex+1);
// If we inserted an item past the current end, we need to clear the items in-between
if (pbNewItem > pbLastItem)
{
memset(pbLastItem, 0, (pbNewItem - pbLastItem));
m_ItemCount = ItemIndex + 1;
}
return pbNewItem;
}
// Returns index of an item
size_t IndexOf(const void * pItem)
{
LPBYTE pbItem = (LPBYTE)pItem;
assert((m_pItemArray <= pbItem) && (pbItem <= m_pItemArray + (m_ItemCount * m_ItemSize)));
assert(((pbItem - m_pItemArray) % m_ItemSize) == 0);
return ((pbItem - m_pItemArray) / m_ItemSize);
}
void * ItemArray()
{
return m_pItemArray;
}
size_t ItemCount()
{
return m_ItemCount;
}
size_t ItemCountMax()
{
return m_ItemCountMax;
}
size_t ItemSize()
{
return m_ItemSize;
}
bool IsInitialized()
{
return (m_pItemArray && m_ItemCountMax);
}
// Invalidates the entire array, but keeps memory allocated
void Reset()
{
memset(m_pItemArray, 0, m_ItemCountMax * m_ItemSize);
m_ItemCount = 0;
}
// Frees the array
void Free()
{
CASC_FREE(m_pItemArray);
m_ItemCountMax = m_ItemCount = m_ItemSize = 0;
}
protected:
bool EnlargeArray(size_t NewItemCount)
{
LPBYTE NewItemArray;
size_t ItemCountMax;
// We expect the array to be already allocated
assert(m_pItemArray != NULL);
assert(m_ItemCountMax != 0);
// Shall we enlarge the table?
if (NewItemCount > m_ItemCountMax)
{
// Calculate new table size
ItemCountMax = m_ItemCountMax;
while (ItemCountMax < NewItemCount)
ItemCountMax = ItemCountMax << 1;
// Allocate new table
NewItemArray = CASC_REALLOC(BYTE, m_pItemArray, (ItemCountMax * m_ItemSize));
if (NewItemArray == NULL)
return false;
// Set the new table size
m_ItemCountMax = ItemCountMax;
m_pItemArray = NewItemArray;
}
return true;
}
LPBYTE m_pItemArray; // Pointer to item array
size_t m_ItemCountMax; // Maximum item count
size_t m_ItemCount; // Current item count
size_t m_ItemSize; // Size of an item
};
#endif // __CASC_ARRAY__
|