]> git.saurik.com Git - apple/xnu.git/blame - libkern/c++/OSArray.cpp
xnu-344.tar.gz
[apple/xnu.git] / libkern / c++ / OSArray.cpp
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/* IOArray.m created by rsulack on Fri 12-Sep-1997 */
23/* IOArray.cpp converted to C++ by gvdl on Fri 1998-10-30 */
24
25
26#include <libkern/c++/OSArray.h>
27#include <libkern/c++/OSSerialize.h>
28#include <libkern/c++/OSLib.h>
29
30#define super OSCollection
31
32OSDefineMetaClassAndStructors(OSArray, OSCollection)
33OSMetaClassDefineReservedUnused(OSArray, 0);
34OSMetaClassDefineReservedUnused(OSArray, 1);
35OSMetaClassDefineReservedUnused(OSArray, 2);
36OSMetaClassDefineReservedUnused(OSArray, 3);
37OSMetaClassDefineReservedUnused(OSArray, 4);
38OSMetaClassDefineReservedUnused(OSArray, 5);
39OSMetaClassDefineReservedUnused(OSArray, 6);
40OSMetaClassDefineReservedUnused(OSArray, 7);
41
42#if OSALLOCDEBUG
43extern "C" {
44 extern int debug_container_malloc_size;
45};
46#define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0)
47#else
48#define ACCUMSIZE(s)
49#endif
50
51bool OSArray::initWithCapacity(unsigned int inCapacity)
52{
53 int size;
54
55 if (!super::init())
56 return false;
57
58 size = sizeof(const OSMetaClassBase *) * inCapacity;
59 array = (const OSMetaClassBase **) kalloc(size);
60 if (!array)
61 return false;
62
63 count = 0;
64 capacity = inCapacity;
65 capacityIncrement = (inCapacity)? inCapacity : 16;
66
67 bzero(array, size);
68 ACCUMSIZE(size);
69
70 return this;
71}
72
73bool OSArray::initWithObjects(const OSObject *objects[],
74 unsigned int theCount,
75 unsigned int theCapacity = 0)
76{
77 unsigned int capacity;
78
79 if (!theCapacity)
80 capacity = theCount;
81 else if (theCount > theCapacity)
82 return false;
83 else
84 capacity = theCapacity;
85
86 if (!objects || !initWithCapacity(capacity))
87 return false;
88
89 for ( unsigned int i = 0; i < theCount; i++ ) {
90 const OSMetaClassBase *newObject = *objects++;
91
92 if (!newObject)
93 return false;
94
95 array[count++] = newObject;
9bccf70c 96 newObject->taggedRetain(OSTypeID(OSCollection));
1c79356b
A
97 }
98
99 return true;
100}
101
102bool OSArray::initWithArray(const OSArray *anArray,
103 unsigned int theCapacity = 0)
104{
105 if ( !anArray )
106 return false;
107
108 return initWithObjects((const OSObject **) anArray->array,
109 anArray->count, theCapacity);
110}
111
112OSArray *OSArray::withCapacity(unsigned int capacity)
113{
114 OSArray *me = new OSArray;
115
116 if (me && !me->initWithCapacity(capacity)) {
117 me->free();
118 return 0;
119 }
120
121 return me;
122}
123
124OSArray *OSArray::withObjects(const OSObject *objects[],
125 unsigned int count,
126 unsigned int capacity = 0)
127{
128 OSArray *me = new OSArray;
129
130 if (me && !me->initWithObjects(objects, count, capacity)) {
131 me->free();
132 return 0;
133 }
134
135 return me;
136}
137
138OSArray *OSArray::withArray(const OSArray *array,
139 unsigned int capacity = 0)
140{
141 OSArray *me = new OSArray;
142
143 if (me && !me->initWithArray(array, capacity)) {
144 me->free();
145 return 0;
146 }
147
148 return me;
149}
150
151void OSArray::free()
152{
153 flushCollection();
154
155 if (array) {
156 kfree((vm_offset_t)array, sizeof(const OSMetaClassBase *) * capacity);
157 ACCUMSIZE( -(sizeof(const OSMetaClassBase *) * capacity) );
158 }
159
160 super::free();
161}
162
163
164unsigned int OSArray::getCount() const { return count; }
165unsigned int OSArray::getCapacity() const { return capacity; }
166unsigned int OSArray::getCapacityIncrement() const { return capacityIncrement; }
167unsigned int OSArray::setCapacityIncrement(unsigned int increment)
168{
169 capacityIncrement = (increment)? increment : 16;
170
171 return capacityIncrement;
172}
173
174unsigned int OSArray::ensureCapacity(unsigned int newCapacity)
175{
176 const OSMetaClassBase **newArray;
177 int oldSize, newSize;
178
179 if (newCapacity <= capacity)
180 return capacity;
181
182 // round up
183 newCapacity = (((newCapacity - 1) / capacityIncrement) + 1)
184 * capacityIncrement;
185 newSize = sizeof(const OSMetaClassBase *) * newCapacity;
186
187 newArray = (const OSMetaClassBase **) kalloc(newSize);
188 if (newArray) {
189 oldSize = sizeof(const OSMetaClassBase *) * capacity;
190
191 ACCUMSIZE(newSize - oldSize);
192
193 bcopy(array, newArray, oldSize);
194 bzero(&newArray[capacity], newSize - oldSize);
195 kfree((vm_offset_t)array, oldSize);
196 array = newArray;
197 capacity = newCapacity;
198 }
199
200 return capacity;
201}
202
203void OSArray::flushCollection()
204{
205 unsigned int i;
206
207 haveUpdated();
208 for (i = 0; i < count; i++)
9bccf70c 209 array[i]->taggedRelease(OSTypeID(OSCollection));
1c79356b
A
210 count = 0;
211}
212
213bool OSArray::setObject(const OSMetaClassBase *anObject)
214{
215 return setObject(count, anObject);
216}
217
218bool OSArray::setObject(unsigned int index, const OSMetaClassBase *anObject)
219{
220 unsigned int i;
221 unsigned int newCount = count + 1;
222
223 if ((index > count) || !anObject)
224 return false;
225
226 // do we need more space?
227 if (newCount > capacity && newCount > ensureCapacity(newCount))
228 return false;
229
230 haveUpdated();
231 if (index != count) {
232 for (i = count; i > index; i--)
233 array[i] = array[i-1];
234 }
235 array[index] = anObject;
9bccf70c 236 anObject->taggedRetain(OSTypeID(OSCollection));
1c79356b
A
237 count++;
238
239 return true;
240}
241
242bool OSArray::merge(const OSArray * otherArray)
243{
244 unsigned int otherCount = otherArray->getCount();
245 unsigned int newCount = count + otherCount;
246
247 if (!otherCount)
248 return true;
249
250 // do we need more space?
251 if (newCount > capacity && newCount > ensureCapacity(newCount))
252 return false;
253
254 haveUpdated();
255 for (unsigned int i = 0; i < otherCount; i++) {
256 const OSMetaClassBase *newObject = otherArray->getObject(i);
257
258 array[count++] = newObject;
9bccf70c 259 newObject->taggedRetain(OSTypeID(OSCollection));
1c79356b
A
260 }
261
262 return true;
263}
264
265void OSArray::
266replaceObject(unsigned int index, const OSMetaClassBase *anObject)
267{
268 const OSMetaClassBase *oldObject;
269
270 if ((index >= count) || !anObject)
271 return;
272
273 haveUpdated();
274 oldObject = array[index];
275 array[index] = anObject;
9bccf70c 276 anObject->taggedRetain(OSTypeID(OSCollection));
1c79356b 277
9bccf70c 278 oldObject->taggedRelease(OSTypeID(OSCollection));
1c79356b
A
279}
280
281void OSArray::removeObject(unsigned int index)
282{
283 unsigned int i;
284 const OSMetaClassBase *oldObject;
285
286 if (index >= count)
287 return;
288
289 haveUpdated();
290 oldObject = array[index];
291
292 count--;
293 for (i = index; i < count; i++)
294 array[i] = array[i+1];
295
9bccf70c 296 oldObject->taggedRelease(OSTypeID(OSCollection));
1c79356b
A
297}
298
299bool OSArray::isEqualTo(const OSArray *anArray) const
300{
301 unsigned int i;
302
303 if ( this == anArray )
304 return true;
305
306 if ( count != anArray->getCount() )
307 return false;
308
309 for ( i = 0; i < count; i++ ) {
310 if ( !array[i]->isEqualTo(anArray->getObject(i)) )
311 return false;
312 }
313
314 return true;
315}
316
317bool OSArray::isEqualTo(const OSMetaClassBase *anObject) const
318{
319 OSArray *otherArray;
320
321 otherArray = OSDynamicCast(OSArray, anObject);
322 if ( otherArray )
323 return isEqualTo(otherArray);
324 else
325 return false;
326}
327
328OSObject *OSArray::getObject(unsigned int index) const
329{
330 if (index >= count)
331 return 0;
332 else
333 return (OSObject *) array[index];
334}
335
336OSObject *OSArray::getLastObject() const
337{
338 if (count == 0)
339 return 0;
340 else
341 return (OSObject *) array[count - 1];
342}
343
344unsigned int OSArray::getNextIndexOfObject(const OSMetaClassBase * anObject,
345 unsigned int index) const
346{
347 while ((index < count) && (array[index] != anObject))
348 index++;
349 if (index >= count)
350 index = (unsigned int)-1;
351 return index;
352}
353
354unsigned int OSArray::iteratorSize() const
355{
356 return sizeof(unsigned int);
357}
358
359bool OSArray::initIterator(void *inIterator) const
360{
361 unsigned int *iteratorP = (unsigned int *) inIterator;
362
363 *iteratorP = 0;
364 return true;
365}
366
367bool OSArray::getNextObjectForIterator(void *inIterator, OSObject **ret) const
368{
369 unsigned int *iteratorP = (unsigned int *) inIterator;
370 unsigned int index = (*iteratorP)++;
371
372 if (index < count) {
373 *ret = (OSObject *) array[index];
374 return true;
375 }
376 else {
377 *ret = 0;
378 return false;
379 }
380}
381
382bool OSArray::serialize(OSSerialize *s) const
383{
384 if (s->previouslySerialized(this)) return true;
385
386 if (!s->addXMLStartTag(this, "array")) return false;
387
388 for (unsigned i = 0; i < count; i++) {
389 if (!array[i]->serialize(s)) return false;
390 }
391
392 return s->addXMLEndTag("array");
393}