I am trying to develop a very simple Core Foundation program that uses the function CFStringCreateArrayBySeparatingStrings()
. However, it does not work as I expect.
The program is the following:
#include <stdio.h>
#include <CoreFoundation/CoreFoundation.h>
void applier(const void *value, void *context) {
printf("%s\n", CFStringGetCStringPtr((CFStringRef)value, CFStringGetSystemEncoding()));
}
int main(int argc, const char * argv[]) {
CFStringRef stringToParse = CFSTR("John Pappas,Mary Foo,Peter Pan");
CFStringRef separatorString = CFSTR(",");
CFArrayRef array = CFStringCreateArrayBySeparatingStrings(kCFAllocatorDefault,
stringToParse,
separatorString);
CFArrayApplyFunction(array,
CFRangeMake((CFIndex)0,
(CFIndex)CFArrayGetCount(array)),
applier,
NULL);
CFRelease(array);
return 0;
}
When I run the program, the output is the following:
John Pappas
(null)
(null)
Program ended with exit code: 0
I don't understand why the 2nd and 3rd values are not printed as expected.
When trying to debug the program, before exiting, the debugger shows that the array does have 3 elements, but the types of its values are not the same type for all. Here is what I am looking at when I stop at the break point with the debugger:
Also, by looking at the debugger, I am a little bit surprised that the elements of the array have values of types that involve NS
. I thought that I was using Core Foundation
and not Foundation
framework. So, I expected the values to have types like CFStringRef
.
Can you help me make this program run successfully using Core Foundation API?
In response to a related question I dived into the documentation. Here's what I found:
From Foundation Release Notes for OS X v10.10 and iOS v8
NS/CFStrings now use a “tagged pointer” format where the string contents are stored in the pointer directly in some cases. This happens automatically thru the existing APIs that create strings, without need to use any new API.
This change will break any code which treats NS/CFStrings objects as pointers
Indeed, CFStringCreateArrayBySeparatingStrings
returns NSTaggedPointerString
s.
From the documentation of CFStringGetCStringPtr
:
This function either returns the requested pointer immediately, with no memory allocations and no copying, in constant time, or returns NULL. If the latter is the result, call an alternative function such as the CFStringGetCString(::::) function to extract the characters.
Whether or not this function returns a valid pointer or NULL depends on many factors, all of which depend on how the string was created and its properties. In addition, the function result might change between different releases and on different platforms. So do not count on receiving a non-NULL result from this function under any circumstances.
CFStringGetCStringPtr
can't return a pointer for a NSTaggedPointerString
. Use CFStringGetCString
instead of CFStringGetCStringPtr
or try CFStringGetCStringPtr
and if the result is NULL
then call CFStringGetCString
.