1 ///////////////////////////////////////////////////////////////////////////////
2 // $Source: x:/prj/tech/libsrc/cpptools/RCS/dynarray.cpp $
4 // $Date: 1998/05/23 07:08:04 $
14 // Must be last header
19 //include "storintr.h"
21 ///////////////////////////////////////////////////////////////////////////////
23 // CLASS: cDynArrayBase
27 char BASED_CODE
cDynArrayBase::gm_pszOutOfRange
[] = "Index out of range";
30 ///////////////////////////////////////
32 // Assignment operator
35 cDynArrayBase
& cDynArrayBase::operator=(const cDynArrayBase
&Array
)
37 // Blow the current array away
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
);
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
)
68 // Note: Allow for scratch block at the end
70 newP
= realloc(m_pItems
, (evenSlots
+1) * m_nItemSize
);
72 newP
= malloc((evenSlots
+1) * m_nItemSize
);
74 AssertMsg(newP
, "Dynamic array resize failed");
79 m_pItems
= (BYTE
*) newP
;
94 ///////////////////////////////////////
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
)
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
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
147 index_t numElems
= Size();
149 if (!OStore
.WriteHeader("DYNARRAY"))
154 for (index_t i
= 0; i
< numElems
; i
++)
159 if (!ItemToStream(OStore
, UnsafeItemPtr(i
)))
163 return OStore
.WriteTrailer();
169 ///////////////////////////////////////
171 // Read the array from a stream
174 BOOL
cDynArrayBase::FromStream(cIStore
&)
177 if (!IStore
.ReadHeader("DYNARRAY"))
180 // Get the number of elements
182 if (!IStore
.From(numElems
))
187 for (index_t i
= 0; i
<numElems
; i
++)
194 return IStore
.Fail();
196 // Stream in the node over the item
197 if (!ItemFromStream(IStore
, UnsafeItemPtr(i
)))
201 return IStore
.ReadTrailer();
208 ///////////////////////////////////////
210 // Read an item from the stream (default binary mode)
213 BOOL
cDynArrayBase::ItemFromStream(cIStore
&, tDynArrayItem
*)
216 // Copy item from stream, overwriting whatever was in the item before
217 return IStore
.From((unsigned char *)pItem
, GetElementSize());
224 ///////////////////////////////////////
226 // Write an item to the stream (default binary mode)
229 BOOL
cDynArrayBase::ItemToStream(cOStore
&, const tDynArrayItem
*) const
232 return OStore
.To((const unsigned char *)pItem
, GetElementSize());
239 ///////////////////////////////////////
241 // Swap the content of two arrays (all state and ownership
242 // of allocated memory). If information should only go one-way,
246 void cDynArrayBase::SwapContents(cDynArrayBase
&x
)
251 x
.m_pItems
= m_pItems
;
256 x
.m_nItemSize
= m_nItemSize
;
261 x
.m_nItems
= m_nItems
;
265 x
.m_nSlots
= m_nSlots
;
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
281 tDynArrayItem
*pNewItem
= bsearch(pKey
, m_pItems
, m_nItems
, m_nItemSize
, SearchFunc
);
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
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
);
308 for (index_t Remaining
= m_nItems
; Remaining
; Remaining
--)
310 if (SearchFunc(pKey
, (tDynArrayItem
*)pNewItem
)==0)
312 pNewItem
+= m_nItemSize
;
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
)
336 qsort(m_pItems
, m_nItems
, m_nItemSize
, SortFunc
);
339 ///////////////////////////////////////////////////////////////////////////////