source: trunk/Cocoa/Pester/Source/MoreSecurity/MoreCFQ.c@ 118

Last change on this file since 118 was 118, checked in by Nicholas Riley, 21 years ago

Broken, to-be-removed authorization implementation

File size: 22.0 KB
RevLine 
[118]1/*
2 File: MoreCFQ.c
3
4 Contains: Core Foundation utility Routines.
5
6 Written by: Quinn
7
8 Copyright: Copyright (c) 2001 by Apple Computer, Inc., All Rights Reserved.
9
10 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
11 ("Apple") in consideration of your agreement to the following terms, and your
12 use, installation, modification or redistribution of this Apple software
13 constitutes acceptance of these terms. If you do not agree with these terms,
14 please do not use, install, modify or redistribute this Apple software.
15
16 In consideration of your agreement to abide by the following terms, and subject
17 to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
18 copyrights in this original Apple software (the "Apple Software"), to use,
19 reproduce, modify and redistribute the Apple Software, with or without
20 modifications, in source and/or binary forms; provided that if you redistribute
21 the Apple Software in its entirety and without modifications, you must retain
22 this notice and the following text and disclaimers in all such redistributions of
23 the Apple Software. Neither the name, trademarks, service marks or logos of
24 Apple Computer, Inc. may be used to endorse or promote products derived from the
25 Apple Software without specific prior written permission from Apple. Except as
26 expressly stated in this notice, no other rights or licenses, express or implied,
27 are granted by Apple herein, including but not limited to any patent rights that
28 may be infringed by your derivative works or by other works in which the Apple
29 Software may be incorporated.
30
31 The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
32 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
33 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
34 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
35 COMBINATION WITH YOUR PRODUCTS.
36
37 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
38 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
39 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
41 OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
42 (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
43 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44
45 Change History (most recent first):
46
47$Log: MoreCFQ.c,v $
48Revision 1.5 2002/12/12 15:22:25 eskimo1
49Added CFQDictionaryMerge.
50
51Revision 1.4 2002/11/08 23:08:47 eskimo1
52Convert nil to NULL. Added CFQStringCopyCString. Convert MoreAssertQ to assert.
53
54Revision 1.3 2002/10/24 11:46:07 eskimo1
55Added CFQError routines.
56
57Revision 1.2 2002/01/22 06:14:19 eskimo1
58Change CFQDictionaryAddNumber to CFQDictionarySetNumber.
59
60Revision 1.1 2002/01/16 22:51:31 eskimo1
61First checked in.
62
63
64*/
65
66/////////////////////////////////////////////////////////////////
67
68// Our prototypes
69
70#include "MoreCFQ.h"
71
72// System interfaces
73
74#if ! MORE_FRAMEWORK_INCLUDES
75 #include <MacErrors.h>
76 #include <CFNumber.h>
77 #include <CFURLAccess.h>
78#endif
79
80#include <stdlib.h>
81
82/////////////////////////////////////////////////////////////////
83#pragma mark ***** Trivial Utilities
84
85extern pascal OSStatus CFQErrorBoolean(Boolean shouldBeTrue)
86{
87 OSStatus err;
88
89 err = noErr;
90 if (!shouldBeTrue) {
91 err = coreFoundationUnknownErr;
92 }
93 return err;
94}
95
96extern pascal OSStatus CFQError(const void *shouldBeNotNULL)
97{
98 return CFQErrorBoolean(shouldBeNotNULL != NULL);
99}
100
101extern pascal CFTypeRef CFQRetain(CFTypeRef cf)
102 // See comment in header.
103{
104 if (cf != NULL) {
105 (void) CFRetain(cf);
106 }
107 return cf;
108}
109
110extern pascal void CFQRelease(CFTypeRef cf)
111 // See comment in header.
112{
113 if (cf != NULL) {
114 CFRelease(cf);
115 }
116}
117
118extern pascal OSStatus CFQDictionaryCreateMutable(CFMutableDictionaryRef *result)
119 // See comment in header.
120{
121 OSStatus err;
122
123 assert( result != NULL);
124 assert(*result == NULL);
125
126 err = noErr;
127 *result = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
128 if (*result == NULL) {
129 err = coreFoundationUnknownErr;
130 }
131 assert( (err == noErr) == (*result != NULL) );
132 return err;
133}
134
135extern pascal OSStatus CFQArrayCreateMutable(CFMutableArrayRef *result)
136 // See comment in header.
137{
138 OSStatus err;
139
140 assert( result != NULL);
141 assert(*result == NULL);
142
143 err = noErr;
144 *result = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
145 if (*result == NULL) {
146 err = coreFoundationUnknownErr;
147 }
148 assert( (err == noErr) == (*result != NULL) );
149 return err;
150}
151
152extern pascal OSStatus CFQArrayCreateWithDictionaryKeys(CFDictionaryRef dict, CFArrayRef *result)
153 // See comment in header.
154{
155 OSStatus err;
156 CFTypeRef * keys;
157
158 assert( dict != NULL);
159 assert( result != NULL);
160 assert(*result == NULL);
161
162 // Allocate a buffer for the keys, get the keys into the buffer, and
163 // create the array from that buffer.
164
165 err = noErr;
166 keys = (CFTypeRef *) malloc( CFDictionaryGetCount(dict) * sizeof(CFTypeRef) );
167 if (keys == NULL) {
168 err = memFullErr;
169 }
170 if (err == noErr) {
171 CFDictionaryGetKeysAndValues(dict, (const void **) keys, NULL);
172
173 *result = CFArrayCreate(NULL, keys, CFDictionaryGetCount(dict), &kCFTypeArrayCallBacks);
174 if (*result == NULL) {
175 err = coreFoundationUnknownErr;
176 }
177 }
178
179 // Clean up.
180
181 if (keys != NULL) {
182 free(keys);
183 }
184
185 assert( (err == noErr) == (*result != NULL) );
186 assert( (*result == NULL) || (CFDictionaryGetCount(dict) == CFArrayGetCount(*result)) );
187
188 return err;
189}
190
191extern pascal OSStatus CFQArrayCreateWithDictionaryValues(CFDictionaryRef dict, CFArrayRef *result)
192 // See comment in header.
193{
194 OSStatus err;
195 CFTypeRef * values;
196
197 assert( dict != NULL);
198 assert( result != NULL);
199 assert(*result == NULL);
200
201 // Allocate a buffer for the values, get the values into the buffer, and
202 // create the array from that buffer.
203
204 err = noErr;
205 values = (CFTypeRef *) malloc( CFDictionaryGetCount(dict) * sizeof(CFTypeRef) );
206 if (values == NULL) {
207 err = memFullErr;
208 }
209 if (err == noErr) {
210 CFDictionaryGetKeysAndValues(dict, NULL, (const void **) values);
211
212 *result = CFArrayCreate(NULL, values, CFDictionaryGetCount(dict), &kCFTypeArrayCallBacks);
213 if (*result == NULL) {
214 err = coreFoundationUnknownErr;
215 }
216 }
217
218 // Clean up.
219
220 if (values != NULL) {
221 free(values);
222 }
223
224 assert( (err == noErr) == (*result != NULL) );
225 assert( (*result == NULL) || (CFDictionaryGetCount(dict) == CFArrayGetCount(*result)) );
226
227 return err;
228}
229
230extern pascal OSStatus CFQDictionaryCreateWithArrayOfKeysAndValues(CFArrayRef keys,
231 CFArrayRef values,
232 CFDictionaryRef *result)
233 // See comment in header.
234{
235 OSStatus err;
236 CFIndex count;
237 CFTypeRef * keysBuffer;
238 CFTypeRef * valuesBuffer;
239
240 assert(keys != NULL);
241 assert(values != NULL);
242 assert( CFArrayGetCount(keys) == CFArrayGetCount(values) );
243 assert( result != NULL);
244 assert(*result == NULL);
245
246 keysBuffer = NULL;
247 valuesBuffer = NULL;
248
249 // Check that the arrays are of a like size.
250
251 err = noErr;
252 count = CFArrayGetCount(keys);
253 if ( count != CFArrayGetCount(values) ) {
254 err = paramErr;
255 }
256
257 // Allocate a buffer for both keys and values.
258
259 if (err == noErr) {
260 keysBuffer = (CFTypeRef *) malloc( sizeof(CFTypeRef) * count );
261 valuesBuffer = (CFTypeRef *) malloc( sizeof(CFTypeRef) * count );
262 if (keysBuffer == NULL || valuesBuffer == NULL) {
263 err = memFullErr;
264 }
265 }
266
267 // Get the keys and values into their buffers, and create a
268 // dictionary based on the buffer.
269
270 if (err == noErr) {
271 CFArrayGetValues(keys, CFRangeMake(0, count), keysBuffer);
272 CFArrayGetValues(values, CFRangeMake(0, count), valuesBuffer);
273
274 *result = CFDictionaryCreate(NULL, keysBuffer, valuesBuffer, count, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
275 if (*result == NULL) {
276 err = coreFoundationUnknownErr;
277 }
278 }
279
280 // Clean up.
281
282 if (keysBuffer != NULL) {
283 free(keysBuffer);
284 }
285 if (valuesBuffer != NULL) {
286 free(valuesBuffer);
287 }
288
289 return err;
290}
291
292extern pascal OSStatus CFQDictionarySetNumber(CFMutableDictionaryRef dict, const void *key, long value)
293 // See comment in header.
294{
295 OSStatus err;
296 CFNumberRef valueNum;
297
298 // Create a CFNumber and add it to the dictionary.
299
300 err = noErr;
301 valueNum = CFNumberCreate(NULL, kCFNumberLongType, &value);
302 if (valueNum == NULL) {
303 err = coreFoundationUnknownErr;
304 }
305 if (err == noErr) {
306 CFDictionarySetValue(dict, key, valueNum);
307 }
308 CFQRelease(valueNum);
309
310 return err;
311}
312
313extern pascal OSStatus CFQStringCopyCString(CFStringRef str, CFStringEncoding encoding, char **cStrPtr)
314{
315 OSStatus err;
316 CFIndex cStrLen;
317 CFRange range;
318
319 assert( str != NULL);
320 assert( cStrPtr != NULL);
321 assert(*cStrPtr == NULL);
322
323 err = noErr;
324
325 range = CFRangeMake(0, CFStringGetLength(str));
326
327 (void) CFStringGetBytes(str, range, encoding, 0, false, NULL, 0, &cStrLen);
328
329 *cStrPtr = (char *) malloc( ((size_t) cStrLen) + 1);
330 if (*cStrPtr == NULL) {
331 err = memFullErr;
332 }
333
334 if (err == NULL) {
335 #if MORE_DEBUG
336 (*cStrPtr)[cStrLen] = '¥';
337 #endif
338
339 if ( CFStringGetBytes(str, range, encoding, 0, false, (UInt8 *) *cStrPtr, cStrLen, &cStrLen) != range.length ) {
340 err = kCFQDataErr;
341 }
342 }
343 if (err == noErr) {
344 assert((*cStrPtr)[cStrLen] == '¥');
345 (*cStrPtr)[cStrLen] = 0;
346 } else {
347 free(*cStrPtr);
348 *cStrPtr = NULL;
349 }
350
351 assert( (err == noErr) == (*cStrPtr != NULL) );
352
353 return err;
354}
355
356/////////////////////////////////////////////////////////////////
357#pragma mark ***** Dictionary Path Routines
358
359extern pascal OSStatus CFQDictionaryGetValueAtPath(CFDictionaryRef dict,
360 const void *path[], CFIndex pathElementCount,
361 const void **result)
362 // See comment in header.
363{
364 OSStatus err;
365 CFDictionaryRef parent;
366 CFIndex thisElement;
367 const void * child;
368
369 assert( dict != NULL);
370 assert( path != NULL);
371 assert( pathElementCount > 0 ); // 0 length paths aren't allowed
372 assert( result != NULL);
373 assert(*result == NULL);
374
375 // This code hasn't been tested yet.
376 assert(false);
377
378 // Some subtleties in the following loop.
379 //
380 // o It's possible for dictionaries to contain NULL values, so we use
381 // CFDictionaryGetValueIfPresent to test for the presence of the
382 // child rather than CFDictionaryGetValue.
383 //
384 // o We use CFDictionaryGetValueIfPresent in place of the combination of
385 // CFDictionaryContainsKey and CFDictionaryGetValue because it does
386 // both operations in one hit.
387 //
388 // o Loop terminates in one of three ways:
389 // i) a path element isn't found (kCFQKeyNotFoundErr)
390 // ii) we find the last path element
391 // iii) we proceed to the next path element but the child we
392 // found isn't valid (kCFQDataErr)
393 //
394 // o There are no releases or retains in this loop because all values are
395 // got with "Get" operations.
396
397 err = noErr;
398 thisElement = 0;
399 parent = dict;
400
401 while (true) {
402 if ( ! CFDictionaryGetValueIfPresent(parent, path[thisElement], &child) ) {
403 err = kCFQKeyNotFoundErr;
404 break;
405 }
406
407 if (thisElement == (pathElementCount - 1)) {
408 break;
409 }
410
411 if ( (child == NULL) || (CFGetTypeID(child) != CFDictionaryGetTypeID()) ) {
412 err = kCFQDataErr;
413 break;
414 }
415
416 parent = (CFDictionaryRef) child;
417 thisElement += 1;
418 }
419
420 if (err == noErr) {
421 *result = child;
422 }
423
424 assert( (err == noErr) == (*result != NULL) );
425
426 return err;
427}
428
429static OSStatus PathArrayHelper(CFArrayRef path, CFTypeRef **pathElements)
430 // pathElements is a pointer to an array of CFTypeRefs.
431 // On return, *pathElements is set to a newly allocated
432 // array which you must free using "free".
433{
434 OSStatus err;
435 CFIndex pathElementCount;
436
437 assert(path != NULL);
438 assert(pathElements != NULL);
439 // We don't assert that *pathElements is NULL because part of
440 // our semantics is that we always set it to NULL.
441
442 pathElementCount = CFArrayGetCount(path);
443 assert(pathElementCount > 0);
444
445 err = noErr;
446 *pathElements = (CFTypeRef *) malloc(sizeof(CFTypeRef) * pathElementCount);
447 if (*pathElements == NULL) {
448 err = memFullErr;
449 }
450 if (err == noErr) {
451 CFArrayGetValues(path, CFRangeMake(0, pathElementCount), *pathElements);
452 }
453
454 assert( (err == noErr) == (*pathElements != NULL) );
455
456 return err;
457}
458
459extern pascal OSStatus CFQDictionaryGetValueAtPathArray(CFDictionaryRef dict,
460 CFArrayRef path,
461 const void **result)
462 // See comment in header.
463{
464 OSStatus err;
465 CFTypeRef * pathElements;
466
467 assert( dict != NULL);
468 assert( path != NULL);
469 assert( result != NULL);
470 assert(*result == NULL);
471
472 err = PathArrayHelper(path, &pathElements);
473 if (err == noErr) {
474 err = CFQDictionaryGetValueAtPath(dict, pathElements, CFArrayGetCount(path), result);
475 }
476 if (pathElements != NULL) {
477 free(pathElements);
478 }
479
480 assert( (err == noErr) == (*result != NULL) );
481
482 return err;
483}
484
485static OSStatus CFQMutableDictionaryGetParentForPath(CFMutableDictionaryRef dict,
486 const void *path[], CFIndex pathElementCount,
487 CFMutableDictionaryRef *result)
488{
489 OSStatus err;
490 CFIndex thisElement;
491 CFMutableDictionaryRef parent;
492 CFDictionaryRef child;
493
494 assert( dict != NULL);
495 assert( path != NULL);
496 assert( pathElementCount > 0 ); // 0 length paths aren't allowed
497 assert( result != NULL);
498
499 // Some subtleties in the following loop.
500 //
501 // o It's possible for dictionaries to contain NULL values, so we use
502 // CFDictionaryGetValueIfPresent to test for the presence of the
503 // child rather than CFDictionaryGetValue.
504 //
505 // o We use CFDictionaryGetValueIfPresent in place of the combination of
506 // CFDictionaryContainsKey and CFDictionaryGetValue because it does
507 // both operations in one hit.
508 //
509 // o Loop terminates in one of three ways:
510 // i) we reach the last path element
511 // ii) a path element isn't found (kCFQKeyNotFoundErr)
512 // iii) we proceed to the next path element but the child we
513 // found isn't valid (kCFQDataErr)
514 // iv) we get an error when creating a mutable dictionary
515 //
516 // o Memory tracking is very tricky. Specifically, we have to be
517 // very careful with the mutableChild variable. We create this
518 // each time we progress through a dictionary in the loop. Each
519 // time we create it we then immediately add it to the parent
520 // dictionary, thus ensuring a continued reference count after
521 // we release our reference count.
522
523 err = noErr;
524 thisElement = 0;
525 parent = dict;
526
527 while (true) {
528 if (thisElement == (pathElementCount - 1)) {
529 break;
530 }
531
532 if ( ! CFDictionaryGetValueIfPresent(parent, path[thisElement], (const void **) &child) ) {
533 err = kCFQKeyNotFoundErr;
534 break;
535 }
536
537 if ( (child == NULL) || (CFGetTypeID(child) != CFDictionaryGetTypeID()) ) {
538 err = kCFQDataErr;
539 break;
540 }
541
542 {
543 CFMutableDictionaryRef mutableChild;
544
545 mutableChild = CFDictionaryCreateMutableCopy(NULL, 0, child);
546 if (mutableChild == NULL) {
547 err = coreFoundationUnknownErr;
548 }
549 if (err == noErr) {
550 CFDictionarySetValue(parent, path[thisElement], mutableChild);
551
552 assert( CFGetRetainCount(mutableChild) >= 2 );
553
554 parent = mutableChild;
555 thisElement += 1;
556 }
557
558 CFQRelease(mutableChild);
559 }
560 if (err != noErr) {
561 break;
562 }
563 }
564 if (err == noErr) {
565 *result = parent;
566 }
567
568 assert( (err == noErr) == (*result != NULL) );
569
570 return err;
571}
572
573extern pascal OSStatus CFQDictionarySetValueAtPath(CFMutableDictionaryRef dict,
574 const void *path[], CFIndex pathElementCount,
575 const void *value)
576 // See comment in header.
577{
578 OSStatus err;
579 CFMutableDictionaryRef parent;
580
581 assert( dict != NULL);
582 assert( path != NULL);
583 assert( pathElementCount > 0 ); // 0 length paths aren't allowed
584
585 err = CFQMutableDictionaryGetParentForPath(dict, path, pathElementCount, &parent);
586 if (err == noErr) {
587 CFDictionarySetValue(parent, path[pathElementCount - 1], value);
588 }
589
590 return err;
591}
592
593extern pascal OSStatus CFQDictionarySetValueAtPathArray(CFMutableDictionaryRef dict,
594 CFArrayRef path,
595 const void *value)
596 // See comment in header.
597{
598 OSStatus err;
599 CFTypeRef * pathElements;
600
601 assert( dict != NULL);
602 assert( path != NULL);
603
604 err = PathArrayHelper(path, &pathElements);
605 if (err == noErr) {
606 err = CFQDictionarySetValueAtPath(dict, pathElements, CFArrayGetCount(path), value);
607 }
608 if (pathElements != NULL) {
609 free(pathElements);
610 }
611
612 return err;
613}
614
615extern pascal OSStatus CFQDictionaryRemoveValueAtPath(CFMutableDictionaryRef dict,
616 const void *path[], CFIndex pathElementCount)
617 // See comment in header.
618{
619 OSStatus err;
620 CFMutableDictionaryRef parent;
621
622 assert( dict != NULL);
623 assert( path != NULL);
624 assert( pathElementCount > 0 ); // 0 length paths aren't allowed
625
626 err = CFQMutableDictionaryGetParentForPath(dict, path, pathElementCount, &parent);
627 if ( ! CFDictionaryContainsKey(parent, path[pathElementCount - 1]) ) {
628 err = kCFQKeyNotFoundErr;
629 }
630 if (err == noErr) {
631 CFDictionaryRemoveValue(parent, path[pathElementCount - 1]);
632 }
633
634 return err;
635}
636
637extern pascal OSStatus CFQDictionaryRemoveValueAtPathArray(CFMutableDictionaryRef dict,
638 CFArrayRef path)
639 // See comment in header.
640{
641 OSStatus err;
642 CFTypeRef * pathElements;
643
644 assert( dict != NULL);
645 assert( path != NULL);
646
647 err = PathArrayHelper(path, &pathElements);
648 if (err == noErr) {
649 err = CFQDictionaryRemoveValueAtPath(dict, pathElements, CFArrayGetCount(path));
650 }
651 if (pathElements != NULL) {
652 free(pathElements);
653 }
654
655 return err;
656}
657
658/////////////////////////////////////////////////////////////////
659#pragma mark ***** Property List Traversal Routines
660
661extern pascal void CFQPropertyListDeepApplyFunction(CFPropertyListRef propList,
662 CFQPropertyListDeepApplierFunction func,
663 void *context)
664 // See comment in header.
665{
666 assert(propList != NULL);
667 assert(func != NULL);
668
669 // Call "func" for this node.
670
671 func(propList, context);
672
673 // If this node is a dictionary or an array, call func for
674 // each element.
675
676 if ( CFGetTypeID(propList) == CFDictionaryGetTypeID() ) {
677 CFIndex count;
678 CFIndex index;
679 const void **keys;
680
681 count = CFDictionaryGetCount( (CFDictionaryRef) propList);
682
683 keys = (const void **) malloc( count * sizeof(const void *));
684 if (keys != NULL) {
685 CFDictionaryGetKeysAndValues( (CFDictionaryRef) propList, keys, NULL);
686
687 for (index = 0; index < count; index++) {
688 CFQPropertyListDeepApplyFunction(CFDictionaryGetValue( (CFDictionaryRef) propList, keys[index]), func, context);
689 }
690 free(keys);
691 }
692 } else if ( CFGetTypeID(propList) == CFArrayGetTypeID() ) {
693 CFIndex count;
694 long index;
695
696 count = CFArrayGetCount( (CFArrayRef) propList);
697 for (index = 0; index < count; index++) {
698 CFQPropertyListDeepApplyFunction(CFArrayGetValueAtIndex( (CFArrayRef) propList, index), func, context);
699 }
700 }
701}
702
703extern pascal Boolean CFQPropertyListIsLeaf(CFTypeRef node)
704 // See comment in header.
705{
706 return ! ( (CFGetTypeID(node) == CFDictionaryGetTypeID())
707 || (CFGetTypeID(node) == CFArrayGetTypeID()) );
708}
709
710extern pascal void CFQPropertyListShallowApplyFunction(CFPropertyListRef propList,
711 CFQPropertyListShallowApplierFunction func,
712 void *context)
713 // See comment in header.
714{
715 assert(propList != NULL);
716 assert(func != NULL);
717
718 // If this node is a dictionary, call "func" for each element.
719 //
720 // If this node is an array, call "func" for each element and
721 // pass a CFNumber of the element's array index to its "key"
722 // parameter.
723
724 if ( CFGetTypeID(propList) == CFDictionaryGetTypeID() ) {
725 CFIndex count;
726 CFIndex index;
727 const void **keys;
728
729 count = CFDictionaryGetCount( (CFDictionaryRef) propList);
730
731 keys = (const void **) malloc( count * sizeof(const void *));
732 if (keys != NULL) {
733 CFDictionaryGetKeysAndValues( (CFDictionaryRef) propList, keys, NULL);
734
735 for (index = 0; index < count; index++) {
736 func(keys[index], CFDictionaryGetValue( (CFDictionaryRef) propList, keys[index]), context);
737 }
738 free(keys);
739 }
740 } else if ( CFGetTypeID(propList) == CFArrayGetTypeID() ) {
741 CFIndex count;
742 CFIndex index;
743
744 count = CFArrayGetCount( (CFArrayRef) propList);
745 for (index = 0; index < count; index++) {
746 CFNumberRef key;
747
748 key = CFNumberCreate(NULL, kCFNumberLongType, &index);
749 if (key != NULL) {
750 func(key, CFArrayGetValueAtIndex( (CFArrayRef) propList, index), context);
751 CFRelease(key);
752 }
753 }
754 } else {
755 assert(false);
756 }
757}
758
759extern pascal OSStatus CFQPropertyListCreateFromXMLFSRef(const FSRef *xmlFile, CFPropertyListMutabilityOptions options, CFPropertyListRef *result)
760 // See comment in header.
761{
762 OSStatus err;
763 CFURLRef xmlURL;
764
765 assert(xmlFile != NULL);
766 assert( result != NULL);
767 assert(*result == NULL);
768
769 xmlURL = CFURLCreateFromFSRef(NULL, xmlFile);
770 err = CFQError(xmlURL);
771 if (err == noErr) {
772 err = CFQPropertyListCreateFromXMLCFURL(xmlURL, options, result);
773 }
774
775 CFQRelease(xmlURL);
776
777 assert( (err == noErr) == (*result != NULL) );
778
779 return err;
780}
781
782extern pascal OSStatus CFQPropertyListCreateFromXMLCFURL(CFURLRef xmlFile, CFPropertyListMutabilityOptions options, CFPropertyListRef *result)
783 // See comment in header.
784{
785 OSStatus err;
786 CFDataRef xmlData;
787
788 assert(xmlFile != NULL);
789 assert( result != NULL);
790 assert(*result == NULL);
791
792 xmlData = NULL;
793
794 err = noErr;
795 if ( ! CFURLCreateDataAndPropertiesFromResource(NULL, xmlFile, &xmlData, NULL, NULL, &err) && (err == noErr) ) {
796 err = coreFoundationUnknownErr;
797 }
798
799 if (err == noErr) {
800 *result = CFPropertyListCreateFromXMLData(NULL, xmlData, options, NULL);
801 if (*result == NULL) {
802 err = coreFoundationUnknownErr;
803 }
804 }
805
806 CFQRelease(xmlData);
807
808 assert( (err == noErr) == (*result != NULL) );
809
810 return err;
811}
812
813static void MergeOne(const void *key, const void *value, void *context)
814{
815 CFMutableDictionaryRef dst;
816
817 assert(context != NULL);
818
819 dst = (CFMutableDictionaryRef) context;
820 assert( CFGetTypeID(dst) == CFDictionaryGetTypeID() );
821
822 CFDictionarySetValue(dst, key, value);
823}
824
825extern pascal OSStatus CFQDictionaryMerge(CFMutableDictionaryRef dst, CFDictionaryRef src)
826{
827 OSStatus err;
828
829 assert(dst != NULL);
830 assert(src != NULL);
831
832 err = noErr;
833 CFDictionaryApplyFunction(src, MergeOne, dst);
834
835 return err;
836}
Note: See TracBrowser for help on using the repository browser.