The MPArray is an opaque structure that is extremely useful for acting as a list of objects. Objects can either be MPTypes (most convenient) where you would use the default array callbacks. However, you can store any void * pointer in the array, provided that you specify callbacks for retain, release, and description copy.
Functions by Task
Creating an Array
Examining an Array
MPArrayCount
MPArrayValueAtIndex
Modifying an Array
MPArrayAppendValue
MPArrayDequeue
MPArrayEnqueue
MPArrayInsertValueAtIndex
MPArrayRemoveValueAtIndex
MPArraySortValues
MPArraySortValuesInRange
MPArraySwapIndexes
Enumerating an Array
MPArrayCreateEnumerator
MPArrayEnumeratorNext
Constants
MPArraySortingOptions
kMPArraySortDefault
kMPArraySortDescending
kMPArraySortStable
Functions
MPArrayAppendValue
Adds the given value to the end of the specified array.
void MPArrayAppendValue(
MPArrayRef array,
void * value
);
Parameters
array
The array to add the value to. This must be a valid MPArray.
value
The value to be added to the array. This can either be an MPType (such as MPStringRef, etc.), or it can be any void * pointer. When this value is added, it is retained using the array’s retain callback (if provided).
Examples
Creates a string to add to an array (assume it was created earlier in the code). It should be noted that you cannot call release on an object until after it has been added to the array. However it is safe to call MPRelease on the object after adding it to the array since the array will retain it.
MPStringRef myString = MPStringCreateWithCString("Hello world!");
MPArrayAppendValue(myArray, myString);
MPRelease(myString);
MPArrayCount
Returns the number of items in the array.
size_t MPArrayCount(
MPArrayRef array
);
Parameters
array
The array for which you wish to get the number of elements in.
Return Value
The number of items in the array.
Examples
MPArrayRef array = MPAutorelease(MPArrayCreate(&kMPTypeArrayCallbacks));
MPArrayAppendValue(array, MPAutorelease(MPStringCreateWithCString("Matthew")));
MPArrayAppendValue(array, MPAutorelease(MPStringCreateWithCString("Kelly")));
// This will print "2" to the screen.
printf("%u\n", MPArrayCount(array));
MPArrayCreate
Creates an instance of MPArray with the given set of callbacks.
MPArrayRef MPArrayCreate(
MPArrayCallBacks * callbacks
);
Parameters
callbacks
The callbacks are functions that are called when retaining, releasing, and getting the description of objects added to the array. If your array is only going to contain MPTypes (such as MPStringRef, MPNumberRef, etc), then you should just pass in &kMPTypeArrayCallbacks which by default specifies MPRetain for retaining, MPRelease for releasing, and MPCopyDescription for description copying. If you are not using MPTypes, then you will need to provide your own set of callbacks. Specifying NULL for any of the callbacks means that that callback is ignored (no retaining, no releasing, etc).
Return Value
An instance of MPArray. The creation follows the create rule, which is that any function in the form MPTypeCreate returns an object that you are responsible for calling MPRelease on when you are finished.
Examples
Creating an array is really easy. The following shows how you would create an array to hold MPTypes.
MPArray myNewArray = MPArrayCreate(&kMPTypeArrayCallbacks);
This example shows how you might use custom callbacks to create an MPArray to store C-strings.
void example_array_create_custom_callbacks(void)
{
// Create the callbacks struct. I am going to duplicate the string when
// retaining, and free it when releasing.
MPArrayCallBacks customCallbacks;
customCallbacks.retain = (MPAllocatorRetainCallBack)strdup;
customCallbacks.release = (MPAllocatorReleaseCallBack)free;
customCallbacks.copyDescription = NULL;
// Create the array and add some values.
MPArrayRef array = MPArrayCreate(&customCallbacks);
MPArrayAppendValue(array, "Chicago");
MPArrayAppendValue(array, "Wheaton");
MPArrayAppendValue(array, "Boston");
// Grab some of the values and print them to screen.
char * firstCity = MPArrayValueAtIndex(array, 0);
char * secondCity = MPArrayValueAtIndex(array, 1);
printf("%s is a suburb of %s.", secondCity, firstCity);
// Clean-up the array (and consequently all duplicated strings).
MPRelease(array);
}
MPArrayCreateEnumerator
Returns an array enumerator object for enumerating through the elements of an array.
MPArrayEnumeratorRef MPArrayCreateEnumerator(
MPArrayRef array,
_Bool reverse
);
Parameters
array
The array whose elements you wish to enumerate through.
reverse
Specify 1 if the enumerator should start from the end (last index) and go to the beginning (first index), instead of the default beginning to end (if you passed in a value of 0).
Return Value
A new instance of MPArrayEnumeratorRef. This follows the create rule, so you need to release it once you are finished.
Examples
This is actually two examples in one. It shows how to create an enumerator to go either front to back, or back to front.
void example_array_enumerate(void)
{
// Create an array and enqueue some stuff.
MPArrayRef array = MPAutorelease(MPArrayCreate(&kMPTypeArrayCallbacks));
MPArrayEnqueue(array, MPAutorelease(MPStringCreateWithCString("VW")));
MPArrayEnqueue(array, MPAutorelease(MPStringCreateWithCString("Audi")));
MPArrayEnqueue(array, MPAutorelease(MPStringCreateWithCString("Honda")));
MPArrayEnqueue(array, MPAutorelease(MPStringCreateWithCString("Porsche")));
// Get an enumerator, and print each string to the screen from front to back.
// This should print "VW", "Audi", "Honda", "Porsche".
MPArrayEnumeratorRef enumForward = MPAutorelease(MPArrayCreateEnumerator(array, 0));
MPStringRef myString = NULL;
while (myString = MPArrayEnumeratorNext(enumForward))
MPShow(myString);
// Get another enumerator, and print each string to the screen from back to front.
// This should print "Porsche", "Honda", "Audi", "VW".
MPArrayEnumeratorRef enumBack = MPAutorelease(MPArrayCreateEnumerator(array, 1));
myString = NULL;
while (myString = MPArrayEnumeratorNext(enumBack))
MPShow(myString);
}
MPArrayDequeue
A convenience function that treats the array like a queue, removing the value at the front of the array and returning it.
void * MPArrayDequeue(
MPArrayRef array
);
Parameters
array
The array you wish to remove the first item from.
Return Value
The value at the front of the array. This value is retained before returning it, so you are responsible for releasing it when you are finished.
Examples
Add some values and then dequeue them.
void example_array_dequeue(void)
{
// Create an array with some stuff in it.
MPArrayRef array = MPAutorelease(MPArrayCreate(&kMPTypeArrayCallbacks));
MPArrayAppendValue(array, MPAutorelease(MPStringCreateWithCString("iMovie")));
MPArrayAppendValue(array, MPAutorelease(MPStringCreateWithCString("iPhoto")));
MPArrayAppendValue(array, MPAutorelease(MPStringCreateWithCString("iDVD")));
// This will print "iMovie", "iPhoto", and "iDVD" to the screen in that order.
MPShow(MPAutorelease(MPArrayDequeue(array)));
MPShow(MPAutorelease(MPArrayDequeue(array)));
MPShow(MPAutorelease(MPArrayDequeue(array)));
}
MPArrayEnqueue
A convenience function that treats the array like a queue, adding the given value to the end of the array. This method is exactly the same as MPArrayAppendValue.
void MPArrayEnqueue(
MPArrayRef array,
void * value
);
Parameters
array
The array you wish to add the value to.
value
The value you wish to add to the array. This value will be retained when added.
Examples
Simple queue setup.
void example_array_enqueue(void)
{
// Create an array and enqueue some stuff.
MPArrayRef array = MPAutorelease(MPArrayCreate(&kMPTypeArrayCallbacks));
MPArrayEnqueue(array, MPAutorelease(MPStringCreateWithCString("iMovie")));
MPArrayEnqueue(array, MPAutorelease(MPStringCreateWithCString("iPhoto")));
MPArrayEnqueue(array, MPAutorelease(MPStringCreateWithCString("iDVD")));
// Print the contents of the array to screen.
MPShow(array);
}
MPArrayEnumeratorNext
Returns the next value in an array that the given enumerator was created from.
void * MPArrayEnumeratorNext(
MPArrayEnumeratorRef enumerator
);
Parameters
enumerator
The enumerator you wish to retrieve the next value from.
Return Value
Returns the next value specified by the enumerator. When you create an array enumerator using MPArrayCreateEnumerator, the returned enumerator knows which array to get the value from. So when you call MPArrayEnumeratorNext, the enumerator knows exactly while value to return.
Examples
See the examples for MPArrayCreateEnumerator.
MPArrayInsertValueAtIndex
Inserts the given value into the specified array at the given index (not after it).
void MPArrayInsertValueAtIndex(
MPArrayRef array,
unsigned index,
void * value
);
Parameters
array
The array to insert the value into. This must be a valid MPArray.
index
The index to insert the value at, not before. If you specify an index which is equal to the count of objects in the array, then it adds the value at the end of the array. Any indexes after that will cause your program to exit.
value
The value to be inserted into the array. This can either be an MPType (such as MPStringRef, etc.), or it can be any void * pointer. When this value is inserted, it is retained using the array’s retain callback (if provided).
Examples
Inserting a few different values at different indexes.
// Assume myArray starts out with elements ["Leslie", "Brad"]
// Now create a string and insert it at the beginning. After inserting,
// our array will be the following: ["Jon", "Leslie", "Brad"]
MPStringRef jon = MPStringCreateWithCString("Jon");
MPArrayInsertValueAtIndex(myArray, 0, jon);
MPRelease(jon);
// Create a string to add to the end. After inserting, our array will be:
// ["Jon", "Leslie", "Brad", "Kathy"]
MPStringRef kathy = MPStringCreateWithCString("Kathy");
MPArrayInsertValueAtIndex(myArray, MPArrayCount(myArray), kathy);
MPRelease(kathy);
MPArrayRemoveValueAtIndex
Removes the value at the given index from the array.
void MPArrayRemoveValueAtIndex(
MPArrayRef array,
unsigned index
);
Parameters
array
The array to remove the value from.
index
The index specifying which value of the array to remove. If the index is out of the bounds of the array, then your program will exit with an error.
Discussion
When the value is removed, it is released with either your provided custom callback for release or the default release function (MPRelease).
Examples
Sample code for creating an array with some strings, and then removing one.
// Create an array containing ["Matthew", "Kelly"].
MPArrayRef array = MPAutorelease(MPArrayCreate(&kMPTypeArrayCallbacks));
MPArrayAppendValue(array, MPAutorelease(MPStringCreateWithCString("Matthew")));
MPArrayAppendValue(array, MPAutorelease(MPStringCreateWithCString("Kelly")));
// This will print "2" to the screen.
printf("%u\n", MPArrayCount(array));
// Remove the first index, now our array contains ["Kelly"].
MPArrayRemoveValueAtIndex(array, 0);
// This will print "1" to the screen.
printf("%u\n", MPArrayCount(array));
MPArraySortValues
Sorts all of the items in the array using the given comparator function and options.
void MPArraySortValues(
MPArrayRef array,
MPArraySortingOptions options,
MPComparatorFunction comparator
);
Parameters
array
The array for whose values you wish to sort.
options
A bitset determining how to sort the array. The options are described in Constants section. Multiple options can be appended together using the C bitwise OR operator.
comparator
This is a function of the type:
typedef int (*MPComparatorFunction)(const void *val1, const void *val2);
This function is called each time two values in the array need to be compared. The way the function should operate is very similar to the C qsort function. If the val1 is less than val2, then return a number less than 0. If the two are equal, then return 0. And if val1 is greater than val2, then return any number greater than 1.
Discussion
See important discussion notes under MPArraySortValuesInRange.
Examples
Shows sorting in action on an array that uses custom callbacks.
void example_array_sort_all(void)
{
// Create the callbacks struct. I am going to duplicate the string when
// retaining, and free it when releasing.
MPArrayCallBacks customCallbacks;
customCallbacks.retain = (MPAllocatorRetainCallBack)strdup;
customCallbacks.release = (MPAllocatorReleaseCallBack)free;
customCallbacks.copyDescription = NULL;
// Create the array and add some values.
MPArrayRef array = MPArrayCreate(&customCallbacks);
MPArrayAppendValue(array, "Chicago");
MPArrayAppendValue(array, "Wheaton");
MPArrayAppendValue(array, "Boston");
// This will print "Chicago", "Wheaton", "Boston"
MPShow(array);
// Sort all of the values in the array.
MPArraySortValues(array, kMPArraySortDefault, (MPComparatorFunction)strcmp);
// This will print "Boston", "Chicago", "Wheaton"
MPShow(array);
// Clean-up the array (and consequently all duplicated strings).
MPRelease(array);
}
MPArraySortValuesInRange
Sorts the items in the specified range in the array using the given comparator function and options.
void MPArraySortValuesInRange(
MPArrayRef array,
unsigned start,
unsigned len,
MPArraySortingOptions options,
MPComparatorFunction comparator
);
Parameters
array
The array whose values you wish to sort.
start
The index to start sorting at.
len
How many items to sort. If the number of items plus the starting index exceeds the number of items in the array, your program will exit with an error.
options
A bitset determining how to sort the array. The options are described in Constants section. Multiple options can be appended together using the C bitwise OR operator.
comparator
This is a function of the type:
typedef int (*MPComparatorFunction)(const void *val1, const void *val2);
This function is called each time two values in the array need to be compared. The way the function should operate is very similar to the C qsort function. If the val1 is less than val2, then return a number less than 0. If the two are equal, then return 0. And if val1 is greater than val2, then return any number greater than 1.
Discussion
This function uses combsort to sort values. It is an extremely efficient algorithm rivaling sorting algorithms such as qsort, merge sort, and heap sort. See this page for more information on combsort.
One very important note about combsort is that it is not “stable”. What this means is that keys with the same value have the potential to be shuffled. In many circumstances, this is perfectly fine, however, there might be an instance where you may need to keep keys of the same value in the exact order they were before the sort. An example of this might be if you are sorting an array of dictionaries (hashtables) on one particular key, say some string. But the order in which you inserted these items into the array is very important, and so if two keys have the same value, it might swap those two dictionaries, which would ruin the order you had. In order to avoid this for these special cases, make sure your sorting options include kMPArraySortStable, which will severely decrease performance, but will keep the results stable. However, in most cases it is fine to just use kMPArraySortDefault.
Examples
Sorting only part of an array of strings. Notice that this sort is on MPTypes.
void example_array_sort_range(void)
{
// Create an array of strings.
MPArrayRef array = MPAutorelease(MPArrayCreate(&kMPTypeArrayCallbacks));
MPArrayAppendValue(array, MPAutorelease(MPStringCreateWithCString("Jack")));
MPArrayAppendValue(array, MPAutorelease(MPStringCreateWithCString("Kate")));
MPArrayAppendValue(array, MPAutorelease(MPStringCreateWithCString("John")));
MPArrayAppendValue(array, MPAutorelease(MPStringCreateWithCString("Sawyer")));
MPArrayAppendValue(array, MPAutorelease(MPStringCreateWithCString("Michael")));
MPArrayAppendValue(array, MPAutorelease(MPStringCreateWithCString("Sun")));
MPArrayAppendValue(array, MPAutorelease(MPStringCreateWithCString("Jin")));
MPArrayAppendValue(array, MPAutorelease(MPStringCreateWithCString("Hurley")));
// This will print the order in which we added them.
MPShow(array);
// Sort the array, which will result in "Kate", "John", "Sawyer", and "Michael"
// sorted in the order "John", "Kate", "Michael", and "Sawyer".
MPArraySortValuesInRange(array, 1, 4, kMPArraySortDefault, (MPComparatorFunction)MPStringCompare);
MPShow(array);
}
MPArraySwapIndexes
Swaps the values at the given indexes of the array.
void MPArraySwapIndexes(
MPArrayRef array,
unsigned index1,
unsigned index2
);
Parameters
array
The array you want to swap values for.
index1
The first index you are swapping. This must be in the array’s bounds otherwise your program will exit on an error.
index2
The second index you are swapping. This must be in the array’s bounds otherwise your program will exit on an error.
Examples
Do a few sample swaps.
void example_array_swap(void)
{
// Assume myArray already contains ["Woodsmen", "Pioneers", "Indians"].
// After this swap, our array will be ["Indians", "Pioneers", "Woodsmen"].
MPArraySwapIndexes(myArray, 0, 2);
// Now we swap again, our array will be ["Indians", "Woodsmen", "Pioneers"].
MPArraySwapIndexes(myArray, 1, 2);
}
MPArrayValueAtIndex
Returns the value of the given array at the specified index.
void * MPArrayValueAtIndex(
MPArrayRef array, unsigned index
);
Parameters
array
The array to retrieve the value from.
index
The index of the array that the value lives at. If the index is out of the bounds of the array, your program will exit on an error.
Return Value
The retrieved value. This value is not retained by the array, so if you need it to stay around after the array is released, you will need to retain it.
Discussion
The running time for this function is linear (O(n)). Therefore, if you are enumerating over the values of an array, it is highly recommended that you use a MPArrayEnumeratorRef which you obtain by calling MPArrayCreateEnumerator on the array for which you wish to enumerate over.
Examples
Shows how to retrieve a value from an array, and also how to retain if you plan on releasing your array.
// Create our array.
MPArrayRef array = MPArrayCreate(&kMPTypeArrayCallbacks);
MPArrayAppendValue(array, MPAutorelease(MPStringCreateWithCString("Kathy")));
// Get the first value and retain it since we are releasing our array.
MPStringRef string = MPRetain(MPArrayValueAtIndex(array, 0));
MPRelease(array);
// This will print "Kathy" to the screen.
printf("%s\n", MPStringCStringPtr(string));
MPRelease(string);
Constants
Sorting options
These options determine how MPArraySortValues and MPArraySortValuesInRange sort an array. Multiple options can be specified by separating them with the C bitwise OR operator.
typedef enum MPArraySortingOptions
{
kMPArraySortDefault = 0,
kMPArraySortDescending = 1U << 0,
kMPArraySortStable = 1U << 1
} MPArraySortingOptions;
kMPArraySortDefault
Specifies the array should be sorted using the default ascending, non-stable method.
kMPArraySortDescending
If this is specified, the array will be sorted in descending order instead.
kMPArraySortStable
Specifies the sorting algorithm should be stable, which while severely inhibits performance, always guarantees FIFO. Please see the discussion for MPArraySortValuesInRange for more information.