|
|
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: /* OSDictionary.m created by rsulack on Fri 12-Sep-1997 */
23: /* OSDictionary.cpp converted to C++ by gvdl on Fri 1998-10-30 */
24: /* OSDictionary.cpp rewritten by gvdl on Fri 1998-10-30 */
25:
26:
27: #include <libkern/c++/OSDictionary.h>
28: #include <libkern/c++/OSArray.h>
29: #include <libkern/c++/OSSymbol.h>
30: #include <libkern/c++/OSSerialize.h>
31: #include <libkern/c++/OSLib.h>
32: #include <libkern/c++/OSCollectionIterator.h>
33:
34: #define super OSCollection
35:
36: OSDefineMetaClassAndStructors(OSDictionary, OSCollection)
37:
38: #ifdef DEBUG
39: extern "C" {
40: extern int debug_container_malloc_size;
41: };
42: #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0)
43: #else
44: #define ACCUMSIZE(s)
45: #endif
46:
47: bool OSDictionary::initWithCapacity(unsigned int inCapacity)
48: {
49: if (!super::init())
50: return false;
51:
52: int size = inCapacity * sizeof(dictEntry);
53:
54: dictionary = (dictEntry *) kalloc(size);
55: if (!dictionary)
56: return false;
57:
58: bzero(dictionary, size);
59: ACCUMSIZE(size);
60:
61: count = 0;
62: capacity = capacityIncrement = inCapacity;
63:
64: return true;
65: }
66:
67: bool OSDictionary::initWithObjects(OSObject *objects[],
68: const OSSymbol *keys[],
69: unsigned int theCount,
70: unsigned int theCapacity = 0)
71: {
72: unsigned int capacity = theCount;
73:
74: if (!objects || !keys)
75: return false;
76:
77: if ( theCapacity ) {
78: if (theCount > theCapacity)
79: return false;
80:
81: capacity = theCapacity;
82: }
83:
84: if (!initWithCapacity(capacity))
85: return false;
86:
87: for (unsigned int i = 0; i < theCount; i++) {
88: OSObject *newObject = *objects++;
89:
90: if (!newObject || !keys[i] || !setObject(keys[i], newObject))
91: return false;
92: }
93:
94: return true;
95: }
96:
97: bool OSDictionary::initWithObjects(OSObject *objects[],
98: OSString *keys[],
99: unsigned int theCount,
100: unsigned int theCapacity = 0)
101: {
102: unsigned int capacity = theCount;
103:
104: if (!objects || !keys)
105: return false;
106:
107: if ( theCapacity ) {
108: if (theCount > theCapacity)
109: return false;
110:
111: capacity = theCapacity;
112: }
113:
114: if (!initWithCapacity(capacity))
115: return false;
116:
117: for (unsigned int i = 0; i < theCount; i++) {
118: const OSSymbol *key = OSSymbol::withString(*keys++);
119: OSObject *newObject = *objects++;
120:
121: if (!key)
122: return false;
123:
124: if (!newObject || !setObject(key, newObject)) {
125: key->release();
126: return false;
127: }
128:
129: key->release();
130: }
131:
132: return true;
133: }
134:
135: bool OSDictionary::initWithDictionary(const OSDictionary *dict,
136: unsigned int theCapacity = 0)
137: {
138: unsigned int capacity;
139:
140: if ( !dict )
141: return false;
142:
143: capacity = dict->count;
144:
145: if ( theCapacity ) {
146: if ( dict->count > theCapacity )
147: return false;
148:
149: capacity = theCapacity;
150: }
151:
152: if (!initWithCapacity(capacity))
153: return false;
154:
155: count = dict->count;
156: bcopy(dict->dictionary, dictionary, count * sizeof(dictEntry));
157: for (unsigned int i = 0; i < count; i++) {
158: dictionary[i].key->retain();
159: dictionary[i].value->retain();
160: }
161:
162: return true;
163: }
164:
165: OSDictionary *OSDictionary::withCapacity(unsigned int capacity)
166: {
167: OSDictionary *me = new OSDictionary;
168:
169: if (me && !me->initWithCapacity(capacity)) {
170: me->free();
171: return 0;
172: }
173:
174: return me;
175: }
176:
177: OSDictionary *OSDictionary::withObjects(OSObject *objects[],
178: const OSSymbol *keys[],
179: unsigned int count,
180: unsigned int capacity = 0)
181: {
182: OSDictionary *me = new OSDictionary;
183:
184: if (me && !me->initWithObjects(objects, keys, count, capacity)) {
185: me->free();
186: return 0;
187: }
188:
189: return me;
190: }
191:
192: OSDictionary *OSDictionary::withObjects(OSObject *objects[],
193: OSString *keys[],
194: unsigned int count,
195: unsigned int capacity = 0)
196: {
197: OSDictionary *me = new OSDictionary;
198:
199: if (me && !me->initWithObjects(objects, keys, count, capacity)) {
200: me->free();
201: return 0;
202: }
203:
204: return me;
205: }
206:
207: OSDictionary *OSDictionary::withDictionary(const OSDictionary *dict,
208: unsigned int capacity = 0)
209: {
210: OSDictionary *me = new OSDictionary;
211:
212: if (me && !me->initWithDictionary(dict, capacity)) {
213: me->free();
214: return 0;
215: }
216:
217: return me;
218: }
219:
220: void OSDictionary::free()
221: {
222: flushCollection();
223: if (dictionary) {
224: kfree((vm_offset_t)dictionary, capacity * sizeof(dictEntry));
225: ACCUMSIZE( -(capacity * sizeof(dictEntry)) );
226: }
227:
228: super::free();
229: }
230:
231: unsigned int OSDictionary::getCount() const { return count; }
232: unsigned int OSDictionary::getCapacity() const { return capacity; }
233:
234: unsigned int OSDictionary::getCapacityIncrement() const
235: {
236: return capacityIncrement;
237: }
238:
239: unsigned int OSDictionary::setCapacityIncrement(unsigned int increment)
240: {
241: return capacityIncrement = increment;
242: }
243:
244: unsigned int OSDictionary::ensureCapacity(unsigned int newCapacity)
245: {
246: dictEntry *newDict;
247: int oldSize, newSize;
248:
249: if (!capacityIncrement)
250: return capacity;
251:
252: newCapacity = (((newCapacity - 1) / capacityIncrement) + 1)
253: * capacityIncrement;
254:
255: if (newCapacity <= capacity)
256: return capacity;
257:
258: // round up
259: newSize = sizeof(dictEntry) * newCapacity;
260:
261: newDict = (dictEntry *) kalloc(newSize);
262: if (newDict) {
263: oldSize = sizeof(dictEntry) * capacity;
264:
265: bcopy(dictionary, newDict, oldSize);
266: bzero(&newDict[capacity], newSize - oldSize);
267:
268: ACCUMSIZE(newSize - oldSize);
269: kfree((vm_offset_t)dictionary, oldSize);
270:
271: dictionary = newDict;
272: capacity = newCapacity;
273: }
274:
275: return capacity;
276: }
277:
278: void OSDictionary::flushCollection()
279: {
280: haveUpdated();
281:
282: for (unsigned int i = 0; i < count; i++) {
283: dictionary[i].key->release();
284: dictionary[i].value->release();
285: }
286: count = 0;
287: }
288:
289: bool OSDictionary::setObject(const OSSymbol *aKey, OSObject *anObject)
290: {
291: if (!anObject || !aKey)
292: return false;
293:
294: // if the key exists, replace the object
295: for (unsigned int i = 0; i < count; i++) {
296: if (aKey == dictionary[i].key) {
297: OSObject *oldObject = dictionary[i].value;
298:
299: anObject->retain();
300: dictionary[i].value = anObject;
301:
302: haveUpdated();
303:
304: oldObject->release();
305: return true;
306: }
307: }
308:
309: // add new key, possibly extending our capacity
310: if (count >= capacity && count >= ensureCapacity(count+1))
311: return 0;
312:
313: aKey->retain();
314: anObject->retain();
315: dictionary[count].key = aKey;
316: dictionary[count].value = anObject;
317: count++;
318:
319: haveUpdated();
320:
321: return true;
322: }
323:
324: void OSDictionary::removeObject(const OSSymbol *aKey)
325: {
326: if (!aKey)
327: return;
328:
329: // if the key exists, remove the object
330: for (unsigned int i = 0; i < count; i++)
331: if (aKey == dictionary[i].key) {
332: dictEntry oldEntry = dictionary[i];
333:
334: haveUpdated();
335:
336: count--;
337: for (; i < count; i++)
338: dictionary[i] = dictionary[i+1];
339:
340: oldEntry.key->release();
341: oldEntry.value->release();
342: return;
343: }
344: }
345:
346:
347: // Returns true on success, false on an error condition.
348: bool OSDictionary::merge(const OSDictionary *aDictionary)
349: {
350: const OSSymbol * sym;
351: OSCollectionIterator * iter;
352:
353: if ( !OSDynamicCast(OSDictionary, (OSDictionary *) aDictionary) )
354: return false;
355:
356: iter = OSCollectionIterator::withCollection((OSDictionary *)aDictionary);
357: if ( !iter )
358: return false;
359:
360: while ( (sym = (const OSSymbol *)iter->getNextObject()) ) {
361: OSObject * obj;
362:
363: obj = aDictionary->getObject(sym);
364: if ( !setObject(sym, obj) ) {
365: iter->release();
366: return false;
367: }
368: }
369: iter->release();
370:
371: return true;
372: }
373:
374: OSObject *OSDictionary::getObject(const OSSymbol *aKey) const
375: {
376: if (!aKey)
377: return 0;
378:
379: // if the key exists, remove the object
380: for (unsigned int i = 0; i < count; i++)
381: if (aKey == dictionary[i].key)
382: return dictionary[i].value;
383:
384: return 0;
385: }
386:
387: // Wrapper macros
388: #define OBJECT_WRAP_1(cmd, k) \
389: { \
390: const OSSymbol *tmpKey = k; \
391: OSObject *retObj = cmd(tmpKey); \
392: \
393: tmpKey->release(); \
394: return retObj; \
395: }
396:
397: #define OBJECT_WRAP_2(cmd, k, o) \
398: { \
399: const OSSymbol *tmpKey = k; \
400: bool ret = cmd(tmpKey, o); \
401: \
402: tmpKey->release(); \
403: return ret; \
404: }
405:
406: #define OBJECT_WRAP_3(cmd, k) \
407: { \
408: const OSSymbol *tmpKey = k; \
409: cmd(tmpKey); \
410: tmpKey->release(); \
411: }
412:
413:
414: bool OSDictionary::setObject(const OSString *aKey, OSObject *anObject)
415: OBJECT_WRAP_2(setObject, OSSymbol::withString(aKey), anObject)
416: bool OSDictionary::setObject(const char *aKey, OSObject *anObject)
417: OBJECT_WRAP_2(setObject, OSSymbol::withCString(aKey), anObject)
418:
419: OSObject *OSDictionary::getObject(const OSString *aKey) const
420: OBJECT_WRAP_1(getObject, OSSymbol::withString(aKey))
421: OSObject *OSDictionary::getObject(const char *aKey) const
422: OBJECT_WRAP_1(getObject, OSSymbol::withCString(aKey))
423:
424: void OSDictionary::removeObject(const OSString *aKey)
425: OBJECT_WRAP_3(removeObject, OSSymbol::withString(aKey))
426: void OSDictionary::removeObject(const char *aKey)
427: OBJECT_WRAP_3(removeObject, OSSymbol::withCString(aKey))
428:
429: bool
430: OSDictionary::isEqualTo(OSDictionary *aDictionary, OSCollection *keys) const
431: {
432: OSCollectionIterator * iter;
433: unsigned int keysCount;
434: OSObject * obj1;
435: OSObject * obj2;
436: OSString * aKey;
437: bool ret;
438:
439: if ( this == aDictionary )
440: return true;
441:
442: keysCount = keys->getCount();
443: if ( (count < keysCount) || (aDictionary->getCount() < keysCount) )
444: return false;
445:
446: iter = OSCollectionIterator::withCollection(keys);
447: if ( !iter )
448: return false;
449:
450: ret = true;
451: while ( (aKey = OSDynamicCast(OSString, iter->getNextObject())) ) {
452: obj1 = getObject(aKey);
453: obj2 = aDictionary->getObject(aKey);
454: if ( !obj1 || !obj2 ) {
455: ret = false;
456: break;
457: }
458:
459: if ( !obj1->isEqualTo(obj2) ) {
460: ret = false;
461: break;
462: }
463: }
464: iter->release();
465:
466: return ret;
467: }
468:
469: bool OSDictionary::isEqualTo(OSDictionary *aDictionary) const
470: {
471: unsigned int i;
472: OSObject * obj;
473:
474: if ( this == aDictionary )
475: return true;
476:
477: if ( count != aDictionary->getCount() )
478: return false;
479:
480: for ( i = 0; i < count; i++ ) {
481: obj = aDictionary->getObject(dictionary[i].key);
482: if ( !obj )
483: return false;
484:
485: if ( !dictionary[i].value->isEqualTo(obj) )
486: return false;
487: }
488:
489: return true;
490: }
491:
492: bool OSDictionary::isEqualTo(const OSObject *anObject) const
493: {
494: OSDictionary *dict;
495:
496: dict = OSDynamicCast(OSDictionary, (OSObject *)anObject);
497: if ( dict )
498: return isEqualTo(dict);
499: else
500: return false;
501: }
502:
503: unsigned int OSDictionary::iteratorSize() const
504: {
505: return sizeof(unsigned int);
506: }
507:
508: bool OSDictionary::initIterator(void *inIterator) const
509: {
510: unsigned int *iteratorP = (unsigned int *) inIterator;
511:
512: *iteratorP = 0;
513: return true;
514: }
515:
516: bool OSDictionary::getNextObjectForIterator(void *inIterator, OSObject **ret) const
517: {
518: unsigned int *iteratorP = (unsigned int *) inIterator;
519: unsigned int index = (*iteratorP)++;
520:
521: if (index < count)
522: *ret = (OSObject *) dictionary[index].key;
523: else
524: *ret = 0;
525:
526: return (*ret != 0);
527: }
528:
529: bool OSDictionary::serialize(OSSerialize *s) const
530: {
531: if (s->previouslySerialized(this)) return true;
532:
533: if (!s->addXMLStartTag(this, "dict")) return false;
534:
535: for (unsigned i = 0; i < count; i++) {
536: const OSSymbol *key = dictionary[i].key;
537:
538: // due the nature of the XML syntax, this must be a symbol
539: if (!key->metaCast("OSSymbol")) {
540: return false;
541: }
542: if (!s->addString("<key>")) return false;
543: const char *c = key->getCStringNoCopy();
544: while (*c) {
545: if (*c == '<') {
546: if (!s->addString("<")) return false;
547: } else if (*c == '>') {
548: if (!s->addString(">")) return false;
549: } else if (*c == '&') {
550: if (!s->addString("&")) return false;
551: } else {
552: if (!s->addChar(*c)) return false;
553: }
554: c++;
555: }
556: if (!s->addXMLEndTag("key")) return false;
557:
558: if (!dictionary[i].value->serialize(s)) return false;
559: }
560:
561: return s->addXMLEndTag("dict");
562: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.