From 9048b4b8950c95df9255e53c101b863037e56ecf Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Sun, 27 Dec 2009 20:14:04 +0000 Subject: [PATCH] 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 --- FL/Fl_Preferences.H | 18 ++++- src/Fl_Preferences.cxx | 146 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 156 insertions(+), 8 deletions(-) diff --git a/FL/Fl_Preferences.H b/FL/Fl_Preferences.H index eba771aee..7ad5de756 100644 --- a/FL/Fl_Preferences.H +++ b/FL/Fl_Preferences.H @@ -79,13 +79,25 @@ public: SYSTEM=0, ///< Preferences are used system-wide 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 ); diff --git a/src/Fl_Preferences.cxx b/src/Fl_Preferences.cxx index a24cf85d5..866c90cae 100644 --- a/src/Fl_Preferences.cxx +++ b/src/Fl_Preferences.cxx @@ -36,6 +36,7 @@ #include #include "flstring.h" #include +#include #if defined(WIN32) && !defined(__CYGWIN__) # include @@ -52,10 +53,88 @@ #endif #ifdef WIN32 -#include +# include +#else +# include #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: + * 937C4900-51AA-4C11-8DD3-7AB59944F03E. 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 + // 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)