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

Last change on this file since 2611 was 2611, checked in by landonf (Landon Fuller), 17 years ago

Build Pextlib (and CFLib, if enabled) using the Tcl stub library.
This will fix the bus error issues with multiple Tcl installations.

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