From 876419ce60c535a06fde52023f7360d2d29ee82a Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 7 Jul 1998 13:53:19 +0000 Subject: [PATCH] added HasEntry/Group function to wxConfig, corrected entry/group deletion 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 | 11 +++- include/wx/fileconf.h | 33 +++++++----- src/common/fileconf.cpp | 111 ++++++++++++++++++++++++++++++++-------- 3 files changed, 120 insertions(+), 35 deletions(-) diff --git a/include/wx/config.h b/include/wx/config.h index d4071bd6ef..d1e27b2517 100644 --- a/include/wx/config.h +++ b/include/wx/config.h @@ -109,6 +109,15 @@ public: 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 @@ -119,7 +128,7 @@ public: 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; diff --git a/include/wx/fileconf.h b/include/wx/fileconf.h index a2bbecb415..84a12b4754 100644 --- a/include/wx/fileconf.h +++ b/include/wx/fileconf.h @@ -34,12 +34,12 @@ // ---------------------------------------------------------------------------- /* - 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 - 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 - 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) @@ -118,11 +118,16 @@ public: 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 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); @@ -141,12 +146,14 @@ public: { 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 *Prev() const { return m_pPrev; } void SetNext(LineList *pNext) { m_pNext = pNext; } + void SetPrev(LineList *pPrev) { m_pPrev = pPrev; } // void SetText(const wxString& str) { m_strLine = str; } @@ -154,13 +161,15 @@ public: 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); - 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: @@ -268,7 +277,7 @@ protected: // 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; } diff --git a/src/common/fileconf.cpp b/src/common/fileconf.cpp index 9f1aea52c0..f2e2c35e03 100644 --- a/src/common/fileconf.cpp +++ b/src/common/fileconf.cpp @@ -2,7 +2,7 @@ // 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 @@ -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) -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); @@ -131,7 +131,7 @@ wxString wxFileConfig::GetLocalFileName(const char *szFile) void wxFileConfig::Init() { - m_pCurrentGroup = + m_pCurrentGroup = 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; - + 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 ' ': case '\t': // ignore whitespace ('\n' impossible here) break; - + 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 - while ( isspace(*pEnd) ) + while ( isspace(*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() ) { - 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 ) @@ -297,7 +297,7 @@ void wxFileConfig::Parse(wxTextFile& file, bool bLocal) } // skip whitespace - while ( isspace(*pEnd) ) + while ( isspace(*pEnd) ) pEnd++; wxString strValue; @@ -325,8 +325,10 @@ void wxFileConfig::SetPath(const wxString& strPath) { wxArrayString aParts; - if ( strPath.IsEmpty() ) + if ( strPath.IsEmpty() ) { + SetRootPath(); return; + } if ( strPath[0] == APPCONF_PATH_SEPARATOR ) { // absolute path @@ -392,6 +394,26 @@ bool wxFileConfig::GetNextEntry (wxString& str, long& lIndex) 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 // ---------------------------------------------------------------------------- @@ -540,6 +562,7 @@ wxFileConfig::LineList *wxFileConfig::LineListAppend(const wxString& str) else { // adjust pointers m_linesTail->SetNext(pLine); + pLine->SetPrev(m_linesTail); } 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 -wxFileConfig::LineList *wxFileConfig::LineListInsert(const wxString& str, +wxFileConfig::LineList *wxFileConfig::LineListInsert(const wxString& str, LineList *pLine) { if ( pLine == m_linesTail ) return LineListAppend(str); - LineList *pNewLine; - + LineList *pNewLine = new LineList(str); 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 { - 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; } +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; @@ -627,7 +673,7 @@ wxFileConfig::LineList *wxFileConfig::ConfigGroup::GetGroupLine() 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); } @@ -755,7 +801,21 @@ bool wxFileConfig::ConfigGroup::DeleteSubgroup(const char *szName) 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; } @@ -771,13 +831,20 @@ bool wxFileConfig::ConfigGroup::DeleteEntry(const char *szName) 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; } // ---------------------------------------------------------------------------- -// +// // ---------------------------------------------------------------------------- void wxFileConfig::ConfigGroup::SetDirty() { @@ -793,7 +860,7 @@ void wxFileConfig::ConfigGroup::SetDirty() // ---------------------------------------------------------------------------- // ctor // ---------------------------------------------------------------------------- -wxFileConfig::ConfigEntry::ConfigEntry(wxFileConfig::ConfigGroup *pParent, +wxFileConfig::ConfigEntry::ConfigEntry(wxFileConfig::ConfigGroup *pParent, 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() ) { - wxLogWarning("Attempt to change immutable key '%s' ignored.", + wxLogWarning("Attempt to change immutable key '%s' ignored.", 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 - m_pLine = Group()->Config()->LineListInsert(strLine, + m_pLine = Group()->Config()->LineListInsert(strLine, Group()->GetLastEntryLine()); Group()->SetLastEntry(this); } -- 2.45.2