preferencedictionary.h

Go to the documentation of this file.
00001 /*
00002  Copyright (C) 2001-2006, William Joseph.
00003  All Rights Reserved.
00004 
00005  This file is part of GtkRadiant.
00006 
00007  GtkRadiant is free software; you can redistribute it and/or modify
00008  it under the terms of the GNU General Public License as published by
00009  the Free Software Foundation; either version 2 of the License, or
00010  (at your option) any later version.
00011 
00012  GtkRadiant is distributed in the hope that it will be useful,
00013  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  GNU General Public License for more details.
00016 
00017  You should have received a copy of the GNU General Public License
00018  along with GtkRadiant; if not, write to the Free Software
00019  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020  */
00021 
00022 #if !defined(INCLUDED_PREFERENCEDICTIONARY_H)
00023 #define INCLUDED_PREFERENCEDICTIONARY_H
00024 
00025 #include "preferencesystem.h"
00026 #include "xml/ixml.h"
00027 #include "stream/stringstream.h"
00028 #include "generic/callback.h"
00029 #include "versionlib.h"
00030 #include <map>
00031 
00032 class PreferenceDictionary: public PreferenceSystem
00033 {
00034         class PreferenceEntry
00035         {
00036                 StringImportCallback m_importer;
00037                 StringExportCallback m_exporter;
00038             public:
00039                 PreferenceEntry (const StringImportCallback& importer, const StringExportCallback& exporter) :
00040                     m_importer(importer), m_exporter(exporter)
00041                 {
00042                 }
00043                 void importString (const std::string& string)
00044                 {
00045                     m_importer(string.c_str());
00046                 }
00047                 void exportString (const StringImportCallback& importer)
00048                 {
00049                     m_exporter(importer);
00050                 }
00051         };
00052 
00053         typedef std::map<std::string, PreferenceEntry> PreferenceEntries;
00054         PreferenceEntries m_preferences;
00055 
00056         typedef std::map<std::string, std::string> PreferenceCache;
00057         PreferenceCache m_cache;
00058 
00059     public:
00060         typedef PreferenceEntries::iterator iterator;
00061 
00062         iterator begin ()
00063         {
00064             return m_preferences.begin();
00065         }
00066         iterator end ()
00067         {
00068             return m_preferences.end();
00069         }
00070         iterator find (const std::string& name)
00071         {
00072             return m_preferences.find(name);
00073         }
00074 
00075         void registerPreference (const std::string& name, const StringImportCallback& importer,
00076                 const StringExportCallback& exporter)
00077         {
00078             m_preferences.insert(PreferenceEntries::value_type(name, PreferenceEntry(importer, exporter)));
00079             PreferenceCache::iterator i = m_cache.find(name);
00080             if (i != m_cache.end()) {
00081                 importer(i->second.c_str());
00082                 m_cache.erase(i);
00083             }
00084         }
00085 
00086         void importPref (const std::string& name, const std::string& value)
00087         {
00088             PreferenceEntries::iterator i = m_preferences.find(name);
00089             if (i != m_preferences.end()) {
00090                 (*i).second.importString(value);
00091             } else {
00092                 m_cache.insert(PreferenceCache::value_type(name, value));
00093             }
00094         }
00095 };
00096 
00097 inline void XMLPreference_importString (XMLImporter& importer, const char* value)
00098 {
00099     importer.write(value, string_length(value));
00100 }
00101 typedef ReferenceCaller1<XMLImporter, const char*, XMLPreference_importString> XMLPreferenceImportStringCaller;
00102 
00103 class XMLPreferenceDictionaryExporter: public XMLExporter
00104 {
00105         class XMLQPrefElement: public XMLElement
00106         {
00107                 const std::string m_version;
00108             public:
00109                 XMLQPrefElement (const std::string& version) :
00110                     m_version(version)
00111                 {
00112                 }
00113                 const std::string name () const
00114                 {
00115                     return "qpref";
00116                 }
00117                 const std::string attribute (const std::string& name) const
00118                 {
00119                     if (name == "version") {
00120                         return m_version;
00121                     }
00122                     return "";
00123                 }
00124                 void forEachAttribute (XMLAttrVisitor& visitor) const
00125                 {
00126                     visitor.visit("version", m_version);
00127                 }
00128         };
00129 
00130         class XMLPreferenceElement: public XMLElement
00131         {
00132                 const std::string m_name;
00133             public:
00134                 XMLPreferenceElement (const std::string& name) :
00135                     m_name(name)
00136                 {
00137                 }
00138                 const std::string name () const
00139                 {
00140                     return "epair";
00141                 }
00142                 const std::string attribute (const std::string& name) const
00143                 {
00144                     if (name == "name")
00145                         return m_name;
00146                     return "";
00147                 }
00148                 void forEachAttribute (XMLAttrVisitor& visitor) const
00149                 {
00150                     visitor.visit("name", m_name);
00151                 }
00152         };
00153 
00154         typedef PreferenceDictionary PreferenceEntries;
00155         PreferenceEntries& m_preferences;
00156         const std::string m_version;
00157     public:
00158         XMLPreferenceDictionaryExporter (PreferenceDictionary& preferences, const std::string& version) :
00159             m_preferences(preferences), m_version(version)
00160         {
00161         }
00162 
00163         void exportXML (XMLImporter& importer)
00164         {
00165             importer.write("\n", 1);
00166 
00167             XMLQPrefElement qpref_element(m_version);
00168             importer.pushElement(qpref_element);
00169             importer.write("\n", 1);
00170 
00171             for (PreferenceEntries::iterator i = m_preferences.begin(); i != m_preferences.end(); ++i) {
00172                 XMLPreferenceElement epair_element((*i).first.c_str());
00173 
00174                 importer.pushElement(epair_element);
00175 
00176                 (*i).second.exportString(XMLPreferenceImportStringCaller(importer));
00177 
00178                 importer.popElement(epair_element.name());
00179                 importer.write("\n", 1);
00180             }
00181 
00182             importer.popElement(qpref_element.name());
00183             importer.write("\n", 1);
00184         }
00185 };
00186 
00187 class XMLPreferenceDictionaryImporter: public XMLImporter
00188 {
00189         struct xml_state_t
00190         {
00191                 enum ETag
00192                 {
00193                     tag_qpref, tag_qpref_ignore, tag_epair, tag_epair_ignore
00194                 };
00195 
00196                 xml_state_t (ETag tag) :
00197                     m_tag(tag)
00198                 {
00199                 }
00200 
00201                 ETag m_tag;
00202                 std::string m_name;
00203                 StringOutputStream m_ostream;
00204         };
00205 
00206         typedef std::vector<xml_state_t> xml_stack_t;
00207         xml_stack_t m_xml_stack;
00208 
00209         typedef PreferenceDictionary PreferenceEntries;
00210         PreferenceEntries& m_preferences;
00211         Version m_version;
00212     public:
00213         XMLPreferenceDictionaryImporter (PreferenceDictionary& preferences, const std::string& version) :
00214             m_preferences(preferences), m_version(version_parse(version))
00215         {
00216         }
00217 
00218         void pushElement (const XMLElement& element)
00219         {
00220             if (m_xml_stack.empty()) {
00221                 if (string_equal(element.name(), "qpref")) {
00222                     Version dataVersion(version_parse(element.attribute("version")));
00223                     if (!version_compatible(m_version, dataVersion)) {
00224                         g_message("qpref import: data version %i:%i is not compatible with code version %i:%i\n",
00225                                 dataVersion.major, dataVersion.minor, m_version.major, m_version.minor);
00226                         m_xml_stack.push_back(xml_state_t::tag_qpref_ignore);
00227                     } else {
00228                         m_xml_stack.push_back(xml_state_t::tag_qpref);
00229                     }
00230                 } else {
00231                     // not valid
00232                 }
00233             } else {
00234                 switch (m_xml_stack.back().m_tag) {
00235                 case xml_state_t::tag_qpref:
00236                     if (string_equal(element.name(), "epair")) {
00237                         m_xml_stack.push_back(xml_state_t::tag_epair);
00238                         m_xml_stack.back().m_name = element.attribute("name");
00239                     } else {
00240                         // not valid
00241                     }
00242                     break;
00243                 case xml_state_t::tag_qpref_ignore:
00244                     if (string_equal(element.name(), "epair")) {
00245                         m_xml_stack.push_back(xml_state_t::tag_epair_ignore);
00246                     } else {
00247                         // not valid
00248                     }
00249                     break;
00250                 case xml_state_t::tag_epair:
00251                 case xml_state_t::tag_epair_ignore:
00252                     // not valid
00253                     break;
00254                 }
00255             }
00256 
00257         }
00258         void popElement (const std::string& name)
00259         {
00260             if (m_xml_stack.back().m_tag == xml_state_t::tag_epair) {
00261                 m_preferences.importPref(m_xml_stack.back().m_name.c_str(), m_xml_stack.back().m_ostream.c_str());
00262             }
00263             m_xml_stack.pop_back();
00264         }
00265         std::size_t write (const char* buffer, std::size_t length)
00266         {
00267             return m_xml_stack.back().m_ostream.write(buffer, length);
00268         }
00269 };
00270 
00271 #endif

Generated by  doxygen 1.6.2