(Just say "You'd Be!")

A C++ wrapper for Userland's ODB Engine library.

Version 1.0b7

Copyright © 1996, 1997 by Brad Pettit. All Rights Reserved.

Email: bpettit@nogoodreason.com

Download UODBE++ and the Userland Object Database from here

This document was last modified 11/18/97

I haven't yet documented the ODB Traversal Class or the auto-purge feature of the wrapper. Until I do, you can get a good idea of how traversal works by looking at the PowerPlant demonstration and the UODBE++ source code.

Q: What is an object database?

An object database ("odb") is a data file that contains tables of values. A value may specify either a simple type or another table. Each item in the table is accessed via a path specification. If you are familiar with Frontier, then you see an odb every time you look at Frontier.root.

An odb structure might look like this, listed as Name (Type):

	MyDataTable (table) 
		<no data yet>
	MyPrefsTable (table)
		MyWindows (table) 
			DocumentWindow (table) 
				color (RGBColor)
				location (Rect) 
			HeaderWindow (table) 
				color (RGBColor)
				location (Rect) 
			Tool Palette (table) 
				color (RGBColor)
				location (Rect)
				Selected Tool (long) 
	MyAccounts (table)
		1 (table)
		2 (table)
		3 (table)

For example, the path specification to access the color of the header window would be MyPrefsTable.MyWindows.HeaderWindow.Color, and the value at that path would be an RGBColor. Given an open CodbFile object (myODB), the C++ code for accessing the color would be:

// create a value accessor
CodbValue val(myODB);
// load the data at the path
// create space for a RGBColor variable called "color"
RGBColor color;
// access the value and set "color"

Because many of the value methods return a reference to the value object, this same sequence could be expressed this way:

RGBColor color;
// create a temp value accessor, load it, and get the color

Q: I've seen the odb API, and it seems simple enough. So why would I want this extra code in my application?

Yes, the odb API is pretty simple and lean. However, there is a certain amount of housekeeping for which your code is responsible, such as disposing of values before getting new ones. The UODBE wrapper takes care of this, as well as type assertion of data, accessing uninitialized data, handling errors, etc. UODBE classes check all odb functions for errors, and throw exceptions if errors occur, so your code isn't cluttered with error-handling, and is easier to read. You can be sure that the errors are being checked at every stage, and that if line 547 is executing, then line 546 must have succeeded.

Also, it makes the code that actually stores the value a piece of cake. The odbValueRecord is an object much like an Apple Event Descriptor (surprise, surprise), and in many cases it stores handles to objects. If you're familiar with AEGizmos, which contains a set of helpers for dealing with an AEDesc, then you can think of this package as ODB Gizmos.

UODBE Class Overview


represents the database file. Methods exist for creating, opening, closing, saving, adding, getting, and removing values, making new tables, and determining if paths are valid. This class is the wrapper around the odb API.


represents a value in the database. One value object may be used to access any of the data items in the database. CodbValue handles the disposal of database objects when they are no longer needed. A value object is always associated with one and only one CodbFile. The calling code talks to the database thru the value object for most data-related operations. It is an error for a CodbValue object to reference a CodbFile that has been destructed. The CodbFile maintains a count of the value objects which reference it. It will report an error if the count is not zero at destructor time. A CodbValue always contains either a valid value or a value of type unknown. Accessing a CodbValue when it contains type unknown or a type different from that requested results in an an exception of type XodbType. Future implementations may support coercion between types.


consists of a pointer to a string. CodbPathBase is separate from CodbPath for performance reasons, so a const string may be passed in to a function expecting a path without copying the string. These objects may exist ephemerally and are constructed automatically by the compiler when necessary.

Most methods in UODBE that require a string constant to specify a path actually specify a reference to a const CodbPathBase as a parameter. Calling code can specify a string constant as the parameter, and the compiler will construct a temporary CodbPathBase object before calling the method. This does not serve much of a purpose yet, but the overhead is relatively low, performance-wise.


consists of a CodbPathBase and a string buffer, as well as a few convenience methods for dealing with odb paths.


represents a table value. This object is created using the CodbValue::TableValue() method.


a helper object for iterating thru the values in a table.

Exception Classes

all odb exceptions have this as a base class
an odb API call failed. an error message can be obtained by GetMessage(). NOTE: This message might return null; that usually indicates a memory allocation error in the engine.
a UODBE assertion failed. Some assertions are debug only. Others are in all builds.
an attempt was made to access data of an incorrect type.
an invalid path was specified
an attempt was made to access a string value, but the buffer provided by the caller was not large enough to hold the entire value. These may be disabled when accessing string values. The required buffer size may be accessed from the exception object via the BytesNeeded method.

Method Summary

a brief description of the methods available in UODBE classes. For brevity, return types and parameters are usually not including in the descriptions. Consult the header file UODBE.h for more.

CodbFile methods:

CodbValue methods:

CodbPath Methods

A path contains any number of qualifiers separated by dot (period) characters. Paths are limited to 255 characters. The shortest qualifier is one character, so the deepest path one may specify is 128 levels deep. Since paths are Pascal-style strings (prefixed with a length byte), a path qualifier consists of any characters except a period. Even a null is OK.

Both of these sequences would specify the same path:

  CodbPath myPath("\pRoot.Preferences.Window.Size");
    // builds the same path as
   CodbPath myPath("\pRoot");
   myPath.PushStringQualifier("\pPreferences"); // dot not needed

This concludes the summary of UODBE++.

I haven't yet documented the ODB Traversal Class or the auto-purge feature of the wrapper. Until I do, you can get a good idea of how traversal works by looking at the PowerPlant demonstration and the UODBE++ source code.