Accessing the Contents of String Objects
The two essential properties of CFString objects are an array of Unicode characters and a count of those characters. Several CFString functions not only obtain those properties, particularly the characters, but perform conversions to almost any desired format.
The CFStringGetBytes
function, which copies the contents of a CFString object into a client-supplied byte buffer, is described in The Basic Conversion Routines. It is described there instead of in this section because it has features that make it particularly suitable for encoding conversions.
Getting the Contents as a C String
You may need to use programming interfaces that require C strings for some of their parameters. For performance reasons, a common strategy for accessing the contents of CFStrings as a C string is to first try to get a pointer of the appropriate type to these strings and, if that fails, to copy the contents into a local buffer. Listing 1 illustrates this strategy for C strings using the CFStringGetCStringPtr
and CFStringGetCString
functions.
Listing 1 Accessing CFString contents as a C string
CFStringRef str; |
CFRange rangeToProcess; |
const char *bytes; |
str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman); |
bytes = CFStringGetCStringPtr(str, kCFStringEncodingMacRoman); |
if (bytes == NULL) { |
char localBuffer[10]; |
Boolean success; |
success = CFStringGetCString(str, localBuffer, 10, kCFStringEncodingMacRoman); |
} |
These functions allow you to specify the encoding that the Unicode characters should be converted to. The functions that end with “Ptr” either return the desired pointer quickly, in constant time, or they return NULL
. If the latter is the case, you should use CFStringGetCString
.
The buffer for the CFStringGetCString
functions can either be on the stack or a piece of allocated memory. These functions might still fail to get the characters, but that only happens in two circumstances: the conversion from the UniChar
contents of CFString to the specified encoding fails or the buffer is too small. If you need a copy of the character buffer or if the code in question is not that performance-sensitive, you could simply call the CFStringGetCString
function without even attempting to get the pointer first.
Getting the Contents as Unicode Strings
String objects offer a pair of functions similar to those for C strings for accessing the contents of a CFString as a 16-bit Unicode buffer: CFStringGetCharactersPtr
and CFStringGetCharacters
. The typical usage of these functions is also identical: you first optionally try to get a pointer to the characters and, if that fails, you try to copy the characters to a buffer you provide. These functions are different, however, in that they require a parameter specifying the length of the string.
Listing 2 illustrates the common strategy for using these functions.
Listing 2 Accessing CFString contents as Unicode characters
CFStringRef str; |
const UniChar *chars; |
str = CFStringCreateWithCString(NULL, "Hello World", kCFStringEncodingMacRoman); |
chars = CFStringGetCharactersPtr(str); |
if (chars == NULL) { |
CFIndex length = CFStringGetLength(str); |
UniChar *buffer = malloc(length * sizeof(UniChar)); |
CFStringGetCharacters(str, CFRangeMake(0, length), buffer); |
// Process the characters... |
free(buffer); |
} |
This example shows an allocated buffer (malloc
) rather than a stack buffer. You can use one or the other. Because you need to know the size of the buffer for the CFStringGetCharacters
function, allocating memory is easier to do but is less efficient. If you allocate memory for the characters you must, of course, free the buffer when you no longer need it.
Character Processing
Sometimes you might want to receive the contents of a CFString not as an entire block of characters but one Unicode character at a time. Perhaps you might be looking for a particular character or sequence of characters, such as special control characters indicating the start and end of a “record.” String objects give you three ways to process Unicode characters.
The first way is to use the CFStringGetCharacters
function described in Getting the Contents as Unicode Strings to copy the characters to a local buffer and then cycle through the characters in the buffer. But this technique can be expensive memory-wise, especially if a large number of characters is involved.
The second way to access characters one at a time is to use the CFStringGetCharacterAtIndex
function, as Listing 3 illustrates.
Listing 3 Getting a character at a time
CFIndex length, i; |
UniChar uchar; |
CFStringRef str; |
str = CFStringCreateWithCString(NULL, "Hello World", kCFStringEncodingMacRoman); |
length = CFStringGetLength(str); |
for (i=0; i < length; i++) { |
uchar = CFStringGetCharacterAtIndex(str, i); |
// Process character.... |
} |
Although this function does not require a large chunk of memory to hold a block of characters, using it in a loop can be inefficient. For such cases, use the CFStringGetCharacters
function instead.
The third technique for character processing, exemplified in Listing 4, combines the convenience of one-at-a-time character access with the efficiency of bulk access. The in-line functions CFStringInitInlineBuffer
and CFStringGetCharacterFromInlineBuffer
give fast access to the contents of a string when you are doing sequential character processing. To use this programming interface, call the CFStringInitInlineBuffer
function with a CFStringInlineBuffer
structure (on the stack, typically) and a range of the CFString’s characters. Then call CFStringGetCharacterFromInlineBuffer
as many times as you want using an index into that range relative to the start of the range. Because these are in-line functions they access the CFString object only periodically to fill the in-line buffer.
Listing 4 Processing characters in an in-line buffer
CFStringRef str; |
CFStringInlineBuffer inlineBuffer;CFIndex length;CFIndex cnt; |
str = CFStringCreateWithCString(NULL, "Hello World", kCFStringEncodingMacRoman); |
length = CFStringGetLength(str) |
CFStringInitInlineBuffer(str, &inlineBuffer, CFRangeMake(0, length)); |
for (cnt = 0; cnt < length; cnt++) { |
UniChar ch = CFStringGetCharacterFromInlineBuffer(&inlineBuffer, cnt); |
// Process character... |
} |
Copyright © 2003, 2014 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2014-02-11