5 * Created on August 1, 2009, 7:12 PM
15 /// ***** Header Class *****
17 template < class Item >
22 Array(const Array<Item>& a);
25 void init(unsigned int uiStartSize = 8, unsigned int uiSizeMultiplier = 2);
28 void alloc(unsigned int uiSize);
32 unsigned int getLength() const;
34 const Item& getAt(unsigned int uiIndex) const;
36 const Item& getFront() const;
37 const Item& getBack() const;
39 void pushFront(const Item& i);
40 void pushBack(const Item& i);
48 unsigned int getSpaceNeeded(unsigned int uiSize) const;
51 void allocFirstTime(unsigned int uiSize);
52 void allocWhenNeeded(unsigned int uiSize);
53 void allocForce(unsigned int uiSize);
55 static Item* getNextHead(Item* pHead, unsigned int uiAllocated, Item* pArrayItems);
56 static Item* getPrevHead(Item* pHead, unsigned int uiAllocated, Item* pArrayItems);
57 static Item* getNextTail(Item* pTail, unsigned int uiAllocated, Item* pArrayItems);
58 static Item* getPrevTail(Item* pTail, unsigned int uiAllocated, Item* pArrayItems);
60 static Item* withinBounds(Item* pValue, Item* pMinBound, Item* pMaxBound);
63 unsigned int m_uiStartSize;
64 unsigned int m_uiSizeMultiplier;
66 unsigned int m_uiAllocated;
69 // NULL Head _and_ NULL Tail means empty
76 template < class Item >
77 bear::Array<Item>::Array()
79 m_uiSizeMultiplier(0),
88 template < class Item >
89 bear::Array<Item>::Array(const Array<Item>& a)
91 m_uiSizeMultiplier(0),
97 // TODO: talk with colton about init/fini when using a copy constructor
98 // (potentialling called from a constructor's initailizer list.)
101 alloc(a.getLength());
103 // HACK: this should be a memcpy or something better
104 for(unsigned int ui=0; ui < a.getLength(); ui++)
106 pushBack(a.getAt(ui));
110 template < class Item >
111 void bear::Array<Item>::init
113 unsigned int uiStartSize,
114 unsigned int uiSizeMultiplier
118 bear::DASSERT(0 < uiStartSize);
119 bear::DASSERT(1 < uiSizeMultiplier);
121 m_uiStartSize = uiStartSize;
122 m_uiSizeMultiplier = uiSizeMultiplier;
126 // If this fires you have memory leaks
127 bear::DASSERT(NULL == m_pArrayItems);
128 m_pArrayItems = NULL;
133 template < class Item >
134 void bear::Array<Item>::fini()
137 m_uiSizeMultiplier = 0;
141 if(NULL != m_pArrayItems)
143 delete m_pArrayItems;
144 m_pArrayItems = NULL;
151 template < class Item >
152 void bear::Array<Item>::alloc(unsigned int uiSize)
154 if(NULL == m_pArrayItems)
156 allocFirstTime(uiSize);
158 else if(m_uiAllocated < uiSize)
163 bear::DASSERT(m_uiAllocated >= uiSize);
165 // TODO: return error when new fails
168 template < class Item >
169 void bear::Array<Item>::trim()
171 unsigned int uiSize = getLength();
172 if(NULL == m_pArrayItems)
174 allocFirstTime(uiSize);
182 bear::DASSERT(uiSize == getLength());
183 bear::DASSERT(uiSize == m_uiAllocated);
186 template < class Item >
187 bool bear::Array<Item>::isEmpty() const
189 if ( NULL == m_pHead )
191 bear::DASSERT(NULL == m_pTail);
196 bear::DASSERT(NULL != m_pTail);
201 template < class Item >
202 const Item& bear::Array<Item>::getAt(unsigned int uiIndex) const
204 // This is very bad. Fix your code
205 DASSERT(uiIndex < getLength());
207 return *withinBounds( m_pHead + uiIndex, m_pArrayItems, m_pArrayItems + m_uiAllocated );
210 template < class Item >
211 const Item& bear::Array<Item>::getFront() const
213 // This is very bad. Fix your code
214 bear::DASSERT(!isEmpty());
217 //bear::DASSERT(m_pHead <= m_uiAllocated);
222 template < class Item >
223 const Item& bear::Array<Item>::getBack() const
225 // This is very bad. Fix your code
226 bear::DASSERT(!isEmpty());
229 //bear::DASSERT(m_pTail <= m_uiAllocated);
234 template < class Item >
235 void bear::Array<Item>::pushFront(const Item& i)
237 // Make sure we have the space to add an item
238 allocWhenNeeded( getLength() + 1 );
242 m_pHead = m_pArrayItems;
243 m_pTail = m_pArrayItems;
247 m_pHead = getNextHead(m_pHead, m_uiAllocated, m_pArrayItems);
253 template < class Item >
254 void bear::Array<Item>::pushBack(const Item& i)
256 // Make sure we have the space to add an item
257 allocWhenNeeded( getLength() + 1 );
261 m_pHead = m_pArrayItems;
262 m_pTail = m_pArrayItems;
266 m_pTail = getNextTail(m_pTail, m_uiAllocated, m_pArrayItems);
272 template < class Item >
273 void bear::Array<Item>::popFront()
275 bear::DASSERT(!isEmpty());
277 if( m_pHead == m_pTail )
284 m_pHead = getPrevHead(m_pHead, m_uiAllocated, m_pArrayItems);
288 template < class Item >
289 void bear::Array<Item>::popBack()
291 bear::DASSERT(!isEmpty());
293 if( m_pHead == m_pTail )
300 m_pTail = getPrevTail(m_pTail, m_uiAllocated, m_pArrayItems);
304 template < class Item >
305 void bear::Array<Item>::clear()
315 template < class Item >
316 unsigned int bear::Array<Item>::getLength() const
324 return mod( m_pTail - m_pHead, m_uiAllocated ) + 1;
328 template < class Item >
329 void bear::Array<Item>::allocFirstTime(unsigned int uiSize)
332 bear::DASSERT(0 == m_uiAllocated);
333 bear::DASSERT(NULL == m_pArrayItems);
334 bear::DASSERT(isEmpty());
338 unsigned int uiNewAllocated = uiSize;
339 Item * pNewArrayItems = new Item[uiNewAllocated];
341 m_uiAllocated = uiNewAllocated;
342 m_pArrayItems = pNewArrayItems;
346 template < class Item >
347 void bear::Array<Item>::allocWhenNeeded(unsigned int uiSize)
349 unsigned int uiSizeNeeded = (0 == m_uiAllocated) ? m_uiStartSize : m_uiAllocated;
351 bear::DASSERT(0 < m_uiStartSize);
352 bear::DASSERT(1 < m_uiSizeMultiplier);
354 while ( uiSizeNeeded < uiSize )
356 uiSizeNeeded *= m_uiSizeMultiplier;
359 if(uiSizeNeeded > m_uiAllocated)
365 template < class Item >
366 void bear::Array<Item>::allocForce(unsigned int uiSize)
368 unsigned int uiOldLength = getLength();
370 unsigned int uiOldAllocated = m_uiAllocated;
371 Item * pOldArrayItems = m_pArrayItems;
372 Item * pOldHead = m_pHead;
373 Item * pOldTail = m_pTail;
376 m_pArrayItems = NULL;
380 unsigned int uiNewAllocated = uiSize;
381 Item * pNewArrayItems = new Item[uiNewAllocated];
382 Item * pNewHead = pNewArrayItems;
383 Item * pNewTail = pNewHead + uiOldLength - 1;
386 // Copy old items into new array
387 Item * pNewItem = pNewHead;
388 Item * pOldItem = pOldHead;
390 // TODO: this could be done using at most 2 memcpys
391 for( unsigned int ii = 0; ii < uiOldLength; ii++ )
393 *pNewItem = *pOldItem;
396 pNewItem = getNextTail(pNewItem, uiNewAllocated, pNewArrayItems);
397 pOldItem = getNextTail(pOldItem, uiOldAllocated, pOldArrayItems);
401 bear::DASSERT(pNewTail == getPrevTail(pNewItem, uiNewAllocated, pNewArrayItems));
402 bear::DASSERT(pOldTail == getPrevTail(pOldItem, uiOldAllocated, pOldArrayItems));
404 delete pOldArrayItems;
405 pOldArrayItems = NULL;
408 m_uiAllocated = uiNewAllocated;
409 m_pArrayItems = pNewArrayItems;
415 template < class Item >
416 Item* bear::Array<Item>::getNextHead
419 unsigned int uiAllocated,
423 return withinBounds( pHead - 1, pArrayItems, pArrayItems + uiAllocated );
426 template < class Item >
427 Item* bear::Array<Item>::getPrevHead
430 unsigned int uiAllocated,
434 return withinBounds( pHead + 1, pArrayItems, pArrayItems + uiAllocated );
437 template < class Item >
438 Item* bear::Array<Item>::getNextTail
441 unsigned int uiAllocated,
445 return withinBounds( pTail + 1, pArrayItems, pArrayItems + uiAllocated );
448 template < class Item >
449 Item* bear::Array<Item>::getPrevTail
452 unsigned int uiAllocated,
456 return withinBounds( pTail - 1, pArrayItems, pArrayItems + uiAllocated );
459 template < class Item >
460 Item* bear::Array<Item>::withinBounds
467 unsigned int uiValue = reinterpret_cast<unsigned int>( pValue );
468 unsigned int uiMinBound = reinterpret_cast<unsigned int>( pMinBound );
469 unsigned int uiMaxBound = reinterpret_cast<unsigned int>( pMaxBound );
471 unsigned int uiBoundedValue = uiMinBound + mod(uiValue - uiMinBound, uiMaxBound - uiMinBound);
473 Item* pBoundedValue = reinterpret_cast<Item*>(uiBoundedValue);
476 bear::DASSERT(pMinBound <= pBoundedValue);
477 bear::DASSERT(pMaxBound > pBoundedValue);
479 return pBoundedValue;