Working With Binary Data
This article contains code examples of common tasks that apply to immutable and mutable data objects,
Creating Data Objects From Raw Bytes
Generally, you create a data object from raw bytes using the
CFDataCreateMutable functions for immutable and mutable data objects respectively. These functions make a copy of the bytes you pass as an argument. The copied bytes are owned by the data object and are freed when the data object is released. It is your responsibility to free the original bytes.
In contrast, the bytes are not copied when you create a data object using
CFDataCreateWithBytesNoCopy with a deallocator argument which is not
kCFAllocatorNull. Instead, the data object takes ownership of the bytes passed in as an argument and frees them when the object is released. For this reason, the bytes you pass to this function must have been allocated using the allocator you provide as the deallocator argument.
If you prefer that the bytes not be copied or freed when the object is released, you can create a no-copy, no-free
CFData object using the
CFDataCreateWithBytesNoCopy function and passing
kCFAllocatorNull as the deallocator argument, as in:
CFDataRef dictData = CFDataCreateWithBytesNoCopy(
NULL, bytes, length, kCFAllocatorNull);
Accessing and Comparing Bytes
The three basic
CFData functions are
CFDataGetBytesPtr function returns a pointer to the bytes contained in the data object. The
CFDataGetBytes function puts the bytes in a supplied buffer. The
CFDataGetLength function returns the number of bytes contained in the data object.
For example, the following code fragment initializes a data object,
myData, with the string
myString. It then uses
CFDataGetBytesPtr to return the bytes as a pointer.
const UInt8 *myString = "Test string.";
CFDataRef myData =
CFDataCreateWithBytesNoCopy(NULL, myString, strlen(myString), kCFAllocatorNull);
const UInt8 *ptr = CFDataGetBytePtr(myData);
To create a data object that contains a subset of the bytes in another data object, pass a value for the range when calling the
CFDataGetBytes function. For example, the following code fragment initializes a data object,
data2, to contain a subrange of
unsigned char aBuffer;
const UInt8 *strPtr = "ABCDEFG";
CFDataRef data1 =
CFDataCreateWithBytesNoCopy(NULL, strPtr, strlen(strPtr), kCFAllocatorNull);
CFDataGetBytes(data1, CFRangeMake(2, 4), aBuffer);
CFDataRef data2 = CFDataCreate(NULL, aBuffer, 20);
To determine whether two data objects are equal, use the
CFEqual function, which performs a byte-for-byte comparison.
Copying Data Objects
Data objects make it convenient to convert between efficient, read-only data objects and mutable data objects. You use the
CFDataCreateMutableCopy functions to get an immutable and mutable copy of an existing data object respectively.