preferencedictionary.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
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
00248 }
00249 break;
00250 case xml_state_t::tag_epair:
00251 case xml_state_t::tag_epair_ignore:
00252
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