]> git.saurik.com Git - wxWidgets.git/commitdiff
added HasEntry/Group function to wxConfig, corrected entry/group deletion
authorVadim Zeitlin <vadim@wxwidgets.org>
Tue, 7 Jul 1998 13:53:19 +0000 (13:53 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Tue, 7 Jul 1998 13:53:19 +0000 (13:53 +0000)
bug (were not deleted from file) in wxFileConfig

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@183 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/config.h
include/wx/fileconf.h
src/common/fileconf.cpp

index d4071bd6ef73b735e3c9e98d886bf950c9f668fb..d1e27b25170f7bed0b4c12dbb613d04e7defa531 100644 (file)
@@ -109,6 +109,15 @@ public:
   virtual bool GetFirstEntry(wxString& str, long& lIndex) = 0;
   virtual bool GetNextEntry (wxString& str, long& lIndex) = 0;
 
   virtual bool GetFirstEntry(wxString& str, long& lIndex) = 0;
   virtual bool GetNextEntry (wxString& str, long& lIndex) = 0;
 
+  // tests of existence
+    // returns TRUE if the group by this name exists
+  virtual bool HasGroup(const wxString& strName) const = 0;
+    // same as above, but for an entry
+  virtual bool HasEntry(const wxString& strName) const = 0;
+    // returns TRUE if either a group or an entry with a given name exist
+  bool Exists(const wxString& strName) const
+    { return HasGroup(strName) || HasEntry(strName); }
+
   // key access: returns TRUE if value was really read, FALSE if default used
   // (and if the key is not found the default value is returned.)
     // read a string from the key
   // key access: returns TRUE if value was really read, FALSE if default used
   // (and if the key is not found the default value is returned.)
     // read a string from the key
@@ -119,7 +128,7 @@ public:
   virtual const char *Read(const char *szKey,
                            const char *szDefault = NULL) const;
     // the same for longs
   virtual const char *Read(const char *szKey,
                            const char *szDefault = NULL) const;
     // the same for longs
-  long Read(const char *szKey, long lDefault) const
+  virtual long Read(const char *szKey, long lDefault) const
     { long l; Read(&l, szKey, lDefault); return l; }
     // and another version: returns true if default value is returned
   virtual bool Read(long *pl, const char *szKey, long lDefault = 0) const = 0;
     { long l; Read(&l, szKey, lDefault); return l; }
     // and another version: returns true if default value is returned
   virtual bool Read(long *pl, const char *szKey, long lDefault = 0) const = 0;
index a2bbecb415e2e7dc6938427d833c61489851e3cb..84a12b4754fa8a91c52a82c34e894aa6bbc92ab2 100644 (file)
 // ----------------------------------------------------------------------------
 
 /*
 // ----------------------------------------------------------------------------
 
 /*
-  wxFileConfig derives from base Config and implements file based config class, 
+  wxFileConfig derives from base Config and implements file based config class,
   i.e. it uses ASCII disk files to store the information. These files are
   i.e. it uses ASCII disk files to store the information. These files are
-  alternatively called INI, .conf or .rc in the documentation. They are 
+  alternatively called INI, .conf or .rc in the documentation. They are
   organized in groups or sections, which can nest (i.e. a group contains
   subgroups, which contain their own subgroups &c). Each group has some
   organized in groups or sections, which can nest (i.e. a group contains
   subgroups, which contain their own subgroups &c). Each group has some
-  number of entries, which are "key = value" pairs. More precisely, the format 
+  number of entries, which are "key = value" pairs. More precisely, the format
   is:
 
   # comments are allowed after either ';' or '#' (Win/UNIX standard)
   is:
 
   # comments are allowed after either ';' or '#' (Win/UNIX standard)
@@ -118,11 +118,16 @@ public:
   virtual bool GetFirstEntry(wxString& str, long& lIndex);
   virtual bool GetNextEntry (wxString& str, long& lIndex);
 
   virtual bool GetFirstEntry(wxString& str, long& lIndex);
   virtual bool GetNextEntry (wxString& str, long& lIndex);
 
+  virtual bool HasGroup(const wxString& strName) const;
+  virtual bool HasEntry(const wxString& strName) const;
+
   virtual bool Read(wxString *pstr, const char *szKey,
                     const char *szDefault = 0) const;
   virtual const char *Read(const char *szKey,
                            const char *szDefault = 0) const;
   virtual bool Read(long *pl, const char *szKey, long lDefault) const;
   virtual bool Read(wxString *pstr, const char *szKey,
                     const char *szDefault = 0) const;
   virtual const char *Read(const char *szKey,
                            const char *szDefault = 0) const;
   virtual bool Read(long *pl, const char *szKey, long lDefault) const;
+  virtual long Read(const char *szKey, long lDefault) const
+    { return wxConfig::Read(szKey, lDefault); }
   virtual bool Write(const char *szKey, const char *szValue);
   virtual bool Write(const char *szKey, long lValue);
   virtual bool Flush(bool bCurrentOnly = FALSE);
   virtual bool Write(const char *szKey, const char *szValue);
   virtual bool Write(const char *szKey, long lValue);
   virtual bool Flush(bool bCurrentOnly = FALSE);
@@ -141,12 +146,14 @@ public:
   {
   public:
     // ctor
   {
   public:
     // ctor
-    LineList(const wxString& str, LineList *pNext = NULL) : m_strLine(str) 
-      { SetNext(pNext); }
-    
-    // 
+    LineList(const wxString& str, LineList *pNext = NULL) : m_strLine(str)
+      { SetNext(pNext); SetPrev(NULL); }
+
+    //
     LineList *Next() const              { return m_pNext;  }
     LineList *Next() const              { return m_pNext;  }
+    LineList *Prev() const              { return m_pPrev;  }
     void      SetNext(LineList *pNext)  { m_pNext = pNext; }
     void      SetNext(LineList *pNext)  { m_pNext = pNext; }
+    void      SetPrev(LineList *pPrev)  { m_pPrev = pPrev; }
 
     //
     void SetText(const wxString& str) { m_strLine = str;  }
 
     //
     void SetText(const wxString& str) { m_strLine = str;  }
@@ -154,13 +161,15 @@ public:
 
   private:
     wxString  m_strLine;      // line contents
 
   private:
     wxString  m_strLine;      // line contents
-    LineList *m_pNext;        // next node
+    LineList *m_pNext,        // next node
+             *m_pPrev;        // previous one
   };
   };
-  
+
   // functions to work with this list
   LineList *LineListAppend(const wxString& str);
   // functions to work with this list
   LineList *LineListAppend(const wxString& str);
-  LineList *LineListInsert(const wxString& str, 
-                           LineList *pLine);    // NULL => Append()
+  LineList *LineListInsert(const wxString& str,
+                           LineList *pLine);    // NULL => Prepend()
+  void      LineListRemove(LineList *pLine);
   bool      LineListIsEmpty();
 
 private:
   bool      LineListIsEmpty();
 
 private:
@@ -268,7 +277,7 @@ protected:
     // will also recursively set parent's dirty flag
     void SetDirty();
     void SetLine(LineList *pLine);
     // will also recursively set parent's dirty flag
     void SetDirty();
     void SetLine(LineList *pLine);
-    
+
     // the new entries in this subgroup will be inserted after the last subgroup
     // or, if there is none, after the last entry
     void SetLastEntry(ConfigEntry *pLastEntry) { m_pLastEntry = pLastEntry; }
     // the new entries in this subgroup will be inserted after the last subgroup
     // or, if there is none, after the last entry
     void SetLastEntry(ConfigEntry *pLastEntry) { m_pLastEntry = pLastEntry; }
index 9f1aea52c0c85aa861a5f36352f0f8e4ad679bb5..f2e2c35e03f00524aafdf92a8818034f6fd78bf4 100644 (file)
@@ -2,7 +2,7 @@
 // Name:        fileconf.cpp
 // Purpose:     implementation of wxFileConfig derivation of wxConfig
 // Author:      Vadim Zeitlin
 // Name:        fileconf.cpp
 // Purpose:     implementation of wxFileConfig derivation of wxConfig
 // Author:      Vadim Zeitlin
-// Modified by: 
+// Modified by:
 // Created:     07.04.98 (adapted from appconf.cpp)
 // RCS-ID:      $Id$
 // Copyright:   (c) 1997 Karsten Ballüder   &  Vadim Zeitlin
 // Created:     07.04.98 (adapted from appconf.cpp)
 // RCS-ID:      $Id$
 // Copyright:   (c) 1997 Karsten Ballüder   &  Vadim Zeitlin
@@ -55,7 +55,7 @@
 // is 'c' a valid character in group name?
 // NB: APPCONF_IMMUTABLE_PREFIX and APPCONF_PATH_SEPARATOR must be valid chars,
 //     but _not_ ']' (group name delimiter)
 // is 'c' a valid character in group name?
 // NB: APPCONF_IMMUTABLE_PREFIX and APPCONF_PATH_SEPARATOR must be valid chars,
 //     but _not_ ']' (group name delimiter)
-inline bool IsValid(char c) { return isalnum(c) || strchr("_/-!.*%", c); }
+inline bool IsValid(char c) { return isalnum(c) || strchr("@_/-!.*%", c); }
 
 // filter strings
 static wxString FilterIn(const wxString& str);
 
 // filter strings
 static wxString FilterIn(const wxString& str);
@@ -131,7 +131,7 @@ wxString wxFileConfig::GetLocalFileName(const char *szFile)
 
 void wxFileConfig::Init()
 {
 
 void wxFileConfig::Init()
 {
-  m_pCurrentGroup = 
+  m_pCurrentGroup =
   m_pRootGroup    = new ConfigGroup(NULL, "", this);
 
   m_linesHead =
   m_pRootGroup    = new ConfigGroup(NULL, "", this);
 
   m_linesHead =
@@ -191,7 +191,7 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
 {
   const char *pStart;
   const char *pEnd;
 {
   const char *pStart;
   const char *pEnd;
-  
+
   for ( uint n = 0; n < file.GetLineCount(); n++ ) {
     // add the line to linked list
     if ( bLocal )
   for ( uint n = 0; n < file.GetLineCount(); n++ ) {
     // add the line to linked list
     if ( bLocal )
@@ -238,12 +238,12 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
           case ';':
             bCont = FALSE;
             break;
           case ';':
             bCont = FALSE;
             break;
-        
+
           case ' ':
           case '\t':
             // ignore whitespace ('\n' impossible here)
             break;
           case ' ':
           case '\t':
             // ignore whitespace ('\n' impossible here)
             break;
-          
+
           default:
             wxLogWarning("file '%s', line %d: '%s' ignored after group header.",
                          file.GetName(), n + 1, pEnd);
           default:
             wxLogWarning("file '%s', line %d: '%s' ignored after group header.",
                          file.GetName(), n + 1, pEnd);
@@ -259,7 +259,7 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
       wxString strKey(pStart, pEnd);
 
       // skip whitespace
       wxString strKey(pStart, pEnd);
 
       // skip whitespace
-      while ( isspace(*pEnd) ) 
+      while ( isspace(*pEnd) )
         pEnd++;
 
       if ( *pEnd++ != '=' ) {
         pEnd++;
 
       if ( *pEnd++ != '=' ) {
@@ -288,7 +288,7 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
           //  (c) key from global file now found in local one
           // which is exactly what we want.
           else if ( !bLocal || pEntry->IsLocal() ) {
           //  (c) key from global file now found in local one
           // which is exactly what we want.
           else if ( !bLocal || pEntry->IsLocal() ) {
-            wxLogWarning("file '%s', line %d: key '%s' was first found at line %d.", 
+            wxLogWarning("file '%s', line %d: key '%s' was first found at line %d.",
                          file.GetName(), n + 1, strKey.c_str(), pEntry->Line());
 
             if ( bLocal )
                          file.GetName(), n + 1, strKey.c_str(), pEntry->Line());
 
             if ( bLocal )
@@ -297,7 +297,7 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
         }
 
         // skip whitespace
         }
 
         // skip whitespace
-        while ( isspace(*pEnd) ) 
+        while ( isspace(*pEnd) )
           pEnd++;
 
         wxString strValue;
           pEnd++;
 
         wxString strValue;
@@ -325,8 +325,10 @@ void wxFileConfig::SetPath(const wxString& strPath)
 {
   wxArrayString aParts;
 
 {
   wxArrayString aParts;
 
-  if ( strPath.IsEmpty() )
+  if ( strPath.IsEmpty() ) {
+    SetRootPath();
     return;
     return;
+  }
 
   if ( strPath[0] == APPCONF_PATH_SEPARATOR ) {
     // absolute path
 
   if ( strPath[0] == APPCONF_PATH_SEPARATOR ) {
     // absolute path
@@ -392,6 +394,26 @@ bool wxFileConfig::GetNextEntry (wxString& str, long& lIndex)
     return FALSE;
 }
 
     return FALSE;
 }
 
+// ----------------------------------------------------------------------------
+// tests for existence
+// ----------------------------------------------------------------------------
+
+bool wxFileConfig::HasGroup(const wxString& strName) const
+{
+  PathChanger path(this, strName);
+
+  ConfigGroup *pGroup = m_pCurrentGroup->FindSubgroup(path.Name());
+  return pGroup != NULL;
+}
+
+bool wxFileConfig::HasEntry(const wxString& strName) const
+{
+  PathChanger path(this, strName);
+
+  ConfigEntry *pEntry = m_pCurrentGroup->FindEntry(path.Name());
+  return pEntry != NULL;
+}
+
 // ----------------------------------------------------------------------------
 // read/write values
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // read/write values
 // ----------------------------------------------------------------------------
@@ -540,6 +562,7 @@ wxFileConfig::LineList *wxFileConfig::LineListAppend(const wxString& str)
   else {
     // adjust pointers
     m_linesTail->SetNext(pLine);
   else {
     // adjust pointers
     m_linesTail->SetNext(pLine);
+    pLine->SetPrev(m_linesTail);
   }
 
   m_linesTail = pLine;
   }
 
   m_linesTail = pLine;
@@ -547,26 +570,49 @@ wxFileConfig::LineList *wxFileConfig::LineListAppend(const wxString& str)
 }
 
 // insert a new line after the given one or in the very beginning if !pLine
 }
 
 // insert a new line after the given one or in the very beginning if !pLine
-wxFileConfig::LineList *wxFileConfig::LineListInsert(const wxString& str, 
+wxFileConfig::LineList *wxFileConfig::LineListInsert(const wxString& str,
                                                      LineList *pLine)
 {
   if ( pLine == m_linesTail )
     return LineListAppend(str);
 
                                                      LineList *pLine)
 {
   if ( pLine == m_linesTail )
     return LineListAppend(str);
 
-  LineList *pNewLine;
-  
+  LineList *pNewLine = new LineList(str);
   if ( pLine == NULL ) {
   if ( pLine == NULL ) {
-    pNewLine = new LineList(str, m_linesHead);
+    // prepend to the list
+    pNewLine->SetNext(m_linesHead);
+    m_linesHead->SetPrev(pNewLine);
     m_linesHead = pNewLine;
   }
   else {
     m_linesHead = pNewLine;
   }
   else {
-    pNewLine = new LineList(str, pLine->Next());
+    // insert before pLine
+    LineList *pNext = pLine->Next();
+    pNewLine->SetNext(pNext);
+    pNewLine->SetPrev(pLine);
+    pNext->SetPrev(pNewLine);
     pLine->SetNext(pNewLine);
   }
 
   return pNewLine;
 }
 
     pLine->SetNext(pNewLine);
   }
 
   return pNewLine;
 }
 
+void wxFileConfig::LineListRemove(LineList *pLine)
+{
+  LineList *pPrev = pLine->Prev(),
+           *pNext = pLine->Next();
+  if ( pPrev == NULL ) {
+    // deleting the first entry
+    m_linesHead = pNext;
+  }
+  else {
+    // not the first entry
+    pPrev->SetNext(pNext);
+  }
+
+  pNext->SetPrev(pPrev);
+
+  delete pLine;
+}
+
 bool wxFileConfig::LineListIsEmpty()
 {
   return m_linesHead == NULL;
 bool wxFileConfig::LineListIsEmpty()
 {
   return m_linesHead == NULL;
@@ -627,7 +673,7 @@ wxFileConfig::LineList *wxFileConfig::ConfigGroup::GetGroupLine()
     if ( Parent() != NULL ) {
       wxString strFullName;
       strFullName << "[" << GetFullName().c_str() + 1 << "]"; // +1: no '/'
     if ( Parent() != NULL ) {
       wxString strFullName;
       strFullName << "[" << GetFullName().c_str() + 1 << "]"; // +1: no '/'
-      m_pLine = m_pConfig->LineListInsert(strFullName, 
+      m_pLine = m_pConfig->LineListInsert(strFullName,
                                           Parent()->GetLastGroupLine());
       Parent()->SetLastGroup(this);
     }
                                           Parent()->GetLastGroupLine());
       Parent()->SetLastGroup(this);
     }
@@ -755,7 +801,21 @@ bool wxFileConfig::ConfigGroup::DeleteSubgroup(const char *szName)
   if ( n == nCount )
     return FALSE;
 
   if ( n == nCount )
     return FALSE;
 
-  delete m_aSubgroups[n];
+  nCount = m_aEntries.Count();
+  for ( n = 0; n < nCount; n++ ) {
+    LineList *pLine = m_aEntries[n]->GetLine();
+    if ( pLine != NULL )
+      m_pConfig->LineListRemove(pLine);
+  }
+
+  ConfigGroup *pGroup = m_aSubgroups[n];
+  LineList *pLine = pGroup->m_pLine;
+  if ( pLine != NULL )
+    m_pConfig->LineListRemove(pLine);
+  delete pGroup;
+
+  SetDirty();
+
   m_aSubgroups.Remove(n);
   return TRUE;
 }
   m_aSubgroups.Remove(n);
   return TRUE;
 }
@@ -771,13 +831,20 @@ bool wxFileConfig::ConfigGroup::DeleteEntry(const char *szName)
   if ( n == nCount )
     return FALSE;
 
   if ( n == nCount )
     return FALSE;
 
-  delete m_aEntries[n];
+  ConfigEntry *pEntry = m_aEntries[n];
+  LineList *pLine = pEntry->GetLine();
+  if ( pLine != NULL )
+    m_pConfig->LineListRemove(pLine);
+  delete pEntry;
+
+  SetDirty();
+
   m_aEntries.Remove(n);
   return TRUE;
 }
 
 // ----------------------------------------------------------------------------
   m_aEntries.Remove(n);
   return TRUE;
 }
 
 // ----------------------------------------------------------------------------
-// 
+//
 // ----------------------------------------------------------------------------
 void wxFileConfig::ConfigGroup::SetDirty()
 {
 // ----------------------------------------------------------------------------
 void wxFileConfig::ConfigGroup::SetDirty()
 {
@@ -793,7 +860,7 @@ void wxFileConfig::ConfigGroup::SetDirty()
 // ----------------------------------------------------------------------------
 // ctor
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // ctor
 // ----------------------------------------------------------------------------
-wxFileConfig::ConfigEntry::ConfigEntry(wxFileConfig::ConfigGroup *pParent, 
+wxFileConfig::ConfigEntry::ConfigEntry(wxFileConfig::ConfigGroup *pParent,
                                        const wxString& strName,
                                        int nLine)
                          : m_strName(strName)
                                        const wxString& strName,
                                        int nLine)
                          : m_strName(strName)
@@ -829,7 +896,7 @@ void wxFileConfig::ConfigEntry::SetLine(LineList *pLine)
 void wxFileConfig::ConfigEntry::SetValue(const wxString& strValue, bool bUser)
 {
   if ( bUser && IsImmutable() ) {
 void wxFileConfig::ConfigEntry::SetValue(const wxString& strValue, bool bUser)
 {
   if ( bUser && IsImmutable() ) {
-    wxLogWarning("Attempt to change immutable key '%s' ignored.", 
+    wxLogWarning("Attempt to change immutable key '%s' ignored.",
                  Name().c_str());
     return;
   }
                  Name().c_str());
     return;
   }
@@ -853,7 +920,7 @@ void wxFileConfig::ConfigEntry::SetValue(const wxString& strValue, bool bUser)
       // add a new line to the file
       wxASSERT( m_nLine == NOT_FOUND );   // consistency check
 
       // add a new line to the file
       wxASSERT( m_nLine == NOT_FOUND );   // consistency check
 
-      m_pLine = Group()->Config()->LineListInsert(strLine, 
+      m_pLine = Group()->Config()->LineListInsert(strLine,
                                                   Group()->GetLastEntryLine());
       Group()->SetLastEntry(this);
     }
                                                   Group()->GetLastEntryLine());
       Group()->SetLastEntry(this);
     }