Here's an example from
gnome-apt, a C++ application used to manage
packages on Debian systems.
gnome-apt loads and saves the position of some
columns in a tree display. The columns are identified
by the
GAptPkgTree::ColumnType enumeration. GAptPkgTree::ColumnTypeEnd is
the last element in the column type enumeration, and
equal to the number of valid column types. This example
is frighteningly "real world" and checks for a number
of error conditions.
static void
load_column_order(vector<GAptPkgTree::ColumnType> & columns)
{
gpointer config_iterator;
guint loaded = 0;
config_iterator = gnome_config_init_iterator("/gnome-apt/ColumnOrder");
if (config_iterator != 0)
{
gchar * col, * pos;
columns.reserve(GAptPkgTree::ColumnTypeEnd);
loaded = 0;
while ((config_iterator =
gnome_config_iterator_next(config_iterator,
&col, &pos)))
{
// shouldn't happen, but I'm paranoid
if (pos == 0 || col == 0)
{
if (pos) g_free(pos);
if (col) g_free(col);
continue;
}
GAptPkgTree::ColumnType ct = string_to_column(col);
gint index = atoi(pos);
g_free(pos); pos = 0;
g_free(col); col = 0;
// the user could mangle the config file to make this happen
if (static_cast<guint>(index) >= columns.size())
continue;
columns[index] = ct;
++loaded;
}
}
if (loaded != static_cast<guint>(GAptPkgTree::ColumnTypeEnd))
{
// Either there was no saved order, or something is busted - use
// default order
columns.clear();
int i = 0;
while (i < GAptPkgTree::ColumnTypeEnd)
{
columns.push_back(static_cast<GAptPkgTree::ColumnType>(i));
++i;
}
// Clean the section - otherwise an old entry could
// remain forever and keep screwing us up in the future.
gnome_config_clean_section("/gnome-apt/ColumnOrder");
gnome_config_sync();
}
g_return_if_fail(columns.size() ==
static_cast<guint>(GAptPkgTree::ColumnTypeEnd));
}
|
It might be helpful to see the function that saves the
column positions:
static void
save_column_order(const vector<GAptPkgTree::ColumnType> & columns)
{
g_return_if_fail(columns.size() ==
static_cast<guint>(GAptPkgTree::ColumnTypeEnd));
int position = 0;
vector<GAptPkgTree::ColumnType>::const_iterator i = columns.begin();
while (i != columns.end())
{
gchar key[256];
g_snprintf(key, 255, "/gnome-apt/ColumnOrder/%s", column_to_string(*i));
gchar val[30];
g_snprintf(val, 29, "%d", position);
gnome_config_set_string(key, val);
++position;
++i;
}
gnome_config_sync();
}
|
When writing this code, the decision was made to store
enumeration values as strings rather than integers. The
column_to_string() and string_to_column() functions use
a simple array of column names indexed by the
enumeration values to convert back and forth. There are
two reasons to do this: it will not break when the
enumeration is altered in future versions of the
program, and it keeps the configuration file
human-editable.
You may also notice that the column positions are
stored with
gnome_config_set_string() instead of gnome_config_set_int(). This is because
gnome_config_iterator_next()
returns a string representation of the stored
information, as found in the file. Most likely, gnome_config_set_int() stores
integers as strings atoi()
would understand (in fact it does), but it is
technically not guaranteed by the API. If the code used
gnome_config_set_int(), it
would have to obtain only the key from gnome_config_iterator_next() and then
call gnome_config_get_int()
to obtain the integer value. Using atoi() on the string value would make
unwarranted assumptions about
gnome-config's implementation.