convert line ends
[canaan.git] / prj / tech / libsrc / cpptools / dynarray.cpp
blob8a8aa09d91d9b87a43cb954f94838d49d21225e2
1 ///////////////////////////////////////////////////////////////////////////////
2 // $Source: x:/prj/tech/libsrc/cpptools/RCS/dynarray.cpp $
3 // $Author: TOML $
4 // $Date: 1998/05/23 07:08:04 $
5 // $Revision: 1.11 $
6 //
8 #include <lg.h>
9 #include <dynarray.h>
11 #include <stdlib.h>
13 #ifndef NO_DB_MEM
14 // Must be last header
15 #include <memall.h>
16 #include <dbmem.h>
17 #endif
19 //include "storintr.h"
21 ///////////////////////////////////////////////////////////////////////////////
23 // CLASS: cDynArrayBase
26 #ifndef SHIP
27 char BASED_CODE cDynArrayBase::gm_pszOutOfRange[] = "Index out of range";
28 #endif
30 ///////////////////////////////////////
32 // Assignment operator
35 cDynArrayBase& cDynArrayBase::operator=(const cDynArrayBase &Array)
37 // Blow the current array away
38 SetSize(0);
40 // Copy the values
41 m_nBlockSizeLessOne = Array.m_nBlockSizeLessOne;
42 m_nItemSize = Array.m_nItemSize;
43 m_nItems = Array.m_nItems;
44 VerifyMsg(Resize(m_nItems), "Array allocation failed");
46 AssertMsg(!m_nItems || m_pItems, "Expected items in dynarray");
48 // Call set item for all the items
49 for (index_t i = 0; i<m_nItems; i++)
50 SetItem(Array.ItemPtr(i), i);
52 return *this;
55 ///////////////////////////////////////
57 // Resize the array buffer to the desired number of slots.
59 // NOTE: The logical size does not change.
62 BOOL cDynArrayBase::DoResize(index_t evenSlots)
64 if (evenSlots)
66 tDynArrayItem *newP;
68 // Note: Allow for scratch block at the end
69 if (m_pItems)
70 newP = realloc(m_pItems, (evenSlots+1) * m_nItemSize);
71 else
72 newP = malloc((evenSlots+1) * m_nItemSize);
74 AssertMsg(newP, "Dynamic array resize failed");
76 if (!newP)
77 return FALSE;
79 m_pItems = (BYTE *) newP;
82 else if (m_pItems)
84 free(m_pItems);
85 m_pItems = 0;
88 m_nSlots = evenSlots;
90 return TRUE;
94 ///////////////////////////////////////
96 // MoveItemToIndex
98 // Move an element to a specified position in the array, shifting
99 // other element in the list appropriately.
102 void cDynArrayBase::MoveItemToIndex(index_t currentIndex, index_t newIndex)
104 AssertMsg(currentIndex < m_nItems && newIndex < m_nItems, gm_pszOutOfRange);
106 if (currentIndex == newIndex)
107 return;
109 // In order to move the item, we must first make a copy of it.
110 // We always keep extra space at the end of the item data block
111 // for this purpose.
112 CopyToTemporary(currentIndex);
114 // If the element is before target location...
115 if (currentIndex < newIndex)
117 // Shift items between current and target locations down one
118 memmove(UnsafeItemPtr( currentIndex), UnsafeItemPtr( currentIndex+1),
119 (newIndex - currentIndex) * m_nItemSize);
123 // ...else the element is after target location...
125 // Shift items between target and current locations up one.
126 memmove(UnsafeItemPtr( newIndex+1), UnsafeItemPtr( newIndex),
127 (currentIndex - newIndex) * m_nItemSize);
131 // Copy element into new position
132 CopyFromTemporary(newIndex);
137 ///////////////////////////////////////
139 // Write the array to the stream
142 BOOL cDynArrayBase::ToStream(cOStore &) const
144 #if 0
145 int iElement = 0;
147 index_t numElems = Size();
149 if (!OStore.WriteHeader("DYNARRAY"))
150 return FALSE;
152 OStore.To(numElems);
154 for (index_t i = 0; i < numElems; i++)
156 if (!OStore.To(i))
157 return FALSE;
159 if (!ItemToStream(OStore, UnsafeItemPtr(i)))
160 return FALSE;
163 return OStore.WriteTrailer();
164 #else
165 return FALSE;
166 #endif
169 ///////////////////////////////////////
171 // Read the array from a stream
174 BOOL cDynArrayBase::FromStream(cIStore &)
176 #if 0
177 if (!IStore.ReadHeader("DYNARRAY"))
178 return FALSE;
180 // Get the number of elements
181 index_t numElems;
182 if (!IStore.From(numElems))
183 return FALSE;
185 SetSize(numElems);
187 for (index_t i = 0; i<numElems; i++)
189 index_t j;
190 if (!IStore.From(j))
191 return FALSE;
193 if (j != i)
194 return IStore.Fail();
196 // Stream in the node over the item
197 if (!ItemFromStream(IStore, UnsafeItemPtr(i)))
198 return FALSE;
201 return IStore.ReadTrailer();
202 #else
203 return FALSE;
204 #endif
208 ///////////////////////////////////////
210 // Read an item from the stream (default binary mode)
213 BOOL cDynArrayBase::ItemFromStream(cIStore &, tDynArrayItem *)
215 #if 0
216 // Copy item from stream, overwriting whatever was in the item before
217 return IStore.From((unsigned char *)pItem, GetElementSize());
218 #else
219 return FALSE;
220 #endif
224 ///////////////////////////////////////
226 // Write an item to the stream (default binary mode)
229 BOOL cDynArrayBase::ItemToStream(cOStore &, const tDynArrayItem *) const
231 #if 0
232 return OStore.To((const unsigned char *)pItem, GetElementSize());
233 #else
234 return FALSE;
235 #endif
239 ///////////////////////////////////////
241 // Swap the content of two arrays (all state and ownership
242 // of allocated memory). If information should only go one-way,
243 // empty one first.
246 void cDynArrayBase::SwapContents(cDynArrayBase &x)
249 BYTE * p;
250 p = x.m_pItems;
251 x.m_pItems = m_pItems;
252 m_pItems = p;
254 size_t sz;
255 sz = x.m_nItemSize;
256 x.m_nItemSize = m_nItemSize;
257 m_nItemSize = sz;
259 index_t ix;
260 ix = x.m_nItems;
261 x.m_nItems = m_nItems;
262 m_nItems = ix;
264 ix = x.m_nSlots;
265 x.m_nSlots = m_nSlots;
266 m_nSlots = ix;
270 ///////////////////////////////////////
272 // Find an element using a supplied comparison function. This routine uses
273 // a binary search algorithm so the array must be sorted.
276 index_t cDynArrayBase::BSearch(tDynArrayKey *pKey, tSearchFunc SearchFunc) const
278 if (!m_pItems)
279 return BAD_INDEX;
281 tDynArrayItem *pNewItem = bsearch(pKey, m_pItems, m_nItems, m_nItemSize, SearchFunc);
283 if (!pNewItem)
284 return BAD_INDEX;
286 return ((BYTE *)pNewItem - m_pItems) / m_nItemSize;
290 ///////////////////////////////////////
292 // Find an element using a supplied comparison function. This routine uses
293 // a straight linear search algorithm.
296 index_t cDynArrayBase::LSearch(tDynArrayKey *pKey, tSearchFunc SearchFunc) const
298 if (!m_pItems)
299 return BAD_INDEX;
301 BYTE * pNewItem;
302 #ifdef LSEARCH_IN_RTL
303 // @TBD: Is this part of our RTL yet?
304 pNewItem = (BYTE *) lsearch(pItem, m_pItems, m_nItems, m_nItemSize, SearchFunc);
305 #else
306 pNewItem = m_pItems;
308 for (index_t Remaining = m_nItems; Remaining; Remaining--)
310 if (SearchFunc(pKey, (tDynArrayItem *)pNewItem)==0)
311 break;
312 pNewItem += m_nItemSize;
315 if (!Remaining)
316 pNewItem = 0;
317 #endif
319 if (!pNewItem)
320 return BAD_INDEX;
322 return (pNewItem - m_pItems) / m_nItemSize;
326 ///////////////////////////////////////
328 // Sort the array of elements based on the supplied comparison function.
331 void cDynArrayBase::Sort(tSortFunc SortFunc)
333 if (!m_pItems)
334 return;
336 qsort(m_pItems, m_nItems, m_nItemSize, SortFunc);
339 ///////////////////////////////////////////////////////////////////////////////