]>
Commit | Line | Data |
---|---|---|
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 | ||
32 | OSDefineMetaClassAndStructors(OSArray, OSCollection) | |
33 | OSMetaClassDefineReservedUnused(OSArray, 0); | |
34 | OSMetaClassDefineReservedUnused(OSArray, 1); | |
35 | OSMetaClassDefineReservedUnused(OSArray, 2); | |
36 | OSMetaClassDefineReservedUnused(OSArray, 3); | |
37 | OSMetaClassDefineReservedUnused(OSArray, 4); | |
38 | OSMetaClassDefineReservedUnused(OSArray, 5); | |
39 | OSMetaClassDefineReservedUnused(OSArray, 6); | |
40 | OSMetaClassDefineReservedUnused(OSArray, 7); | |
41 | ||
42 | #if OSALLOCDEBUG | |
43 | extern "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 | ||
51 | bool 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 | ||
73 | bool 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 | ||
102 | bool 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 | ||
112 | OSArray *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 | ||
124 | OSArray *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 | ||
138 | OSArray *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 | ||
151 | void 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 | ||
164 | unsigned int OSArray::getCount() const { return count; } | |
165 | unsigned int OSArray::getCapacity() const { return capacity; } | |
166 | unsigned int OSArray::getCapacityIncrement() const { return capacityIncrement; } | |
167 | unsigned int OSArray::setCapacityIncrement(unsigned int increment) | |
168 | { | |
169 | capacityIncrement = (increment)? increment : 16; | |
170 | ||
171 | return capacityIncrement; | |
172 | } | |
173 | ||
174 | unsigned 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 | ||
203 | void 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 | ||
213 | bool OSArray::setObject(const OSMetaClassBase *anObject) | |
214 | { | |
215 | return setObject(count, anObject); | |
216 | } | |
217 | ||
218 | bool 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 | ||
242 | bool 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 | ||
265 | void OSArray:: | |
266 | replaceObject(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 | ||
281 | void 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 | ||
299 | bool 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 | ||
317 | bool 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 | ||
328 | OSObject *OSArray::getObject(unsigned int index) const | |
329 | { | |
330 | if (index >= count) | |
331 | return 0; | |
332 | else | |
333 | return (OSObject *) array[index]; | |
334 | } | |
335 | ||
336 | OSObject *OSArray::getLastObject() const | |
337 | { | |
338 | if (count == 0) | |
339 | return 0; | |
340 | else | |
341 | return (OSObject *) array[count - 1]; | |
342 | } | |
343 | ||
344 | unsigned 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 | ||
354 | unsigned int OSArray::iteratorSize() const | |
355 | { | |
356 | return sizeof(unsigned int); | |
357 | } | |
358 | ||
359 | bool OSArray::initIterator(void *inIterator) const | |
360 | { | |
361 | unsigned int *iteratorP = (unsigned int *) inIterator; | |
362 | ||
363 | *iteratorP = 0; | |
364 | return true; | |
365 | } | |
366 | ||
367 | bool 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 | ||
382 | bool 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 | } |