Develop Biology
The language of life
Container.cpp
Go to the documentation of this file.
1/*
2 * This file is a part of the Biology project by eons LLC.
3 * Biology (aka Develop Biology) is a framework for approaching software
4 * development from a natural sciences perspective.
5 *
6 * Copyright (C) 2022 Séon O'Shannon & eons LLC
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as
10 * published by the Free Software Foundation, either version 3 of the
11 * License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
24#include <limits>
25#include <algorithm>
26
27namespace bio {
28
30 const Index expectedSize,
31 std::size_t stepSize
32)
33 :
34 m_firstFree(1),
35 m_size(expectedSize + 1),
36 m_tempItt(NULL)
37{
38 m_store = (unsigned char*)std::malloc(m_size * stepSize);
40}
41
43 :
44 m_firstFree(other.m_firstFree),
45 m_size(other.m_size),
46 m_tempItt(NULL)
47{
48 m_store = (unsigned char*)std::malloc(m_size * other.GetStepSize());
50 Import(&other); // <- NOT VIRTUAL (in ctor).
51}
52
54{
55 Clear(); // <- NOT VIRTUAL (in dtor).
56 if (m_tempItt)
57 {
58 delete m_tempItt;
59 m_tempItt = NULL;
60 }
61 std::free(m_store);
62}
63
65{
66 return 1;
67}
68
70{
71 return GetAllocatedSize();
72}
73
75{
76 return m_size;
77}
78
80{
81 return m_firstFree;
82}
83
85{
86 return GetAllocatedSize() - m_deallocated.size();
87}
88
89bool Container::IsInRange(const Index index) const
90{
91 return index && index < m_size;
92}
93
94bool Container::IsFree(Index index) const
95{
96 if (index >= m_firstFree)
97 {
98 return true;
99 }
100 return std::find(
101 m_deallocated.begin(),
102 m_deallocated.end(),
103 index
104 ) != m_deallocated.end();
105}
106
107bool Container::IsAllocated(const Index index) const
108{
109 return IsInRange(index) && !IsFree(index);
110}
111
113{
114 BIO_SANITIZE(m_size < std::numeric_limits< Index >::max(), ,
115 return)
116 Index targetSize = m_size * m_size; //squared.
117 if (targetSize < m_size)
118 {
119 targetSize = std::numeric_limits< Index >::max();
120 }
121 m_store = (unsigned char*)std::realloc(
122 m_store,
123 targetSize * GetStepSize());
125 return)
126 m_size = targetSize;
127}
128
130{
132 BIO_SANITIZE(ret, ,
133 return ret)
134 std::memcpy(
135 &m_store[ret * sizeof(ByteStream)],
136 content,
137 sizeof(ByteStream));
138 return ret;
139}
140
142 const ByteStream content,
143 const Index index
144)
145{
146 BIO_SANITIZE(index, ,
147 return InvalidIndex())
148
149 if (index == m_firstFree)
150 {
151 //no adjustment necessary.
152 Add(content);
153 }
154
155 if (GetAllocatedSize() == GetCapacity())
156 {
157 Expand();
158 }
159
160 //move all memory down 1.
161 std::memcpy(
162 &m_store[index * GetStepSize()],
163 &m_store[(index + 1) * GetStepSize()],
164 (m_firstFree - index) * GetStepSize());
165
166 //adjust all deallocated positions.
167 std::deque< Index > adjustedDeallocations;
168 for (
169 std::deque< Index >::iterator dlc = m_deallocated.begin();
170 dlc != m_deallocated.end();
171 ++dlc
172 )
173 {
174 adjustedDeallocations.push_front(*dlc + 1);
175 }
176 m_deallocated = adjustedDeallocations;
177
178 //make sure we add to the desired index.
179 m_deallocated.push_front(index);
180
181 //add the content.
182 return Add(content);
183}
184
186{
187 BIO_SANITIZE(IsAllocated(index), ,
188 return NULL)
189 ByteStream* ret;
190 std::memcpy(
191 ret,
192 &m_store[index * sizeof(ByteStream)],
193 sizeof(ByteStream));
194 return *ret;
195}
196
197const ByteStream Container::Access(const Index index) const
198{
199 BIO_SANITIZE(IsAllocated(index), ,
200 return NULL)
201 ByteStream* ret;
202 std::memcpy(
203 ret,
204 &m_store[index * sizeof(ByteStream)],
205 sizeof(ByteStream));
206 return *ret;
207}
208
210{
211 if (!m_tempItt)
212 {
214 }
216 for (
218 --m_tempItt
219 )
220 {
221 if (AreEqual(
223 content
224 ))
225 {
226 return m_tempItt->GetIndex();
227 }
228 }
229 return InvalidIndex();
230}
231
232bool Container::Has(const ByteStream content) const
233{
234 return SeekTo(content); //implicit cast to bool should work.
235}
236
237bool Container::Erase(const Index index)
238{
239 BIO_SANITIZE(IsAllocated(index), ,
240 return false)
241 ByteStream* toDelete;
242 std::memcpy(
243 toDelete,
244 &m_store[index * sizeof(ByteStream)],
245 sizeof(ByteStream));
246 delete toDelete;
247 m_deallocated.push_back(index);
248 return true;
249}
250
251void Container::Import(const Container* other)
252{
253 BIO_SANITIZE(other, ,
254 return)
255 Iterator* otr = other->End();
256 for (
257 ; !otr->IsAtBeginning();
258 --otr
259 )
260 {
261 Add(**otr);
262 }
263}
264
266{
267 //Call destructors before clearing the array.
268 if (!m_tempItt)
269 {
271 }
273 for (
275 --m_tempItt
276 )
277 {
279 }
280
281 m_firstFree = 1;
282 m_deallocated.clear();
283}
284
286{
287 BIO_SANITIZE(IsAllocated(index), ,
288 return NULL)
289 return new Iterator(
290 this,
291 index
292 );
293}
294
296{
297 return SmartIterator(
298 this,
299 GetBeginIndex());
300}
301
303{
304 return SmartIterator(
305 this,
306 GetEndIndex());
307}
308
310{
311 return Access(index);
312}
313
314const ByteStream Container::operator[](const Index index) const
315{
316 return Access(index);
317}
318
320{
321 return Access(itt);
322}
323
325{
326 return Access(itt);
327}
328
330{
331 Index ret = InvalidIndex();
332 if (!m_deallocated.empty())
333 {
334 ret = m_deallocated.front();
335 m_deallocated.pop_front();
336 }
337 else if (m_firstFree == m_size)
338 {
339 Expand();
340 ret = m_firstFree++;
341 }
342 return ret;
343}
344
346 Index internal,
347 const ByteStream external
348) const
349{
350 return Access(internal) == external;
351}
352
353const std::size_t Container::GetStepSize() const
354{
355 return sizeof(ByteStream);
356}
357
358} //bio namespace
#define BIO_ASSERT(cond)
Definition: AssertMacros.h:29
#define BIO_SANITIZE(test, success, failure)
virtual SmartIterator End() const
Definition: Container.cpp:302
virtual SmartIterator Begin() const
Definition: Container.cpp:295
virtual ByteStream Access(const Index index)
Definition: Container.cpp:185
virtual Index GetCapacity() const
Definition: Container.cpp:74
virtual void Clear()
Definition: Container.cpp:265
virtual bool AreEqual(Index internal, const ByteStream external) const
Definition: Container.cpp:345
Container(const Index expectedSize=2, std::size_t stepSize=sizeof(ByteStream))
Definition: Container.cpp:29
unsigned char * m_store
Definition: Container.h:340
virtual bool IsInRange(const Index index) const
Definition: Container.cpp:89
virtual Index Insert(const ByteStream content, const Index index)
Definition: Container.cpp:141
virtual Index GetNextAvailableIndex()
Definition: Container.cpp:329
virtual Index GetNumberOfElements() const
Definition: Container.cpp:84
Index m_firstFree
Definition: Container.h:343
Index SeekTo(const ByteStream content) const
Definition: Container.cpp:209
virtual bool IsFree(const Index index) const
Definition: Container.cpp:94
virtual bool IsAllocated(const Index index) const
Definition: Container.cpp:107
virtual ByteStream operator[](const Index index)
Definition: Container.cpp:309
virtual Index GetAllocatedSize() const
Definition: Container.cpp:79
virtual const std::size_t GetStepSize() const
Definition: Container.cpp:353
virtual Index GetBeginIndex() const
Definition: Container.cpp:64
virtual void Import(const Container *other)
Definition: Container.cpp:251
virtual ~Container()
Definition: Container.cpp:53
bool Has(const ByteStream content) const
Definition: Container.cpp:232
virtual Index Add(const ByteStream content)
Definition: Container.cpp:129
std::deque< Index > m_deallocated
Definition: Container.h:344
virtual bool Erase(Index index)
Definition: Container.cpp:237
virtual Iterator * ConstructClassIterator(const Index index=InvalidIndex()) const
Definition: Container.cpp:285
virtual void Expand()
Definition: Container.cpp:112
Iterator * m_tempItt
Definition: Container.h:350
virtual Index GetEndIndex() const
Definition: Container.cpp:69
bool MoveTo(const Index index)
Definition: Iterator.cpp:48
virtual bool IsAtBeginning() const
Definition: Iterator.cpp:58
Index GetIndex() const
Definition: Iterator.cpp:43
Definition: Cell.h:31
uint32_t Index
Definition: Types.h:57
const Index InvalidIndex()
Definition: Types.cpp:26