Improved Preferences database. Branches can now be accessed by index. Added UUID generation (better versions needed for Unix and MSWin!). Added access to group name and path

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6983 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Matthias Melcher 2009-12-27 20:14:04 +00:00
parent 38c15442a4
commit 9048b4b895
2 changed files with 156 additions and 8 deletions

View File

@ -80,12 +80,24 @@ public:
USER ///< Preferences apply only to the current user
};
static const char *newUUID();
Fl_Preferences( Root root, const char *vendor, const char *application );
Fl_Preferences( const char *path, const char *vendor, const char *application );
Fl_Preferences( Fl_Preferences &parent, const char *group );
Fl_Preferences( Fl_Preferences*, const char *group );
Fl_Preferences( Fl_Preferences *parent, const char *group );
Fl_Preferences( Fl_Preferences &parent, int groupIndex );
Fl_Preferences( Fl_Preferences *parent, int groupIndex );
~Fl_Preferences();
/** Return the name of this entry.
*/
const char *name() { return node->name(); }
/** Return the the full path to this entry.
*/
const char *path() { return node->path(); }
int groups();
const char *group( int num_group );
char groupExists( const char *key );
@ -163,6 +175,7 @@ private:
Fl_Preferences &operator=(const Fl_Preferences&);
static char nameBuffer[128];
static char uuidBuffer[40];
class FL_EXPORT Node // a node contains a list to all its entries
{ // and all means to manage the tree structure
@ -174,6 +187,8 @@ private:
~Node();
// node methods
int write( FILE *f );
const char *name();
const char *path() { return path_; }
Node *find( const char *path );
Node *search( const char *path, int offset=0 );
Node *addChild( const char *path );
@ -184,6 +199,7 @@ private:
// entry methods
int nChildren();
const char *child( int ix );
Node *childNode( int ix );
void set( const char *name, const char *value );
void set( const char *line );
void add( const char *line );

View File

@ -36,6 +36,7 @@
#include <FL/fl_utf8.h>
#include "flstring.h"
#include <sys/stat.h>
#include <time.h>
#if defined(WIN32) && !defined(__CYGWIN__)
# include <direct.h>
@ -53,9 +54,87 @@
#ifdef WIN32
# include <windows.h>
#else
# include <sys/time.h>
#endif // WIN32
char Fl_Preferences::nameBuffer[128];
char Fl_Preferences::uuidBuffer[40];
/**
* Returns a UUID as generated by the system.
*
* A UUID is a "universally unique identifier" which is commonly used in
* configuration files to create identities. A UUID in ASCII looks like this:
* <tt>937C4900-51AA-4C11-8DD3-7AB59944F03E</tt>. It has always 36 bytes plus
* a trailing zero.
*
* \return a pointer to a static buffer containing the new UUID in ASCII format.
* The buffer is overwritten during every call to this function!
*/
const char *Fl_Preferences::newUUID()
{
#ifdef __APPLE__
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFUUIDBytes b = CFUUIDGetUUIDBytes(theUUID);
sprintf(uuidBuffer, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
b.byte0, b.byte1, b.byte2, b.byte3, b.byte4, b.byte5, b.byte6, b.byte7,
b.byte8, b.byte9, b.byte10, b.byte11, b.byte12, b.byte13, b.byte14, b.byte15);
CFRelease(theUUID);
#elif defined (WIN32)
#warning MSWindows implementation missing!
// UUID b;
// UuidCreate(&b);
unsigned char b[16];
time_t t = time(0); // first 4 byte
b[0] = (unsigned char)t;
b[1] = (unsigned char)(t>>8);
b[2] = (unsigned char)(t>>16);
b[3] = (unsigned char)(t>>24);
int r = rand(); // four more bytes
b[4] = (unsigned char)r;
b[5] = (unsigned char)(r>>8);
b[6] = (unsigned char)(r>>16);
b[7] = (unsigned char)(r>>24);
unsigned int a = (unsigned int)&t; // four more bytes
b[8] = (unsigned char)a;
b[9] = (unsigned char)(a>>8);
b[10] = (unsigned char)(a>>16);
b[11] = (unsigned char)(a>>24);
char name[80]; // last four bytes
gethostname(name, 79);
memcpy(b+12, name, 4);
sprintf(uuidBuffer, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]);
#else
#warning Unix implementation missing!
// #include <uuid/uuid.h>
// void uuid_generate(uuid_t out);
unsigned char b[16];
time_t t = time(0); // first 4 byte
b[0] = (unsigned char)t;
b[1] = (unsigned char)(t>>8);
b[2] = (unsigned char)(t>>16);
b[3] = (unsigned char)(t>>24);
int r = rand(); // four more bytes
b[4] = (unsigned char)r;
b[5] = (unsigned char)(r>>8);
b[6] = (unsigned char)(r>>16);
b[7] = (unsigned char)(r>>24);
unsigned int a = (unsigned int)&t; // four more bytes
b[8] = (unsigned char)a;
b[9] = (unsigned char)(a>>8);
b[10] = (unsigned char)(a>>16);
b[11] = (unsigned char)(a>>24);
char name[80]; // last four bytes
gethostname(name, 79);
memcpy(b+12, name, 4);
sprintf(uuidBuffer, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]);
#endif
}
/**
@ -132,6 +211,41 @@ Fl_Preferences::Fl_Preferences( Fl_Preferences *parent, const char *group )
}
/**
\brief Open a child group using a given index.
Use the \p groupIndex argument to find the group that you would like to access.
If the given index is invalid (negative or too high), a new group is created
with a UUID as a name.
\param[in] parent reference object for the new group
\param[in] groupIndex zero based index into child groups
*/
Fl_Preferences::Fl_Preferences( Fl_Preferences &parent, int groupIndex )
{
rootNode = parent.rootNode;
if (groupIndex<0 || groupIndex>=parent.groups()) {
node = parent.node->addChild( newUUID() );
} else {
node = parent.node->childNode( groupIndex );
}
}
/**
\see Fl_Preferences( Fl_Preferences&, int groupIndex )
*/
Fl_Preferences::Fl_Preferences( Fl_Preferences *parent, int groupIndex )
{
rootNode = parent->rootNode;
if (groupIndex<0 || groupIndex>=parent->groups()) {
node = parent->node->addChild( newUUID() );
} else {
node = parent->node->childNode( groupIndex );
}
}
/**
The destructor removes allocated resources. When used on the
\em base preferences group, the destructor flushes all
@ -1348,20 +1462,38 @@ int Fl_Preferences::Node::nChildren()
return cnt;
}
// return the node name
const char *Fl_Preferences::Node::name()
{
if ( path_ )
{
char *r = strrchr( path_, '/' );
return r ? r+1 : path_ ;
} else {
return 0L ;
}
}
// return the n'th child node
const char *Fl_Preferences::Node::child( int ix )
{
Node *nd = childNode( ix );
if ( nd )
return nd->name();
else
return 0L ;
}
// return the n'th child node
Fl_Preferences::Node *Fl_Preferences::Node::childNode( int ix )
{
Node *nd;
for ( nd = child_; nd; nd = nd->next_ )
{
if ( !ix-- ) break;
if ( !nd ) break;
}
if ( nd && nd->path_ )
{
char *r = strrchr( nd->path_, '/' );
return r ? r+1 : nd->path_ ;
}
return 0L ;
return nd;
}
// remove myself from the list and delete me (and all children)