summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2009-12-27 20:14:04 +0000
committerMatthias Melcher <fltk@matthiasm.com>2009-12-27 20:14:04 +0000
commit9048b4b8950c95df9255e53c101b863037e56ecf (patch)
treec9dbcf55bedfcd1ed3801444e4d74e7105ace01d
parent38c15442a418a238462b1207adb681cf992edab7 (diff)
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
-rw-r--r--FL/Fl_Preferences.H18
-rw-r--r--src/Fl_Preferences.cxx146
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 <FL/fl_utf8.h>
#include "flstring.h"
#include <sys/stat.h>
+#include <time.h>
#if defined(WIN32) && !defined(__CYGWIN__)
# include <direct.h>
@@ -52,10 +53,88 @@
#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
+}
/**
@@ -133,6 +212,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
changes to the preferences file and deletes all internal
@@ -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)