|
|
1.1 root 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:
34:
35: #ifdef DEBUG
36: extern "C" {
37: extern int debug_container_malloc_size;
38: };
39: #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0)
40: #else
41: #define ACCUMSIZE(s)
42: #endif
43:
44: bool OSArray::initWithCapacity(unsigned int inCapacity)
45: {
46: int size;
47:
48: if (!super::init())
49: return false;
50:
51: size = sizeof(OSObject *) * inCapacity;
52: array = (OSObject **) kalloc(size);
53: if (!array)
54: return false;
55:
56: count = 0;
57: capacity = inCapacity;
58: capacityIncrement = capacity;
59:
60: bzero(array, size);
61: ACCUMSIZE(size);
62:
63: return this;
64: }
65:
66: bool OSArray::initWithObjects(OSObject *objects[],
67: unsigned int theCount,
68: unsigned int theCapacity = 0)
69: {
70: unsigned int capacity = theCount;
71:
72: if ( theCapacity ) {
73: if ( theCount > theCapacity )
74: return false;
75:
76: capacity = theCapacity;
77: }
78:
79: if (!objects || !initWithCapacity(capacity))
80: return false;
81:
82: for ( unsigned int i = 0; i < theCount; i++ ) {
83: OSObject *newObject = *objects++;
84:
85: if (!newObject)
86: return false;
87:
88: array[count++] = newObject;
89: newObject->retain();
90: }
91:
92: return true;
93: }
94:
95: bool OSArray::initWithArray(const OSArray *anArray,
96: unsigned int theCapacity = 0)
97: {
98: if ( !anArray )
99: return false;
100:
101: return initWithObjects(anArray->array, anArray->count,
102: theCapacity);
103: }
104:
105: OSArray *OSArray::withCapacity(unsigned int capacity)
106: {
107: OSArray *me = new OSArray;
108:
109: if (me && !me->initWithCapacity(capacity)) {
110: me->free();
111: return 0;
112: }
113:
114: return me;
115: }
116:
117: OSArray *OSArray::withObjects(OSObject *objects[],
118: unsigned int count,
119: unsigned int capacity = 0)
120: {
121: OSArray *me = new OSArray;
122:
123: if (me && !me->initWithObjects(objects, count, capacity)) {
124: me->free();
125: return 0;
126: }
127:
128: return me;
129: }
130:
131: OSArray *OSArray::withArray(const OSArray *array,
132: unsigned int capacity = 0)
133: {
134: OSArray *me = new OSArray;
135:
136: if (me && !me->initWithArray(array, capacity)) {
137: me->free();
138: return 0;
139: }
140:
141: return me;
142: }
143:
144: void OSArray::free()
145: {
146: flushCollection();
147:
148: if (array) {
149: kfree((vm_offset_t)array, sizeof(OSObject *) * capacity);
150: ACCUMSIZE( -(sizeof(OSObject *) * capacity) );
151: }
152:
153: super::free();
154: }
155:
156:
157: unsigned int OSArray::getCount() const { return count; }
158: unsigned int OSArray::getCapacity() const { return capacity; }
159: unsigned int OSArray::getCapacityIncrement() const { return capacityIncrement; }
160: unsigned int OSArray::setCapacityIncrement(unsigned int increment)
161: {
162: return capacityIncrement = increment;
163: }
164:
165: unsigned int OSArray::ensureCapacity(unsigned int newCapacity)
166: {
167: OSObject **newArray;
168: int oldSize, newSize;
169:
170: if (!capacityIncrement || newCapacity <= capacity)
171: return capacity;
172:
173: // round up
174: newCapacity = (((newCapacity - 1) / capacityIncrement) + 1)
175: * capacityIncrement;
176: newSize = sizeof(OSObject *) * newCapacity;
177:
178: newArray = (OSObject **) kalloc(newSize);
179: if (newArray) {
180: oldSize = sizeof(OSObject *) * capacity;
181:
182: ACCUMSIZE(newSize - oldSize);
183:
184: bcopy(array, newArray, oldSize);
185: bzero(&newArray[capacity], newSize - oldSize);
186: kfree((vm_offset_t)array, oldSize);
187: array = newArray;
188: capacity = newCapacity;
189: }
190:
191: return capacity;
192: }
193:
194: void OSArray::flushCollection()
195: {
196: unsigned int i;
197:
198: haveUpdated();
199: for (i = 0; i < count; i++)
200: array[i]->release();
201: count = 0;
202: }
203:
204: bool OSArray::setObject(OSObject *anObject)
205: {
206: return setObject(count, anObject);
207: }
208:
209: bool OSArray::setObject(unsigned int index, OSObject *anObject)
210: {
211: unsigned int i;
212: unsigned int newCount = count + 1;
213:
214: if ((index > count) || !anObject)
215: return false;
216:
217: // do we need more space?
218: if (newCount > capacity && newCount > ensureCapacity(newCount))
219: return false;
220:
221: haveUpdated();
222: if (index != count) {
223: for (i = count; i > index; i--)
224: array[i] = array[i-1];
225: }
226: array[index] = anObject;
227: anObject->retain();
228: count++;
229:
230: return true;
231: }
232:
233: bool OSArray::merge(const OSArray * otherArray)
234: {
235: unsigned int otherCount = otherArray->getCount();
236: unsigned int newCount = count + otherCount;
237:
238: if (!otherCount)
239: return true;
240:
241: // do we need more space?
242: if (newCount > capacity && newCount > ensureCapacity(newCount))
243: return false;
244:
245: haveUpdated();
246: for (unsigned int i = 0; i < otherCount; i++) {
247: OSObject *newObject = otherArray->getObject(i);
248:
249: array[count++] = newObject;
250: newObject->retain();
251: }
252:
253: return true;
254: }
255:
256: void OSArray::replaceObject(unsigned int index, OSObject *anObject)
257:
258: {
259: OSObject *oldObject;
260:
261: if ((index >= count) || !anObject)
262: return;
263:
264: haveUpdated();
265: oldObject = array[index];
266: array[index] = anObject;
267: anObject->retain();
268:
269: oldObject->release();
270: }
271:
272: void OSArray::removeObject(unsigned int index)
273: {
274: unsigned int i;
275: OSObject *oldObject;
276:
277: if (index >= count)
278: return;
279:
280: haveUpdated();
281: oldObject = array[index];
282:
283: count--;
284: for (i = index; i < count; i++)
285: array[i] = array[i+1];
286:
287: oldObject->release();
288: }
289:
290: bool OSArray::isEqualTo(OSArray *anArray) const
291: {
292: unsigned int i;
293:
294: if ( this == anArray )
295: return true;
296:
297: if ( count != anArray->getCount() )
298: return false;
299:
300: for ( i = 0; i < count; i++ ) {
301: if ( !array[i]->isEqualTo(anArray->getObject(i)) )
302: return false;
303: }
304:
305: return true;
306: }
307:
308: bool OSArray::isEqualTo(const OSObject *anObject) const
309: {
310: OSArray *otherArray;
311:
312: otherArray = OSDynamicCast(OSArray, (OSObject *)anObject);
313: if ( otherArray )
314: return isEqualTo(otherArray);
315: else
316: return false;
317: }
318:
319: OSObject *OSArray::getObject(unsigned int index) const
320: {
321: if (index >= count)
322: return 0;
323: else
324: return array[index];
325: }
326:
327: OSObject *OSArray::lastObject() const
328: {
329: if (count == 0)
330: return 0;
331: else
332: return array[count - 1];
333: }
334:
335: unsigned int OSArray::getNextIndexOfObject(OSObject * anObject,
336: unsigned int index) const
337: {
338: while ((index < count) && (array[index] != anObject))
339: {}
340: if (index >= count)
341: index = (unsigned int)-1;
342: return index;
343: }
344:
345: unsigned int OSArray::iteratorSize() const
346: {
347: return sizeof(unsigned int);
348: }
349:
350: bool OSArray::initIterator(void *inIterator) const
351: {
352: unsigned int *iteratorP = (unsigned int *) inIterator;
353:
354: *iteratorP = 0;
355: return true;
356: }
357:
358: bool OSArray::getNextObjectForIterator(void *inIterator, OSObject **ret) const
359: {
360: unsigned int *iteratorP = (unsigned int *) inIterator;
361: unsigned int index = (*iteratorP)++;
362:
363: if (index < count) {
364: *ret = array[index];
365: return true;
366: }
367: else {
368: *ret = 0;
369: return false;
370: }
371: }
372:
373: bool OSArray::serialize(OSSerialize *s) const
374: {
375: if (s->previouslySerialized(this)) return true;
376:
377: if (!s->addXMLStartTag(this, "array")) return false;
378:
379: for (unsigned i = 0; i < count; i++) {
380: if (!array[i]->serialize(s)) return false;
381: }
382:
383: return s->addXMLEndTag("array");
384: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.