The uuid(3) function can be used to generate UUIDs on most UNIX/Linux systems. Also see RFC 4122 for details on "version 3" UUIDs (which is what the uuid function generates), which can also be generated with code like this (from CUPS):
snprintf(uuid, sizeof(uuid), "%s:%s:%d:%d", ServerName, con->servername, con->serverport, job->id); _cupsMD5Init(&md5state); _cupsMD5Append(&md5state, (unsigned char *)uuid, strlen(uuid)); _cupsMD5Finish(&md5state, md5sum); /* * Format the UUID URI using the MD5 sum and job ID. */ snprintf(uuid, sizeof(uuid), "urn:uuid:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" "%02x%02x%02x%02x%02x%02x", md5sum[0], md5sum[1], md5sum[2], md5sum[3], md5sum[4], md5sum[5], (md5sum[6] & 15) | 0x30, md5sum[7], (md5sum[8] & 0x3f) | 0x40, md5sum[9], md5sum[10], md5sum[11], md5sum[12], md5sum[13], md5sum[14], md5sum[15]); On Dec 27, 2009, at 12:14 PM, fltk-dev@easysw.com wrote: > Author: matt > Date: 2009-12-27 12:14:04 -0800 (Sun, 27 Dec 2009) > New Revision: 6983 > Log: > 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 > > Modified: > branches/branch-1.3/FL/Fl_Preferences.H > branches/branch-1.3/src/Fl_Preferences.cxx > > Modified: branches/branch-1.3/FL/Fl_Preferences.H > =================================================================== > --- branches/branch-1.3/FL/Fl_Preferences.H 2009-12-27 15:23:47 UTC (rev > 6982) > +++ branches/branch-1.3/FL/Fl_Preferences.H 2009-12-27 20:14:04 UTC (rev > 6983) > @@ -79,13 +79,25 @@ > 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 @@ > 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 @@ > ~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 @@ > // 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 ); > > Modified: branches/branch-1.3/src/Fl_Preferences.cxx > =================================================================== > --- branches/branch-1.3/src/Fl_Preferences.cxx 2009-12-27 15:23:47 UTC > (rev 6982) > +++ branches/branch-1.3/src/Fl_Preferences.cxx 2009-12-27 20:14:04 UTC > (rev 6983) > @@ -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> > @@ -52,12 +53,90 @@ > #endif > > #ifdef WIN32 > -#include <windows.h> > +# 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 > +} > > + > /** > The constructor creates a group that manages name/value pairs and > child groups. Groups are ready for reading and writing at any time. > @@ -133,6 +212,41 @@ > > > /** > + \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 > changes to the preferences file and deletes all internal > @@ -1348,20 +1462,38 @@ > 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) > > _______________________________________________ > fltk-commit mailing list > fltk-com...@easysw.com > http://lists.easysw.com/mailman/listinfo/fltk-commit ________________________________________ Michael Sweet, Easy Software Products _______________________________________________ fltk-dev mailing list fltk-dev@easysw.com http://lists.easysw.com/mailman/listinfo/fltk-dev