Search code examples
objective-cobjective-c++core-foundation

Casting a basic CFTypeRef to a more specific CoreFoundation type


Is there a simple way to convert a CTypeRef to a specific CoreFoundation type? I'm not looking to cast inline as (CFStringRef)myObjectRef but would like to create a helper method to do this for me for all CoreFoundation types.

I know it's possible to use something like CFGetTypeID(myObjectRef) == CFStringGetTypeID() to find out whether a CTypeRef is a CFString. However creating a single method to do this could become very verbose and have a lot of if statements.

Is building out a method with a bunch of if statements against CFGetTypeID() the only way? Or is there a simpler way to do this?

UPDATE: with example

I'd like to make a helper function to work with some legacy code I can't change. Currently it produces one of CFDictionaryRef, CFStringRef or CFURLRef as a return value provided as a CTypeRef. I'm currently working around this by running CFGetTypeID() on the returned value but this isn't ideal. Rather than having C-style casts all over the place, I'd rather have a CastToCF() helper which handles this for me. This would help make testing easier in the future as well.

P.S. I'm not worried about mutable types.


Solution

  • there's no obvious point in doing this. a c style cast is not like other languages - it is a typecast which the address on the left will be identical to the address on the right. cftypes will not throw or return null if you do a bad cast (unlike other languages). iow, it's merely a decoration for you to specify a type, and a c compiler will assume your cast is valid.

    or perhaps you can provide a better example of how you would use this, if that did not help.

    Update

    ok. since you tagged it objc++, i'd just create a helper class which had plenty of diagnostics and did all the noisy conversions (minimal illustration):

    class t_helper {
    public:
        t_helper(CFTypeRef cf) : d_cf(cf), d_type(CFGetTypeID(cf)) { assert(this->d_cf); }
        ~t_helper() {}
    
        /* type info */
        bool isString() const { return CFStringGetTypeID() == this->type(); }
        CFStringRef string() { assert(this->isString()); return this->cf_cast<CFStringRef>(); }
    
        bool isDictionary() const { return CFDictionaryGetTypeID() == this->type(); }
        CFDictionaryRef dictionary() { assert(this->isDictionary()); return this->cf_cast<CFDictionaryRef>(); }
    
     ...
    
        /* and a trivial example of an operation */
        void appendMutableCopyToArray(CFMutableArrayRef array) {
            if (this->isString()) {
                CFMutableStringRef cp(CFStringCreateMutableCopy(0,0,this->string()));
                CFArrayAppendValue(array, cp);
                CFRelease(cp);
            }
            ...
        }
    
     ...
    
    private:
        template < typename T > T cf_cast() { return reinterpret_cast<T>(this->d_cf); }
        const CFTypeID type() const { return this->d_type; }
    private:
        CFTypeRef d_cf;
        const CFTypeID d_type;
    };
    

    that's about as accurate as i can get get without a really specific example of the program you are dealing with.