source: trunk/base/src/cflib1.0/CFLib.c @ 13738

Last change on this file since 13738 was 13738, checked in by pguyot (Paul Guyot), 15 years ago

Add a lot of missing $Id$

  • Property svn:eol-style set to native
File size: 41.3 KB
Line 
1/*
2 * CFLib.c
3 * CFLib.dylib
4 * $Id: CFLib.c,v 1.3 2005/08/27 00:07:25 pguyot Exp $
5 *
6 * Copyright (c) 2003 Kevin Van Vechten <kevin@opendarwin.org>
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the copyright owner nor the names of contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <tcl.h>
35#include <CoreFoundation/CoreFoundation.h>
36
37/*
38        Wildebeest
39        TCL bindings for CoreFoundation
40       
41        Currently CFString, CFData, CFURL, CFArray, and CFDictionary are
42        toll free bridged.
43       
44        Most of CFArray, CFDictionary, CFBundle, and CFPropertyList
45        have been implemented.
46       
47        TODO:
48                Toll free bridges for CFNumber, CFDate, CFBoolean.
49 */
50
51/* CFBase.h */
52
53/* CFType ObjType */
54static int tclObjToCFString(Tcl_Interp*, Tcl_Obj*, CFTypeRef*);
55static int tclObjToCFType(Tcl_Interp* interp, Tcl_Obj* obj, CFTypeRef* outPtr) {
56        *outPtr = NULL;
57        if (obj->typePtr == Tcl_GetObjType("CFString") ||
58                obj->typePtr == Tcl_GetObjType("CFData") ||
59                obj->typePtr == Tcl_GetObjType("CFURL") ||
60                obj->typePtr == Tcl_GetObjType("CFNumber") ||
61                obj->typePtr == Tcl_GetObjType("CFArray") ||
62                obj->typePtr == Tcl_GetObjType("CFDictionary") ||
63                obj->typePtr == Tcl_GetObjType("CFBundle") ||
64                obj->typePtr == Tcl_GetObjType("CFType")) {
65                *outPtr = CFRetain(obj->internalRep.otherValuePtr);
66        } else {
67                return tclObjToCFString(interp, obj, outPtr);
68        }
69        return TCL_OK;
70}
71
72static void cfTypeDupInternalRepProc(Tcl_Obj* srcPtr, Tcl_Obj* dupPtr) {
73        dupPtr->typePtr = srcPtr->typePtr;
74        CFTypeRef cf = srcPtr->internalRep.otherValuePtr;
75        dupPtr->internalRep.otherValuePtr = cf ? (void*)CFRetain(cf) : NULL;
76}
77
78static void cfTypeFreeInternalRepProc(Tcl_Obj* objPtr) {
79        objPtr->typePtr = NULL;
80        CFTypeRef cf = objPtr->internalRep.otherValuePtr;
81        if (cf) CFRelease(cf);
82}
83
84static void cfTypeUpdateStringProc2(Tcl_Obj* objPtr, CFStringRef str) {
85        if (str) {
86                CFIndex length = CFStringGetLength(str);
87                CFIndex size = CFStringGetMaximumSizeForEncoding(length + 1, kCFStringEncodingUTF8);
88                objPtr->bytes = Tcl_Alloc(size);
89                if (objPtr->bytes) {
90                        CFIndex bytesUsed;
91                        CFStringGetBytes(str, CFRangeMake(0, length), kCFStringEncodingUTF8, '?', 0, objPtr->bytes, size, &bytesUsed);
92                        objPtr->length = bytesUsed;
93                        objPtr->bytes[bytesUsed] = 0;   // terminating NUL as per TCL spec.
94                }
95        }
96}
97
98static void cfTypeUpdateStringProc(Tcl_Obj* objPtr) {
99        CFTypeRef cf = objPtr->internalRep.otherValuePtr;
100        if (cf) {
101                CFStringRef str = CFCopyDescription(cf);
102                if (str) {
103                        cfTypeUpdateStringProc2(objPtr, str);
104                        CFRelease(str);
105                }
106        }
107}
108
109static int cfTypeSetFromAnyProc(Tcl_Interp* interp, Tcl_Obj* objPtr) {
110        Tcl_Obj* tcl_result = Tcl_NewStringObj("CFTypes must be created with CF constructors", -1);
111        Tcl_SetObjResult(interp, tcl_result);
112        return TCL_ERROR;
113}
114
115static void cfTypeRegister() {
116        static Tcl_ObjType cfTypeType;
117        cfTypeType.name = "CFType";
118        cfTypeType.freeIntRepProc = cfTypeFreeInternalRepProc;
119        cfTypeType.dupIntRepProc = cfTypeDupInternalRepProc;
120        cfTypeType.updateStringProc = cfTypeUpdateStringProc;
121        cfTypeType.setFromAnyProc = cfTypeSetFromAnyProc;
122        Tcl_RegisterObjType(&cfTypeType);
123}
124
125
126
127
128/* CFString.h */
129
130// tcl string -> CFString implicit conversion
131static int tclObjToCFString(Tcl_Interp* interp, Tcl_Obj* obj, CFTypeRef* outString) {
132        *outString = NULL;
133        if (obj->typePtr != Tcl_GetObjType("CFString")) {
134                int length;
135                char* buf = Tcl_GetStringFromObj(obj, &length);
136                if (buf) {
137                        *outString = CFStringCreateWithBytes(NULL, buf, length, kCFStringEncodingUTF8, 0);
138                } else {
139                        return TCL_ERROR;
140                }
141        } else {
142                *outString = CFRetain(obj->internalRep.otherValuePtr);
143        }
144        return TCL_OK;
145}
146
147// CFString -> tcl string implicit conversion
148static Tcl_Obj* cfStringToTCLString(CFStringRef cf) {
149        Tcl_Obj* tcl_result = NULL;
150        if (cf) {
151                CFIndex length = CFStringGetLength(cf);
152                CFIndex size = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUnicode);
153                UniChar* buffer = (UniChar*)Tcl_Alloc(size);
154                if (buffer) {
155                        CFStringGetCharacters(cf, CFRangeMake(0, length), buffer);
156                        tcl_result = Tcl_NewUnicodeObj(buffer, length);
157                        Tcl_Free((char*)buffer);
158                }
159        }
160        return tcl_result;
161}
162
163
164/* CFString ObjType */
165
166static int cfStringSetFromAnyProc(Tcl_Interp* interp, Tcl_Obj* objPtr) {
167        if (objPtr->bytes) {
168                objPtr->internalRep.otherValuePtr = (void*)CFStringCreateWithBytes(NULL, 
169                                                                                                objPtr->bytes,
170                                                                                                objPtr->length,
171                                                                                                kCFStringEncodingUTF8,
172                                                                                                0);
173                return TCL_OK;
174        } else {
175                return TCL_ERROR;
176        }
177}
178
179static void cfStringUpdateStringProc(Tcl_Obj* objPtr) {
180        cfTypeUpdateStringProc2(objPtr, objPtr->internalRep.otherValuePtr);
181}
182
183static void cfStringRegister() {
184        static Tcl_ObjType cfStringType;
185        cfStringType.name = "CFString";
186        cfStringType.freeIntRepProc = cfTypeFreeInternalRepProc;
187        cfStringType.dupIntRepProc = cfTypeDupInternalRepProc;
188        cfStringType.updateStringProc = cfStringUpdateStringProc;
189        cfStringType.setFromAnyProc = cfStringSetFromAnyProc;
190        Tcl_RegisterObjType(&cfStringType);
191}
192
193/* CFData.h */
194/* CFData ObjType */
195
196// tcl string -> CFData implicit conversion
197static int tclObjToCFData(Tcl_Interp* interp, Tcl_Obj* obj, CFTypeRef* outData) {
198        *outData = NULL;
199        if (obj->typePtr != Tcl_GetObjType("CFData")) {
200                int length;
201                char* buf = Tcl_GetStringFromObj(obj, &length);
202                if (buf) {
203                        *outData = CFDataCreate(NULL, buf, length);
204                } else {
205                        return TCL_ERROR;
206                }
207        } else {
208                *outData = CFRetain(obj->internalRep.otherValuePtr);
209        }
210        return TCL_OK;
211}
212
213static int cfDataSetFromAnyProc(Tcl_Interp* interp, Tcl_Obj* objPtr) {
214        if (objPtr->bytes) {
215                objPtr->internalRep.otherValuePtr = (void*)CFDataCreate(NULL, 
216                                                                                                objPtr->bytes,
217                                                                                                objPtr->length);
218                return TCL_OK;
219        } else {
220                return TCL_ERROR;
221        }
222}
223
224static void cfDataUpdateStringProc(Tcl_Obj* objPtr) {
225        CFDataRef data = objPtr->internalRep.otherValuePtr;
226        if (data) {
227                CFIndex length = CFDataGetLength(data);
228                objPtr->bytes = Tcl_Alloc(length);
229                if (objPtr->bytes) {
230                        CFDataGetBytes(data, CFRangeMake(0, length), objPtr->bytes);
231                        objPtr->length = length;
232                }
233        }
234}
235
236static void cfDataRegister() {
237        static Tcl_ObjType cfDataType;
238        cfDataType.name = "CFData";
239        cfDataType.freeIntRepProc = cfTypeFreeInternalRepProc;
240        cfDataType.dupIntRepProc = cfTypeDupInternalRepProc;
241        cfDataType.updateStringProc = cfDataUpdateStringProc;
242        cfDataType.setFromAnyProc = cfDataSetFromAnyProc;
243        Tcl_RegisterObjType(&cfDataType);
244}
245
246
247/* CFArray.h */
248/* CFArray ObjType */
249
250// tcl list -> CFArray implicit conversion
251static int tclObjToCFArray(Tcl_Interp* interp, Tcl_Obj* obj, CFTypeRef* outPtr) {
252        int result = TCL_OK;
253        *outPtr = NULL;
254        if (obj->typePtr != Tcl_GetObjType("CFArray")) {
255                int objc;
256                Tcl_Obj** objv;
257                result = Tcl_ListObjGetElements(interp, obj, &objc, &objv);
258                if (result == TCL_OK) {
259                        const void** argv = (const void**)Tcl_Alloc(sizeof(void*) * objc);
260                        int i;
261                        for (i = 0; i < objc; ++i) {
262                                result = tclObjToCFType(interp, objv[i], (CFTypeRef*)&argv[i]);
263                                if (result != TCL_OK) break;
264                        }
265                        if (result == TCL_OK) {
266                                *outPtr = CFArrayCreate(NULL, argv, objc, &kCFTypeArrayCallBacks);
267                        }
268                        Tcl_Free((char*)argv);
269                }
270        } else {
271                *outPtr = CFRetain(obj->internalRep.otherValuePtr);
272        }
273        return result;
274}
275
276static int cfArraySetFromAnyProc(Tcl_Interp* interp, Tcl_Obj* objPtr) {
277        Tcl_Obj* tcl_result = Tcl_NewStringObj("CFArrays must be created with CFArrayCreate", -1);
278        Tcl_SetObjResult(interp, tcl_result);
279        return TCL_ERROR;
280}
281
282static void cfArrayRegister() {
283        static Tcl_ObjType cfArrayType;
284        cfArrayType.name = "CFArray";
285        cfArrayType.freeIntRepProc = cfTypeFreeInternalRepProc;
286        cfArrayType.dupIntRepProc = cfTypeDupInternalRepProc;
287        cfArrayType.updateStringProc = cfTypeUpdateStringProc;
288        cfArrayType.setFromAnyProc = cfArraySetFromAnyProc;
289        Tcl_RegisterObjType(&cfArrayType);
290}
291
292
293/* CFDictionary.h */
294/* CFDictionary ObjType */
295// tcl list -> CFDictionary implicit conversion
296static int tclObjToCFDictionary(Tcl_Interp* interp, Tcl_Obj* obj, CFTypeRef* outPtr) {
297        int result = TCL_OK;
298        *outPtr = NULL;
299        if (obj->typePtr != Tcl_GetObjType("CFDictionary")) {
300                int objc;
301                Tcl_Obj** objv;
302                result = Tcl_ListObjGetElements(interp, obj, &objc, &objv);
303                if (result == TCL_OK) {                 
304                        if (objc & 1) {
305                                Tcl_Obj* tcl_result = Tcl_NewStringObj("list must have an even number of elements", -1);
306                                Tcl_SetObjResult(interp, tcl_result);
307                                result = TCL_ERROR;
308                        } else {
309                                const void** keys = (const void**)Tcl_Alloc(sizeof(void*) * objc / 2);
310                                const void** vals = (const void**)Tcl_Alloc(sizeof(void*) * objc / 2);
311                                int i, j;
312                                for (i = 0, j = 0; i < objc; i += 2, ++j) {
313                                        result = tclObjToCFType(interp, objv[i], (CFTypeRef*)&keys[j]);
314                                        if (result != TCL_OK) break;
315                                        result = tclObjToCFType(interp, objv[i+1], (CFTypeRef*)&vals[j]);
316                                        if (result != TCL_OK) break;
317                                }
318                                if (result == TCL_OK) {
319                                        *outPtr = CFDictionaryCreate(NULL, keys, vals, objc / 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
320                                }
321                                Tcl_Free((char*)keys);
322                                Tcl_Free((char*)vals);
323                        }
324                }
325        } else {
326                *outPtr = CFRetain(obj->internalRep.otherValuePtr);
327        }
328        return result;
329}
330
331static int cfDictionarySetFromAnyProc(Tcl_Interp* interp, Tcl_Obj* objPtr) {
332        Tcl_Obj* tcl_result = Tcl_NewStringObj("CFDictionaries must be created with CFDictionaryCreate", -1);
333        Tcl_SetObjResult(interp, tcl_result);
334        return TCL_ERROR;
335}
336
337static void cfDictionaryRegister() {
338        static Tcl_ObjType cfDictionaryType;
339        cfDictionaryType.name = "CFDictionary";
340        cfDictionaryType.freeIntRepProc = cfTypeFreeInternalRepProc;
341        cfDictionaryType.dupIntRepProc = cfTypeDupInternalRepProc;
342        cfDictionaryType.updateStringProc = cfTypeUpdateStringProc;
343        cfDictionaryType.setFromAnyProc = cfDictionarySetFromAnyProc;
344        Tcl_RegisterObjType(&cfDictionaryType);
345}
346
347/* CFNumber.h */
348/* CFNumber ObjType */
349
350static int cfNumberSetFromAnyProc(Tcl_Interp* interp, Tcl_Obj* objPtr) {
351        Tcl_Obj* tcl_result = Tcl_NewStringObj("CFNumbers must be created with CFNumberCreate", -1);
352        Tcl_SetObjResult(interp, tcl_result);
353        return TCL_ERROR;
354}
355
356// XXX: consolidate with cfStringUpdateStringProc
357static void cfNumberUpdateStringProc(Tcl_Obj* objPtr) {
358        CFNumberRef number = objPtr->internalRep.otherValuePtr;
359        CFStringRef str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@"), number);
360        if (str) {
361                cfTypeUpdateStringProc2(objPtr, str);
362                CFRelease(str);
363        }
364}
365
366static void cfNumberRegister() {
367        static Tcl_ObjType cfNumberType;
368        cfNumberType.name = "CFNumber";
369        cfNumberType.freeIntRepProc = cfTypeFreeInternalRepProc;
370        cfNumberType.dupIntRepProc = cfTypeDupInternalRepProc;
371        cfNumberType.updateStringProc = cfNumberUpdateStringProc;
372        cfNumberType.setFromAnyProc = cfNumberSetFromAnyProc;
373        Tcl_RegisterObjType(&cfNumberType);
374}
375
376//CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr);
377int tclCFNumberCreate(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
378        CFStringRef string;
379        int                     result = TCL_OK;
380        Tcl_Obj*        tcl_result;
381        char*           theType;
382        if (objc != 3) {
383                Tcl_WrongNumArgs(interp, 1, objv, "theType value");
384                return TCL_ERROR;
385        }
386        theType = Tcl_GetStringFromObj(objv[1], NULL);
387       
388        tcl_result = Tcl_NewObj();
389        tcl_result->typePtr = Tcl_GetObjType("CFNumber");
390        tcl_result->bytes = NULL;
391        tcl_result->length = 0;
392       
393        // This may be cutting corners, but since property lists only
394        // distinguish between real and integer, we'll only make that
395        // distinction here too.
396        if (strcmp(theType, "kCFNumberSInt8Type") == 0 ||
397                strcmp(theType, "kCFNumberSInt16Type") == 0 ||
398                strcmp(theType, "kCFNumberSInt32Type") == 0 ||
399                strcmp(theType, "kCFNumberSInt64Type") == 0 ||
400                strcmp(theType, "kCFNumberCharType") == 0 ||
401                strcmp(theType, "kCFNumberShortType") == 0 ||
402                strcmp(theType, "kCFNumberIntType") == 0 ||
403                strcmp(theType, "kCFNumberLongType") == 0 ||
404                strcmp(theType, "kCFNumberLongLongType") == 0 ||
405                strcmp(theType, "kCFNumberCFIndexType") == 0) {
406                        long val;
407                        result = Tcl_GetLongFromObj(interp, objv[2], &val);
408                        if (result == TCL_ERROR) return result;
409                        tcl_result->internalRep.otherValuePtr = (void*)CFNumberCreate(NULL, kCFNumberLongType, &val);
410        } else if (strcmp(theType, "kCFNumberFloatType") == 0 ||
411                strcmp(theType, "kCFNumberDoubleType") == 0 ||
412                strcmp(theType, "kCFNumberFloat32Type") == 0 ||
413                strcmp(theType, "kCFNumberFloat64Type") == 0) {
414                        double val;
415                        result = Tcl_GetDoubleFromObj(interp, objv[2], &val);
416                        if (result == TCL_ERROR) return result;
417                        tcl_result->internalRep.otherValuePtr = (void*)CFNumberCreate(NULL, kCFNumberDoubleType, &val);         
418        } else {
419                Tcl_Obj* tcl_result = Tcl_NewStringObj("unknown CFNumberType", -1);
420                Tcl_SetObjResult(interp, tcl_result);
421                return TCL_ERROR;
422        }
423        Tcl_SetObjResult(interp, tcl_result);
424        return result;
425}
426
427
428/* CFURL.h */
429
430// tcl string -> CFString implicit conversion
431static int tclObjToCFURL(Tcl_Interp* interp, Tcl_Obj* obj, CFTypeRef* outURL) {
432        *outURL = NULL;
433        if (obj->typePtr != Tcl_GetObjType("CFURL")) {
434                int length;
435                char* buf = Tcl_GetStringFromObj(obj, &length);
436                if (buf) {
437                        *outURL = CFURLCreateWithBytes(NULL, buf, length, kCFStringEncodingUTF8, NULL);
438                } else {
439                        return TCL_ERROR;
440                }
441        } else {
442                *outURL = CFRetain(obj->internalRep.otherValuePtr);
443        }
444        return TCL_OK;
445}
446/*
447// CFString -> tcl string implicit conversion
448static Tcl_Obj* cfURLToTCLString(CFURLRef url) {
449        CFDataRef data = CFURLCreateData(NULL, url, kCFStringEncodingUTF8, 1);
450        Tcl_Obj* tcl_result = NULL;
451        if (data) {
452                CFIndex length = CFDataGetLength(data);
453                char* buffer = Tcl_Alloc(length);
454                if (buffer) {
455                        CFDataGetBytes(data, CFRangeMake(0, length), buffer);
456                        tcl_result = Tcl_NewStringObj(buffer, length);
457                        Tcl_Free(buffer);
458                }
459        }
460        return tcl_result;
461}
462*/
463
464/* CFString ObjType */
465
466static int cfURLSetFromAnyProc(Tcl_Interp* interp, Tcl_Obj* objPtr) {
467        if (objPtr->bytes) {
468                objPtr->internalRep.otherValuePtr = (void*)CFURLCreateWithBytes(NULL, 
469                                                                                                objPtr->bytes,
470                                                                                                objPtr->length,
471                                                                                                kCFStringEncodingUTF8,
472                                                                                                NULL);
473                if (objPtr->internalRep.otherValuePtr == NULL) return TCL_ERROR;
474                return TCL_OK;
475        } else {
476                return TCL_ERROR;
477        }
478}
479
480static void cfURLUpdateStringProc(Tcl_Obj* objPtr) {
481        CFURLRef url = objPtr->internalRep.otherValuePtr;
482        if (url) {
483                CFURLRef absurl = CFURLCopyAbsoluteURL(url);
484                if (absurl) {
485                        CFStringRef str = CFURLGetString(absurl);
486                        cfTypeUpdateStringProc2(objPtr, str);
487                        CFRelease(absurl);
488                }
489        }
490}
491
492static void cfURLRegister() {
493        static Tcl_ObjType cfURLType;
494        cfURLType.name = "CFURL";
495        cfURLType.freeIntRepProc = cfTypeFreeInternalRepProc;
496        cfURLType.dupIntRepProc = cfTypeDupInternalRepProc;
497        cfURLType.updateStringProc = cfURLUpdateStringProc;
498        cfURLType.setFromAnyProc = cfURLSetFromAnyProc;
499        Tcl_RegisterObjType(&cfURLType);
500}
501
502
503
504
505/* CFBase.h */
506
507static Tcl_Obj* cfTypeToTCLString(CFTypeRef cf) {
508        if (CFGetTypeID(cf) == CFStringGetTypeID()) {
509                return cfStringToTCLString(cf);
510        } else {
511                CFStringRef string = CFCopyDescription(cf);
512                return cfStringToTCLString(string);
513        }
514}
515
516
517// CFGetTypeID(cf)
518int tclCFGetTypeID(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
519        CFTypeRef cf;
520        Tcl_Obj* tcl_result;
521        if (objc != 2) {
522                Tcl_WrongNumArgs(interp, 1, objv, "cftype");
523                return TCL_ERROR;
524        }
525        cf = objv[1]->internalRep.otherValuePtr;
526        if (cf) {
527                // xxx: test for valid objv[1]->typePtr;
528                tcl_result = Tcl_NewIntObj(CFGetTypeID(cf));
529                if (!tcl_result) return TCL_ERROR;
530                Tcl_SetObjResult(interp, tcl_result);
531                return TCL_OK;
532        } else {
533                return TCL_ERROR;
534        }
535}
536
537// CFNumberGetTypeID(), CFStringGetTypeID(), et al.
538int tclCFGetTypeID2(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
539        Tcl_Obj* tcl_result;
540        if (objc != 1) {
541                Tcl_WrongNumArgs(interp, 1, objv, "");
542                return TCL_ERROR;
543        }
544        tcl_result = Tcl_NewIntObj((int)clientData);
545        if (!tcl_result) return TCL_ERROR;
546        Tcl_SetObjResult(interp, tcl_result);
547        return TCL_OK;
548}
549
550
551/* CFPropertyList.h */
552
553static int tclObjToCFPropertyList(Tcl_Interp* interp, Tcl_Obj* obj, CFTypeRef* outPtr) {
554        *outPtr = NULL;
555        if (obj->typePtr == Tcl_GetObjType("CFString") ||
556                obj->typePtr == Tcl_GetObjType("CFData") ||
557                obj->typePtr == Tcl_GetObjType("CFNumber") ||
558                obj->typePtr == Tcl_GetObjType("CFArray") ||
559                obj->typePtr == Tcl_GetObjType("CFDictionary")) {
560                *outPtr = CFRetain(obj->internalRep.otherValuePtr);
561        } else {
562                return tclObjToCFString(interp, obj, outPtr);
563        }
564        return TCL_OK;
565}
566
567static int tclObjToCFPropertyListFormat(Tcl_Interp* interp, Tcl_Obj* obj, CFTypeRef* outPtr) {
568        int result = TCL_OK, length;
569        char* buf = Tcl_GetStringFromObj(obj, &length);
570        *outPtr = NULL;
571        if (buf && strcmp(buf, "kCFPropertyListOpenStepFormat") == 0) {
572                *outPtr = (CFTypeRef) kCFPropertyListOpenStepFormat;
573        } else if (buf && strcmp(buf, "kCFPropertyListXMLFormat_v1_0") == 0) {
574                *outPtr = (CFTypeRef) kCFPropertyListXMLFormat_v1_0;
575        } else if (buf && strcmp(buf, "kCFPropertyListBinaryFormat_v1_0") == 0) {
576                *outPtr = (CFTypeRef) kCFPropertyListBinaryFormat_v1_0;
577        } else {
578                Tcl_Obj* tcl_result = Tcl_NewStringObj("invalid property list format constant", -1);
579                Tcl_SetObjResult(interp, tcl_result);
580                result = TCL_ERROR;
581        }
582        return result;
583}
584
585static int tclObjToCFMutabilityOption(Tcl_Interp* interp, Tcl_Obj* obj, CFTypeRef* outPtr) {
586        int result = TCL_OK, length;
587        char* buf = Tcl_GetStringFromObj(obj, &length);
588        *outPtr = NULL;
589        if (buf && strcmp(buf, "kCFPropertyListImmutable") == 0) {
590                *outPtr = (CFTypeRef) kCFPropertyListImmutable;
591        } else if (buf && strcmp(buf, "kCFPropertyListMutableContainers") == 0) {
592                *outPtr = (CFTypeRef) kCFPropertyListMutableContainers;
593        } else if (buf && strcmp(buf, "kCFPropertyListMutableContainersAndLeaves") == 0) {
594                *outPtr = (CFTypeRef) kCFPropertyListMutableContainersAndLeaves;
595        } else {
596                Tcl_Obj* tcl_result = Tcl_NewStringObj("invalid mutability option constant", -1);
597                Tcl_SetObjResult(interp, tcl_result);
598                result = TCL_ERROR;
599        }
600        return result;
601}
602
603
604
605/* CFBundle.h */
606/* CFBundle ObjType */
607
608static int tclObjToCFBundle(Tcl_Interp* interp, Tcl_Obj* obj, CFTypeRef* outPtr) {
609        *outPtr = NULL;
610        if (obj->typePtr == Tcl_GetObjType("CFBundle")) {
611                *outPtr = CFRetain(obj->internalRep.otherValuePtr);
612        } else {
613                Tcl_Obj* tcl_result = Tcl_NewStringObj("argument must be a CFBundle", -1);
614                Tcl_SetObjResult(interp, tcl_result);
615                return TCL_ERROR;
616        }
617        return TCL_OK;
618}
619
620static int cfBundleSetFromAnyProc(Tcl_Interp* interp, Tcl_Obj* objPtr) {
621        Tcl_Obj* tcl_result = Tcl_NewStringObj("CFBundles must be created with CFBundleCreate", -1);
622        Tcl_SetObjResult(interp, tcl_result);
623        return TCL_ERROR;
624}
625
626static void cfBundleUpdateStringProc(Tcl_Obj* objPtr) {
627        CFBundleRef bundle = objPtr->internalRep.otherValuePtr;
628        if (bundle) {
629                CFStringRef description = CFCopyDescription(bundle);
630                if (description) {
631                        CFIndex length = CFStringGetLength(description);
632                        CFIndex size = CFStringGetMaximumSizeForEncoding(length + 1, kCFStringEncodingUTF8);
633                        objPtr->bytes = Tcl_Alloc(size);
634                        if (objPtr->bytes) {
635                                CFIndex bytesUsed;
636                                CFStringGetBytes(description, CFRangeMake(0, length), kCFStringEncodingUTF8, '?', 0, objPtr->bytes, size, &bytesUsed);
637                                objPtr->length = bytesUsed;
638                                objPtr->bytes[bytesUsed] = 0;   // terminating NUL as per TCL spec.
639                        }
640                        CFRelease(description);
641                }
642        }
643}
644
645static void cfBundleDupInternalRepProc(Tcl_Obj* srcPtr, Tcl_Obj* dupPtr) {
646        CFBundleRef bundle = srcPtr->internalRep.otherValuePtr;
647        dupPtr->internalRep.otherValuePtr = bundle ? (void*)CFRetain(bundle) : NULL;
648}
649
650static void cfBundleFreeInternalRepProc(Tcl_Obj* objPtr) {
651        CFBundleRef bundle = objPtr->internalRep.otherValuePtr;
652        if (bundle) CFRelease(bundle);
653}
654
655static void cfBundleRegister() {
656        static Tcl_ObjType cfBundleType;
657        cfBundleType.name = "CFBundle";
658        cfBundleType.freeIntRepProc = cfBundleFreeInternalRepProc;
659        cfBundleType.dupIntRepProc = cfBundleDupInternalRepProc;
660        cfBundleType.updateStringProc = cfBundleUpdateStringProc;
661        cfBundleType.setFromAnyProc = cfBundleSetFromAnyProc;
662        Tcl_RegisterObjType(&cfBundleType);
663}
664
665enum {
666        LITERAL,
667        CFTYPE,
668        CFRANGE,
669        CFINDEX,
670        CFERRORSTR,
671        END
672};
673
674typedef struct cfParam {
675        int kind;                       // LITERAL (doesn't pop argument), CFTYPE (32bit), CFRANGE (64bit)
676        char* class;            // if present, type check, if null, don't type check.
677        int (*func)(Tcl_Interp*, Tcl_Obj*, CFTypeRef*); // conversion function or literal value.
678} cfParam;
679
680typedef struct cfSignature {
681        char* name;                     // name of CF function to call
682        void* func;                     // pointer to CF function to call
683        char* format;           // tcl format string
684        char* result;           // type of result
685        int releaseResult;      // true if result should be released (create and copy funcs)
686        cfParam argv[10];       // description of arguments
687} cfSignature;
688
689
690static int tclCFFunc(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
691        cfSignature* sig = (cfSignature*)clientData;
692        int result = TCL_OK;
693        Tcl_Obj* tcl_result;
694        void* res;
695       
696        int i, j, k;
697        void** args;
698
699        // iterate through argv and count up all non-LITERALs
700        // this is the expected objc.
701        for (i = 0, j = 1; sig->argv[i].kind != END; ++i) {
702                if (sig->argv[i].kind != LITERAL && sig->argv[i].kind != CFERRORSTR) ++j;
703        }
704
705        if (objc != j) {
706                Tcl_WrongNumArgs(interp, 1, objv, sig->format);
707                return TCL_ERROR;
708        }
709       
710        args = (void**)Tcl_Alloc(sizeof(void*) * /* argc */ 20);
711
712        for (i = 0, j = 0, k = 1; sig->argv[j].kind != END; ++i, ++j) {
713                // i is index to local args array.
714                // j is index to argv
715                // k is index to objv
716               
717                // Copy literal value, don't pop from Tcl stack.
718                switch (sig->argv[j].kind) {
719                        case LITERAL:
720                                args[i] = (void*)sig->argv[j].func;
721                                break;
722                       
723                        case CFTYPE:
724                                // test that the classes match, if both are set.
725                                //if (!sig->argv[j].class || objv[k]->typePtr == NULL || objv[k]->typePtr == Tcl_GetObjType(sig->argv[j].class)) {
726                                        result = sig->argv[j].func(interp, objv[k], (CFTypeRef*) &args[i]);
727                                //} else {
728                                //      Tcl_Obj* tcl_result = Tcl_NewStringObj("argument must be a ", -1);
729                                //      Tcl_AppendToObj(tcl_result, sig->argv[j].class, -1);
730                                //      Tcl_SetObjResult(interp, tcl_result);
731                                //      result = TCL_ERROR;
732                                //}
733                                ++k;
734                                break;
735                               
736                        case CFINDEX:
737                                result = Tcl_GetIntFromObj(interp, objv[k], (int*) &args[i]);
738                                ++k;
739                                break;
740                               
741                        case CFERRORSTR:
742                                args[i] = (void*) Tcl_Alloc(sizeof(CFStringRef));
743                                break;
744                               
745                        case CFRANGE:
746                                ++k;
747                        default:
748                                break;
749                }
750                if (result != TCL_OK) break;
751        }
752       
753        if (result == TCL_OK) {
754        objc = i;
755        if (objc == 0) {
756                res = ((void* (*)())sig->func)();
757        } else if (objc == 1) {
758                res = ((void* (*)(void*))sig->func)(args[0]);
759        } else if (objc == 2) {
760                res = ((void* (*)(void*,void*))sig->func)(args[0],args[1]);
761        } else if (objc == 3) {
762                res = ((void* (*)(void*,void*,void*))sig->func)(args[0],args[1],args[2]);
763        } else if (objc == 4) {
764                res = ((void* (*)(void*,void*,void*,void*))sig->func)(args[0],args[1],args[2],args[3]);
765        } else if (objc == 5) {
766                res = ((void* (*)(void*,void*,void*,void*,void*))sig->func)(args[0],args[1],args[2],args[3],args[4]);
767        } else if (objc == 6) {
768                res = ((void* (*)(void*,void*,void*,void*,void*,void*))sig->func)(args[0],args[1],args[2],args[3],args[4],args[5]);
769        }
770
771        if (sig->result && strcmp(sig->result, "void") != 0) {
772                tcl_result = Tcl_NewObj();
773                tcl_result->bytes = NULL;
774                tcl_result->length = 0;
775                if (strcmp(sig->result, "CFType") == 0) {
776                        if (res) {
777                                CFTypeID id = CFGetTypeID(res);
778                                if (id == CFStringGetTypeID()) tcl_result->typePtr = Tcl_GetObjType("CFString");
779                                else if (id == CFNumberGetTypeID()) tcl_result->typePtr = Tcl_GetObjType("CFNumber");
780                                else if (id == CFDataGetTypeID()) tcl_result->typePtr = Tcl_GetObjType("CFData");
781                                else if (id == CFURLGetTypeID()) tcl_result->typePtr = Tcl_GetObjType("CFURL");
782                                else if (id == CFBundleGetTypeID()) tcl_result->typePtr = Tcl_GetObjType("CFBundle");
783                                else if (id == CFDictionaryGetTypeID()) tcl_result->typePtr = Tcl_GetObjType("CFDictionary");
784                                else if (id == CFArrayGetTypeID()) tcl_result->typePtr = Tcl_GetObjType("CFArray");
785                                else tcl_result->typePtr = Tcl_GetObjType("CFType");
786                                tcl_result->internalRep.otherValuePtr = (void*)CFRetain(res);
787                                Tcl_SetObjResult(interp, tcl_result);
788                                if (sig->releaseResult) CFRelease(res);
789                        } else {
790                                tcl_result->typePtr = NULL;
791                                tcl_result->internalRep.otherValuePtr = NULL;
792                        }
793                } else if (strcmp(sig->result, "CFIndex") == 0) {
794                        tcl_result = Tcl_NewIntObj((int)res);
795                        Tcl_SetObjResult(interp, tcl_result);
796                }
797        }
798        } // end TCL_OK
799       
800        for (i = 0; sig->argv[i].kind != END; ++i) {
801                if (sig->argv[i].kind == CFERRORSTR && result == TCL_OK) {
802                        if (*((CFStringRef*)args[i])) {
803                                Tcl_Obj* tcl_result = cfStringToTCLString(*((CFStringRef*)args[i]));
804                                Tcl_SetObjResult(interp, tcl_result);
805                                result = TCL_ERROR;
806                        }
807                        Tcl_Free(args[i]);
808                }
809        }
810       
811        if (args) Tcl_Free((char*)args);
812       
813        return result;
814}
815
816int Cflib_Init(Tcl_Interp *interp)
817{
818        int i;
819        static cfSignature sig[] = {
820                /* CFBundle.h */
821                {
822                        "CFBundleGetMainBundle", CFBundleGetMainBundle, "", "CFType", 0,
823                        { 
824                                { END, NULL, NULL }
825                        }
826                },
827                {
828                        "CFBundleGetBundleWithIdentifier", CFBundleGetBundleWithIdentifier, "", "CFType", 0,
829                        {
830                                { CFTYPE, "CFString", tclObjToCFString },
831                                { END, NULL, NULL }
832                        }
833                },
834                {
835                        "CFBundleGetAllBundles", CFBundleGetAllBundles, "", "CFType", 0,
836                        { 
837                                { END, NULL, NULL }
838                        }
839                },
840                {
841                        "CFBundleCreate", CFBundleCreate, "bundleURL", "CFType", 1,
842                        { 
843                                { LITERAL, NULL, NULL },
844                                { CFTYPE, "CFURL", tclObjToCFURL },
845                                { END, NULL, NULL }
846                        }
847                },
848                {
849                        "CFBundleCreateBundlesFromDirectory", CFBundleCreateBundlesFromDirectory, "directoryURL bundleType", "CFType", 1,
850                        { 
851                                { LITERAL, NULL, NULL },
852                                { CFTYPE, "CFURL", tclObjToCFURL },
853                                { CFTYPE, "CFString", tclObjToCFString },
854                                { END, NULL, NULL }
855                        }
856                },
857                {
858                        "CFBundleCopyBundleURL", CFBundleCopyBundleURL, "bundle", "CFType", 1,
859                        {
860                                { CFTYPE, "CFBundle", tclObjToCFBundle },
861                                { END, NULL, NULL }
862                        }
863                },
864                {
865                        "CFBundleGetValueForInfoDictionaryKey", CFBundleGetValueForInfoDictionaryKey, "bundle key", "CFType", 0,
866                        {
867                                { CFTYPE, "CFBundle", tclObjToCFBundle },
868                                { CFTYPE, "CFString", tclObjToCFString },
869                                { END, NULL, NULL }
870                        }
871                },
872                {
873                        "CFBundleGetInfoDictionary", CFBundleGetInfoDictionary, "bundle", "CFType", 0,
874                        {
875                                { CFTYPE, "CFBundle", tclObjToCFBundle },
876                                { END, NULL, NULL }
877                        }
878                },
879                {
880                        "CFBundleGetLocalInfoDictionary", CFBundleGetLocalInfoDictionary, "bundle", "CFType", 0,
881                        {
882                                { CFTYPE, "CFBundle", tclObjToCFBundle },
883                                { END, NULL, NULL }
884                        }
885                },
886                // CFBundleGetPackageInfo
887                {
888                        "CFBundleGetIdentifier", CFBundleGetIdentifier, "bundle", "CFType", 0,
889                        {
890                                { CFTYPE, "CFBundle", tclObjToCFBundle },
891                                { END, NULL, NULL }
892                        }
893                },
894                {
895                        "CFBundleGetVersionNumber", CFBundleGetVersionNumber, "bundle", "CFIndex", 0,
896                        {
897                                { CFTYPE, "CFBundle", tclObjToCFBundle },
898                                { END, NULL, NULL }
899                        }
900                },
901                {
902                        "CFBundleGetDevelopmentRegion", CFBundleGetDevelopmentRegion, "bundle", "CFType", 0,
903                        {
904                                { CFTYPE, "CFBundle", tclObjToCFBundle },
905                                { END, NULL, NULL }
906                        }
907                },
908                {
909                        "CFBundleCopySupportFilesDirectoryURL", CFBundleCopySupportFilesDirectoryURL, "bundle", "CFType", 1,
910                        {
911                                { CFTYPE, "CFBundle", tclObjToCFBundle },
912                                { END, NULL, NULL }
913                        }
914                },
915                {
916                        "CFBundleCopyResourcesDirectoryURL", CFBundleCopyResourcesDirectoryURL, "bundle", "CFType", 1,
917                        {
918                                { CFTYPE, "CFBundle", tclObjToCFBundle },
919                                { END, NULL, NULL }
920                        }
921                },
922                {
923                        "CFBundleCopyPrivateFrameworksURL", CFBundleCopyPrivateFrameworksURL, "bundle", "CFType", 1,
924                        {
925                                { CFTYPE, "CFBundle", tclObjToCFBundle },
926                                { END, NULL, NULL }
927                        }
928                },
929                {
930                        "CFBundleCopySharedFrameworksURL", CFBundleCopySharedFrameworksURL, "bundle", "CFType", 1,
931                        {
932                                { CFTYPE, "CFBundle", tclObjToCFBundle },
933                                { END, NULL, NULL }
934                        }
935                },
936                {
937                        "CFBundleCopySharedSupportURL", CFBundleCopySharedSupportURL, "bundle", "CFType", 1,
938                        {
939                                { CFTYPE, "CFBundle", tclObjToCFBundle },
940                                { END, NULL, NULL }
941                        }
942                },
943                {
944                        "CFBundleCopyBuiltInPlugInsURL", CFBundleCopyBuiltInPlugInsURL, "bundle", "CFType", 1,
945                        {
946                                { CFTYPE, "CFBundle", tclObjToCFBundle },
947                                { END, NULL, NULL }
948                        }
949                },
950                {
951                        "CFBundleCopyInfoDictionaryInDirectory", CFBundleCopyResourcesDirectoryURL, "bundelURL", "CFType", 1,
952                        {
953                                { CFTYPE, "CFURL", tclObjToCFURL },
954                                { END, NULL, NULL }
955                        }
956                },
957                // CFBundleGetPackageInfoInDirectory
958                {
959                        "CFBundleCopyResourceURL", CFBundleCopyResourceURL, "bundle resourceName resourceType subDirName", "CFType", 1,
960                        {
961                                { CFTYPE, "CFBundle", tclObjToCFBundle },
962                                { CFTYPE, "CFString", tclObjToCFString },
963                                { CFTYPE, "CFString", tclObjToCFString },
964                                { CFTYPE, "CFString", tclObjToCFString },
965                                { END, NULL, NULL }
966                        }
967                },
968                {
969                        "CFBundleCopyResourceURLsOfType", CFBundleCopyResourceURLsOfType, "bundle resourceType subDirName", "CFType", 1,
970                        {
971                                { CFTYPE, "CFBundle", tclObjToCFType },
972                                { CFTYPE, "CFString", tclObjToCFString },
973                                { CFTYPE, "CFString", tclObjToCFString },
974                                { END, NULL, NULL }
975                        }
976                },
977                {
978                        "CFBundleCopyLocalizedString", CFBundleCopyLocalizedString, "bundle key value tableName", "CFType", 1,
979                        {
980                                { CFTYPE, "CFBundle", tclObjToCFBundle },
981                                { CFTYPE, "CFString", tclObjToCFString },
982                                { CFTYPE, "CFString", tclObjToCFString },
983                                { CFTYPE, "CFString", tclObjToCFString },
984                                { END, NULL, NULL }
985                        }
986                },
987                {
988                        "CFBundleCopyResourceURLInDirectory", CFBundleCopyResourceURLInDirectory, "bundleURL resourceName resourceType subDirName", "CFType", 1,
989                        {
990                                { CFTYPE, "CFURL", tclObjToCFURL },
991                                { CFTYPE, "CFString", tclObjToCFString },
992                                { CFTYPE, "CFString", tclObjToCFString },
993                                { CFTYPE, "CFString", tclObjToCFString },
994                                { END, NULL, NULL }
995                        }
996                },
997                {
998                        "CFBundleCopyResourceURLsOfTypeInDirectory", CFBundleCopyResourceURLsOfTypeInDirectory, "bundleURL resourceType subDirName", "CFType", 1,
999                        {
1000                                { CFTYPE, "CFURL", tclObjToCFURL },
1001                                { CFTYPE, "CFString", tclObjToCFString },
1002                                { CFTYPE, "CFString", tclObjToCFString },
1003                                { END, NULL, NULL }
1004                        }
1005                },
1006                {
1007                        "CFBundleCopyBundleLocalizations", CFBundleCopyBundleLocalizations, "bundle", "CFType", 1,
1008                        {
1009                                { CFTYPE, "CFBundle", tclObjToCFBundle },
1010                                { END, NULL, NULL }
1011                        }
1012                },
1013                {
1014                        "CFBundleCopyPreferredLocalizationsFromArray", CFBundleCopyPreferredLocalizationsFromArray, "locArray", "CFType", 1,
1015                        {
1016                                { CFTYPE, "CFArray", tclObjToCFArray },
1017                                { END, NULL, NULL }
1018                        }
1019                },
1020                {
1021                        "CFBundleCopyLocalizationsForPreferences", CFBundleCopyPreferredLocalizationsFromArray, "locArray prefArray", "CFType", 1,
1022                        {
1023                                { CFTYPE, "CFArray", tclObjToCFArray },
1024                                { CFTYPE, "CFArray", tclObjToCFArray },
1025                                { END, NULL, NULL }
1026                        }
1027                },
1028                // CFBundleCopyResourceURLForLocalization
1029                // CFBundleCopyResourceURLsOfTypeForLocalization
1030                // CFBundleCopyInfoDictionaryForURL
1031                // CFBundleCopyLocalizationsForURL
1032
1033                /* CFPropertyList.h */
1034                {
1035                        "CFPropertyListCreateFromXMLData", CFPropertyListCreateFromXMLData, "xmlData mutabilityOption", "CFType", 1,
1036                        {
1037                                { LITERAL, NULL, NULL },
1038                                { CFTYPE, "CFData", tclObjToCFData },
1039                                { CFTYPE, NULL, tclObjToCFMutabilityOption },
1040                                { CFERRORSTR, NULL, NULL }, // xxx: error string
1041                                { END, NULL, NULL }
1042                        }
1043                },
1044                {
1045                        "CFPropertyListCreateXMLData", CFPropertyListCreateXMLData, "propertyList", "CFType", 1,
1046                        {
1047                                { LITERAL, NULL, NULL },
1048                                { CFTYPE, NULL, tclObjToCFPropertyList }, 
1049                                { END, NULL, NULL }
1050                        }
1051                },
1052                {
1053                        "CFPropertyListCreateDeepCopy", CFPropertyListCreateDeepCopy, "propertyList mutabilityOption", "CFType", 1,
1054                        {
1055                                { LITERAL, NULL, NULL },
1056                                { CFTYPE, NULL, tclObjToCFPropertyList },
1057                                { CFTYPE, NULL, tclObjToCFMutabilityOption },
1058                                { END, NULL, NULL }
1059                        }
1060                },
1061                {
1062                        "CFPropertyListIsValid", CFPropertyListIsValid, "propertyList format", "CFIndex", 1,
1063                        {
1064                                { CFTYPE, NULL, tclObjToCFPropertyList },
1065                                { CFTYPE, NULL, tclObjToCFPropertyListFormat },
1066                                { END, NULL, NULL }
1067                        }
1068                },
1069               
1070                // CFPropertyListWriteToStream
1071                // CFPropertyListCreateFromStream
1072               
1073                /* CFArray.h */
1074                // CFArrayCreate
1075                {
1076                        "CFArrayCreateCopy", CFArrayCreateCopy, "theArray", "CFType", 1,
1077                        {
1078                                { LITERAL, NULL, NULL },
1079                                { CFTYPE, "CFArray", NULL },
1080                                { END, NULL, NULL }
1081                        }
1082                },
1083                {
1084                        "CFArrayCreateMutable", CFArrayCreateMutable, "capacity", "CFType", 1,
1085                        {
1086                                { LITERAL, NULL, NULL },
1087                                { CFINDEX, "CFIndex", NULL },
1088                                { LITERAL, NULL, (void*)&kCFTypeArrayCallBacks },       // xxx: func to handle callbacks
1089                                { END, NULL, NULL }
1090                        }
1091                },
1092                {
1093                        "CFArrayCreateMutableCopy", CFArrayCreateMutableCopy, "capacity theArray", "CFType", 1,
1094                        {
1095                                { LITERAL, NULL, NULL },
1096                                { CFINDEX, "CFIndex", NULL },
1097                                { CFTYPE, "CFArray", NULL },
1098                                { END, NULL, NULL }
1099                        }
1100                },
1101                {
1102                        "CFArrayGetCount", CFDictionaryGetCount, "theArray", "CFIndex", 0,
1103                        {
1104                                { CFTYPE, "CFArray", tclObjToCFArray },
1105                                { END, NULL, NULL }
1106                        }
1107                },
1108                {
1109                        "CFArrayGetCountOfValue", CFArrayGetCountOfValue, "theArray start end value", "CFIndex", 0,
1110                        {
1111                                { CFTYPE, "CFArray", tclObjToCFArray },
1112                                { CFINDEX, NULL, NULL },        // xxx: these part of CFRange
1113                                { CFINDEX, NULL, NULL }, 
1114                                { CFTYPE, NULL, tclObjToCFType }, 
1115                                { END, NULL, NULL }
1116                        }
1117                },
1118                {
1119                        "CFArrayContainsValue", CFArrayContainsValue, "theArray start end value", "CFIndex", 0,
1120                        {
1121                                { CFTYPE, "CFArray", tclObjToCFArray },
1122                                { CFINDEX, NULL, NULL },        // xxx: these part of CFRange
1123                                { CFINDEX, NULL, NULL }, 
1124                                { CFTYPE, NULL, tclObjToCFType }, 
1125                                { END, NULL, NULL }
1126                        }
1127                },
1128                {
1129                        "CFArrayGetValueAtIndex", CFArrayGetValueAtIndex, "theArray index", "CFType", 0,
1130                        {
1131                                { CFTYPE, "CFArray", tclObjToCFArray },
1132                                { CFINDEX, NULL, NULL }, 
1133                                { END, NULL, NULL }
1134                        }
1135                },
1136                // CFArrayGetValues
1137                // CFArrayApplyFunction
1138                {
1139                        "CFArrayGetFirstIndexOfValue", CFArrayGetFirstIndexOfValue, "theArray start end value", "CFIndex", 0,
1140                        {
1141                                { CFTYPE, "CFArray", tclObjToCFArray },
1142                                { CFINDEX, NULL, NULL },        // xxx: these part of CFRange
1143                                { CFINDEX, NULL, NULL }, 
1144                                { CFTYPE, NULL, tclObjToCFType }, 
1145                                { END, NULL, NULL }
1146                        }
1147                },
1148                {
1149                        "CFArrayGetLastIndexOfValue", CFArrayGetLastIndexOfValue, "theArray start end value", "CFIndex", 0,
1150                        {
1151                                { CFTYPE, "CFArray", tclObjToCFArray },
1152                                { CFINDEX, NULL, NULL },        // xxx: these part of CFRange
1153                                { CFINDEX, NULL, NULL }, 
1154                                { CFTYPE, NULL, tclObjToCFType }, 
1155                                { END, NULL, NULL }
1156                        }
1157                },
1158                // CFArrayBSearchValues
1159                {
1160                        "CFArrayAppendValue", CFArrayAppendValue, "theArray index", "void", 0,
1161                        {
1162                                { CFTYPE, "CFArray", tclObjToCFArray },
1163                                { CFTYPE, NULL, tclObjToCFType }, 
1164                                { END, NULL, NULL }
1165                        }
1166                },
1167                {
1168                        "CFArrayInsertValueAtIndex", CFArrayInsertValueAtIndex, "theArray index value", "void", 0,
1169                        {
1170                                { CFTYPE, "CFArray", tclObjToCFArray },
1171                                { CFINDEX, NULL, NULL },
1172                                { CFTYPE, NULL, tclObjToCFType }, 
1173                                { END, NULL, NULL }
1174                        }
1175                },
1176                {
1177                        "CFArraySetValueAtIndex", CFArraySetValueAtIndex, "theArray index value", "void", 0,
1178                        {
1179                                { CFTYPE, "CFArray", tclObjToCFArray },
1180                                { CFINDEX, NULL, NULL },
1181                                { CFTYPE, NULL, tclObjToCFType }, 
1182                                { END, NULL, NULL }
1183                        }
1184                },
1185                {
1186                        "CFArrayRemoveValueAtIndex", CFArrayRemoveValueAtIndex, "theArray index", "void", 0,
1187                        {
1188                                { CFTYPE, "CFArray", tclObjToCFArray },
1189                                { CFINDEX, NULL, NULL },
1190                                { END, NULL, NULL }
1191                        }
1192                },
1193                {
1194                        "CFArrayRemoveAllValues", CFArrayRemoveAllValues, "theArray", "void", 0,
1195                        {
1196                                { CFTYPE, "CFArray", tclObjToCFArray },
1197                                { END, NULL, NULL }
1198                        }
1199                },
1200                // CFArrayReplaceValues
1201                {
1202                        "CFArrayExchangeValuesAtIndices", CFArrayExchangeValuesAtIndices, "theArray idx1 idx2", "void", 0,
1203                        {
1204                                { CFTYPE, "CFArray", tclObjToCFArray },
1205                                { CFINDEX, NULL, NULL },
1206                                { CFINDEX, NULL, NULL },
1207                                { END, NULL, NULL }
1208                        }
1209                },
1210                // CFArraySortValues
1211                {
1212                        "CFArrayAppendArray", CFArrayAppendArray, "theArray otherArray start end", "void", 0,
1213                        {
1214                                { CFTYPE, "CFArray", tclObjToCFArray },
1215                                { CFTYPE, "CFArray", tclObjToCFArray },
1216                                { CFINDEX, NULL, NULL },
1217                                { CFINDEX, NULL, NULL },
1218                                { END, NULL, NULL }
1219                        }
1220                },
1221               
1222               
1223                /* CFDictionary.h */
1224                // CFDictionaryCreate
1225                {
1226                        "CFDictionaryCreateCopy", CFDictionaryCreateCopy, "theDict", "CFType", 1,
1227                        {
1228                                { LITERAL, NULL, NULL },
1229                                { CFTYPE, "CFDictionary", NULL },
1230                                { END, NULL, NULL }
1231                        }
1232                },
1233                {
1234                        "CFDictionaryCreateMutable", CFDictionaryCreateMutable, "capacity", "CFType", 1,
1235                        {
1236                                { LITERAL, NULL, NULL },
1237                                { CFINDEX, "CFIndex", NULL },
1238                                { LITERAL, NULL, (void*)&kCFTypeDictionaryKeyCallBacks },       // xxx: func to handle callbacks
1239                                { LITERAL, NULL, (void*)&kCFTypeDictionaryValueCallBacks }, // xxx: func to handle callbacks
1240                                { END, NULL, NULL }
1241                        }
1242                },
1243                {
1244                        "CFDictionaryCreateMutableCopy", CFDictionaryCreateMutableCopy, "capacity theDict", "CFType", 1,
1245                        {
1246                                { LITERAL, NULL, NULL },
1247                                { CFINDEX, "CFIndex", NULL },
1248                                { CFTYPE, "CFDictionary", NULL },
1249                                { END, NULL, NULL }
1250                        }
1251                },
1252                {
1253                        "CFDictionaryGetCount", CFDictionaryGetCount, "dictionary", "CFIndex", 0,
1254                        {
1255                                { CFTYPE, "CFDictionary", tclObjToCFDictionary },
1256                                { END, NULL, NULL }
1257                        }
1258                },
1259                {
1260                        "CFDictionaryGetCountOfKey", CFDictionaryGetCountOfKey, "dictionary key", "CFIndex", 0,
1261                        {
1262                                { CFTYPE, "CFDictionary", tclObjToCFDictionary },
1263                                { CFTYPE, NULL, tclObjToCFType }, 
1264                                { END, NULL, NULL }
1265                        }
1266                },
1267                {
1268                        "CFDictionaryGetCountOfValue", CFDictionaryGetCountOfValue, "dictionary value", "CFIndex", 0,
1269                        {
1270                                { CFTYPE, "CFDictionary", tclObjToCFDictionary },
1271                                { CFTYPE, NULL, tclObjToCFType }, 
1272                                { END, NULL, NULL }
1273                        }
1274                },
1275                {
1276                        "CFDictionaryContainsKey", CFDictionaryContainsKey, "dictionary key", "CFIndex", 0,
1277                        {
1278                                { CFTYPE, "CFDictionary", tclObjToCFDictionary },
1279                                { CFTYPE, NULL, tclObjToCFType }, 
1280                                { END, NULL, NULL }
1281                        }
1282                },
1283                {
1284                        "CFDictionaryContainsValue", CFDictionaryContainsValue, "dictionary value", "CFIndex", 0,
1285                        {
1286                                { CFTYPE, "CFDictionary", tclObjToCFDictionary },
1287                                { CFTYPE, NULL, tclObjToCFType }, 
1288                                { END, NULL, NULL }
1289                        }
1290                },
1291                {
1292                        "CFDictionaryGetValue", CFDictionaryGetValue, "dictionary key", "CFType", 0,
1293                        {
1294                                { CFTYPE, "CFDictionary", tclObjToCFDictionary },
1295                                { CFTYPE, NULL, tclObjToCFType }, 
1296                                { END, NULL, NULL }
1297                        }
1298                },
1299                // CFDictionaryGetValueIfPresent
1300                // CFDictionaryGetKeysAndValues
1301                // CFDictionaryApplyFunction
1302                {
1303                        "CFDictionaryAddValue", CFDictionaryAddValue, "dictionary key value", "void", 0,
1304                        {
1305                                { CFTYPE, "CFDictionary", tclObjToCFDictionary },
1306                                { CFTYPE, NULL, tclObjToCFType }, 
1307                                { CFTYPE, NULL, tclObjToCFType }, 
1308                                { END, NULL, NULL }
1309                        }
1310                },
1311                {
1312                        "CFDictionarySetValue", CFDictionarySetValue, "dictionary key value", "void", 0,
1313                        {
1314                                { CFTYPE, "CFDictionary", tclObjToCFDictionary },
1315                                { CFTYPE, NULL, tclObjToCFType }, 
1316                                { CFTYPE, NULL, tclObjToCFType }, 
1317                                { END, NULL, NULL }
1318                        }
1319                },
1320                {
1321                        "CFDictionaryReplaceValue", CFDictionaryReplaceValue, "dictionary key value", "void", 0,
1322                        {
1323                                { CFTYPE, "CFDictionary", tclObjToCFDictionary },
1324                                { CFTYPE, NULL, tclObjToCFType }, 
1325                                { CFTYPE, NULL, tclObjToCFType }, 
1326                                { END, NULL, NULL }
1327                        }
1328                },
1329                {
1330                        "CFDictionaryRemoveValue", CFDictionaryRemoveValue, "dictionary key", "void", 0,
1331                        {
1332                                { CFTYPE, "CFDictionary", tclObjToCFDictionary },
1333                                { CFTYPE, NULL, tclObjToCFType }, 
1334                                { END, NULL, NULL }
1335                        }
1336                },
1337                {
1338                        "CFDictionaryRemoveAllValues", CFDictionaryRemoveAllValues, "dictionary", "void", 0,
1339                        {
1340                                { CFTYPE, "CFDictionary", tclObjToCFDictionary },
1341                                { END, NULL, NULL }
1342                        }
1343                },
1344                {
1345                        NULL, NULL, NULL, NULL, 0, { { END, NULL, NULL } }
1346                }
1347        };
1348
1349        if(Tcl_InitStubs(interp, "8.3", 0) == NULL)
1350                return TCL_ERROR;
1351
1352        for (i = 0; sig[i].name != NULL; ++i) {
1353                Tcl_CreateObjCommand(interp, sig[i].name, tclCFFunc, &sig[i], NULL);
1354        }
1355
1356        cfTypeRegister();
1357        cfStringRegister();
1358        cfNumberRegister();
1359        cfDataRegister();
1360        cfBundleRegister();
1361        cfURLRegister();
1362        cfDictionaryRegister();
1363        cfArrayRegister();
1364       
1365        Tcl_CreateObjCommand(interp, "CFGetTypeID", tclCFGetTypeID, NULL, NULL);
1366        Tcl_CreateObjCommand(interp, "CFStringGetTypeID", tclCFGetTypeID2, (void*)CFStringGetTypeID(), NULL);
1367        Tcl_CreateObjCommand(interp, "CFNumberCreate", tclCFNumberCreate, NULL, NULL);
1368        Tcl_CreateObjCommand(interp, "CFNumberGetTypeID", tclCFGetTypeID2, (void*)CFNumberGetTypeID(), NULL);
1369        Tcl_CreateObjCommand(interp, "CFURLGetTypeID", tclCFGetTypeID2, (void*)CFURLGetTypeID(), NULL);
1370        Tcl_CreateObjCommand(interp, "CFBundleGetTypeID", tclCFGetTypeID2, (void*)CFBundleGetTypeID(), NULL);
1371        Tcl_CreateObjCommand(interp, "CFDictionaryGetTypeID", tclCFGetTypeID2, (void*)CFDictionaryGetTypeID(), NULL);
1372        Tcl_CreateObjCommand(interp, "CFArrayGetTypeID", tclCFGetTypeID2, (void*)CFArrayGetTypeID(), NULL);
1373        //Tcl_CreateObjCommand(interp, "CFBundleCreateBundlesFromDirectory", tclCFBundleCreateBundlesFromDirectory, NULL, NULL);
1374
1375        if(Tcl_PkgProvide(interp, "CFLib", "1.0") != TCL_OK)
1376                return TCL_ERROR;
1377        return TCL_OK;
1378}
Note: See TracBrowser for help on using the repository browser.