Why use CDBStore instead of built-in storage mechanisms like property lists or Core Data? Because it occupies what I think is a sweet spot in between the two.
Why should you not use CDBStore?
hg clone http://mooseyard.com/hg/hgwebdir.cgi/CDBStore/ CDBStore
Or if you're just looking:
The underlying tinycdb library (included) is in the public domain.
However, CDBStore is more limited than a regular in-memory NSDictionary in what object types it supports. By default, the keys must be NSData objects. The values can be of any archivable class (one that implements the NSCoding protocol.)
It's possible to extend the supported key and value types. You just have to subclass CDBStore and override a few methods that convert between object pointers (id) and raw binary data.
CDBReader provides read-only access to an existing cdb file. You can look up the data value associated with a key, and you can enumerate all of the key-value pairs. That's all.
CDBWriter is the write-only counterpart. You feed it key-value pairs one at a time, and it writes them to a new cdb file. After the file is complete, it can be accessed with CDBReader.
In addition, the tinycdb implementation memory-maps the file, which means it benefits from the kernel's unified buffer cache, and avoids allocating memory in your heap, even when reading values. This can greatly improve memory usage with large files.
As I said above, the CDBReader and CDBWriter classes are just simple object-oriented wrappers around the tinycdb API. There's nothing exciting about their implementation.
To support key and value objects, CDBStore just uses two pairs of methods to encode and decode keys and values. The key codec just copies the bytes into and out of NSData objects. The value codec uses NSKeyedArchiver and NSKeyedUnarchiver (plus some special cases to more efficiently handle common types like NSData, NSString and NSValue.)
To support incremental updates, CDBStore keeps an in-memory NSMutableDictionary to store unsaved changes; its lookup code checks this dictionary first before hitting the cdb file. (This dictionary is also used as a read cache, to avoid the expense of unarchiving objects multiple times.) To save changes, it first opens a CDBWriter on a new temporary file. Then it enumerates over the original file, copying the old value bytes directly across for an unmodified key, or archiving the object value for a modified key. Deleted keys are skipped. Then newly-added keys and values are written. Finally, the new file atomically replaces the old one.
This is a "safe-save" technique. It has the advantage that the file can't be corrupted due to a crash, kernel panic or power failure, since the old file remains in place until the new one is complete. (Incrementally-updated files like SQL databases or Berkeley DBs can't make that claim.) But it has the disadvantage that the entire file has to be copied on save, even if only a tiny part of it changed. This could be a problem if you have a very large, frequently-changing file.