Inherits From: NSObject
Conforms To: NSObject (NSObject)
Declared In: Foundation/NSByteStore.h
An NSBTreeBlock provides ordered, associative storage and retrieval of untyped data. It identifies and orders data items, called values, by key, using a comparator function. A companion class, NSBTreeCursor, actually manipulates the contents of the NSBTreeBlock; NSBTreeBlock only provides the mechanisms for storing and sorting the key/value pairs.
Setting Up an NSBTreeBlock
An NSBTreeBlock can be used with either a memory-based NSByteStore or an NSByteStoreFile. The NSByteStore holds the contents of the NSBTreeBlock. Use NSBTreeBlock with NSByteStoreFile to build persistent databases. An NSBTreeBlock is initialized as a new client of an NSByteStore using the method initWithStore: or initWithStore:block:. The NSBTreeBlock takes up one block in the NSByteStore per key/value pair and one block for each node in the tree. An NSBTreeBlock will always take up at least one block in the NSByteStore.
After the NSBTreeBlock has been initialized, it must have its comparator function set with the setComparator:context:. A comparator function takes as arguments two pieces of arbitrary data and their lengths and returns an integer indicating their ordering relative to one another. A comparator function is of type (NSBTreeComparator *), which has the form:
typedef int NSBTreeComparator(NSData * data1, NSData * data2, const void *context)
where data1 and data2 are pointers to data and context is a pointer to blind data that may be used by the comparator function. The comparator function returns a number less than 0 if data1 is considered less than data2, greater than 0 if data1 is considered greater than data2, and equal to 0 if data1 and data2 are considered equal. By default, NSBTreeBlocks compare keys as strings.
Getting Data Into and Out of an NSBTreeBlock
As stated above, NSBTreeBlock simply provides the capacity for associative storage. An NSBTreeCursor is needed to take advantage of that capacity. An NSBTreeCursor is like a pointer into the NSBTreeBlock: It can move to specific positions within the key space and perform operations on the values stored at those locations, independent of other cursors. See the NSBTreeCursor class description for more information.
Multiple NSBTreeCursors may independently access a single NSBTreeBlock. The actions of one cursor don't affect any of the other cursors in the NSBTreeBlock, except to the extent that they modify the contents of the NSBTreeBlock. It is both safe and meaningful to remove a record that another NSBTreeCursor has just located, as long as the code using the other NSBTreeCursor anticipates this possibility, as described below.
In the case of one cursor removing a value that another cursor has just located, the second cursor will have received an indication from a key-locating method (for example, moveCursorToKey:) that it has found a key. When it tries to access the value associated with that key, however, the key may no longer exist. The cursor will detect the deletion and slide forward to the next available key if asked to read the value, or it will raise an exception if asked to remove or write the value. If your code allows multiple cursors to be concurrently active in a single NSBTreeBlock, it must anticipate this behavior by handling the exceptions that may be raised and by comparing the key against the expected value after invoking cursorKey. If one cursor is pointed at a key and a second cursor removes or adds a key at a different location, it does not change the position of the first cursor.
Working With the NSByteStore
Since NSBTreeBlock is an NSByteStore client, the transaction model of NSByteStore applies to changes made to the contents of an NSBTreeBlock. In particular, you must send the commitTransaction message to the NSByteStore to have changes to the NSBTreeBlock take effect (and be flushed to disk for a file-based store). If an NSBTreeBlock is used on a strictly read-only basis, transaction management can be ignored.
After an abortTransaction, a cursor may be pointing to a key that no longer exists. Therefore, you must reposition each cursor using one of the moveCursor... methods after an abortTransaction.
Creating and Initializing a New NSBTreeBlock Instance