1 /* 2 * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3 3 * http://www.gnu.org/licenses/lgpl-3.0.html 4 */ 5 6 #ifndef X_CONFIGMANAGER_H 7 #define X_CONFIGMANAGER_H 8 9 #include <wx/hashmap.h> 10 #include <wx/hashset.h> 11 12 #include "settings.h" 13 #include "globals.h" 14 15 #include <tinyxml.h> 16 #include "manager.h" 17 #include "base64.h" 18 19 #undef new 20 #include <map> 21 #include <set> 22 23 24 /* ------------------------------------------------------------------------------------------------------------------ 25 * Interface Serializable 26 * ConfigManager can save arbitrary objects and even sets/maps of objects, provided they implement Serializable. 27 * 28 * Usage: 29 * ------ 30 * class MySerializableLongIntClass : public ISerializable 31 * { 32 * //... 33 * wxString SerializeOut() const {wxString tmp; tmp << m_int; return tmp;}; 34 * void SerializeIn(const wxString& s){s.ToLong(&m_int);}; 35 * //... 36 * long int m_int; 37 * }; 38 */ 39 class ISerializable 40 { 41 public: 42 ISerializable(); 43 virtual ~ISerializable(); 44 virtual wxString SerializeOut() const = 0; 45 virtual void SerializeIn(const wxString& s) = 0; 46 }; 47 48 49 /* ------------------------------------------------------------------------------------------------------------------ 50 * Containers supported by ConfigManager 51 */ 52 namespace ConfigManagerContainer 53 { 54 typedef std::map<wxString, wxString> StringToStringMap; 55 typedef std::map<int, wxString> IntToStringMap; 56 typedef std::set<wxString> StringSet; 57 58 typedef std::map<wxString, ISerializable*> SerializableObjectMap; 59 } 60 61 62 /* ------------------------------------------------------------------------------------------------------------------*/ 63 /** Search dirs values. Used as a bitmask in ConfigManager::LocateDataFile() and friends.*/ 64 enum SearchDirs 65 { 66 sdHome = 0x0001, ///< User's home directory 67 sdBase = 0x0002, ///< Code::Blocks' installation base 68 sdTemp = 0x0004, ///< System-wide temp folder 69 sdPath = 0x0008, ///< All dirs in the PATH environment variable 70 sdConfig = 0x0010, ///< Config folder 71 sdCurrent = 0x0020, ///< Current working folder 72 73 sdPluginsUser = 0x0100, ///< Plugins folder in user's dir 74 sdScriptsUser = 0x0200, ///< Scripts folder in user's dir 75 sdDataUser = 0x0400, ///< Data folder in user's dir 76 77 sdAllUser = 0x0f00, ///< Convenience value meaning "all sd*User values" 78 79 sdPluginsGlobal = 0x1000, ///< Plugins folder in base dir 80 sdScriptsGlobal = 0x2000, ///< Scripts folder in base dir 81 sdDataGlobal = 0x4000, ///< Data folder in base dir 82 83 sdAllGlobal = 0xf000, ///< Convenience value meaning "all sd*Global values" 84 85 sdAllKnown = 0xffff ///< All known dirs (i.e. all of the above) 86 }; 87 88 89 class CodeBlocksApp; 90 91 /* ------------------------------------------------------------------------------------------------------------------ 92 * ConfigManager class 93 */ 94 class DLLIMPORT ConfigManager 95 { 96 friend class CfgMgrBldr; 97 friend class CodeBlocksApp; 98 99 TiXmlDocument *doc; 100 TiXmlElement* root; 101 TiXmlElement* pathNode; 102 103 ConfigManager(TiXmlElement* r); 104 TiXmlElement* AssertPath(wxString& path); 105 TiXmlElement* GetUniqElement(TiXmlElement* p, const wxString& q); 106 void SetNodeText(TiXmlElement *n, const TiXmlText& t); 107 inline void Collapse(wxString& str) const; 108 wxString InvalidNameMessage(const wxString& what, const wxString& sub, TiXmlElement *localPath) const; 109 static void InitPaths(); 110 static void MigrateFolders(); 111 112 static wxString config_folder; 113 static wxString home_folder; 114 static wxString data_path_user; 115 static wxString data_path_global; 116 117 #ifdef CB_AUTOCONF 118 static wxString plugin_path_global; 119 #endif 120 static wxString app_path; 121 static wxString temp_folder; 122 static wxString alternate_user_data_path; 123 static bool has_alternate_user_data_path; 124 125 protected: 126 //For use by the CodeBlocksApp when the --user-data-dir switch is set 127 //all of the user config and user plugin data will be set relative to this path 128 static bool SetUserDataFolder(const wxString &user_data_path); 129 130 //Used by CfgMgrBldr internally by ConfigManager 131 static wxString GetUserDataFolder(); 132 133 public: 134 135 /* ----------------------------------------------------------------------------------------------------- 136 * Utility functions for accessing files/folders in a system-wide, consistent way 137 * -----------------------------------------------------------------------------------------------------*/ 138 139 140 /** @brief Locate a file in an installation- and platform-independent way. 141 * 142 * You should always use this function if you are looking for "some arbitrary file that belongs to Code::Blocks", 143 * as it works across platforms without any additional effort from your side, and it has some builtin redundancy. 144 * @par 145 * So, code that looked like this in the old days: 146 * @code 147 * wxString some_file = ConfigManager::GetScriptsFolder() + wxFILE_SEP_PATH + _T("startup.script"); 148 * @endcode 149 * should be converted to this: 150 * @code 151 * wxString some_file = ConfigManager::LocateDataFile(_T("startup.script"), sdScriptsUser | sdScriptsGlobal); 152 * @endcode 153 * This would try to locate the file named "startup.script" in the global and also in the user's scripts folders. 154 * @note User's dirs @b always have precedence over global dirs. 155 * 156 * @param filename name of the file to search for 157 * @param search_dirs A bit-mask of the folders to include in the search. 158 */ 159 static wxString LocateDataFile(const wxString& filename, int search_dirs = sdAllKnown); 160 161 /** @brief Access one of Code::Blocks' folders. 162 * @param dir The directory to return. 163 */ 164 static wxString GetFolder(SearchDirs dir); 165 166 /* Backwards compatible functions. For new code, please use GetFolder() instead. 167 * 168 * Query "standard" paths that work across platforms. 169 * NEVER hard-code a path like "C:\CodeBlocks\share\data". Always use one of the following functions to compose a path. 170 */ GetHomeFolder()171 static wxString GetHomeFolder() { return GetFolder(sdHome); } GetConfigFolder()172 static wxString GetConfigFolder(){ return GetFolder(sdConfig); } 173 static wxString GetPluginsFolder(bool global = true){ return GetFolder(global ? sdPluginsGlobal : sdPluginsUser); } 174 static wxString GetScriptsFolder(bool global = true){ return GetFolder(global ? sdScriptsGlobal : sdScriptsUser); } 175 static wxString GetDataFolder(bool global = true){ return GetFolder(global ? sdDataGlobal : sdDataUser); } GetExecutableFolder()176 static wxString GetExecutableFolder(){ return GetFolder(sdBase); } GetTempFolder()177 static wxString GetTempFolder(){ return GetFolder(sdTemp); } 178 179 /* 180 * Network proxy for HTTP/FTP transfers 181 */ 182 static wxString GetProxy(); 183 184 /* 185 * Builtin revision information 186 */ 187 static wxString GetRevisionString(); 188 static unsigned int GetRevisionNumber(); 189 static wxString GetSvnDate(); 190 ReadDataPath()191 static inline wxString ReadDataPath(){return GetDataFolder();} // use instead of cfg->Read("data_path"); ReadAppPath()192 static inline wxString ReadAppPath(){return GetExecutableFolder();} // use instead of cfg->Read("app_path"); 193 194 195 196 /* ----------------------------------------------------------------------------------------------------- 197 * Path functions for navigation within your configuration namespace 198 */ 199 wxString GetPath() const; 200 void SetPath(const wxString& strPath); 201 wxArrayString EnumerateSubPaths(const wxString& path); 202 wxArrayString EnumerateKeys(const wxString& path); 203 void DeleteSubPath(const wxString& strPath); 204 205 /* ----------------------------------------------------------------------------------------------------- 206 * Clear all nodes from your namespace or delete the namespace (removing it from the config file). 207 * WARNING: After Delete() returns, the pointer to your instance is invalid. Before you can call ANY member 208 * function of this class, you have to call Manager::Get()->GetConfigManager() for a valid reference again. 209 * Note that Delete() is inherently thread-unsafe. You delete an entire namespace of data as well as the object 210 * responsible of handling that data! Make sure you know what you do. 211 * This is even more true for DeleteAll() which you should really NEVER use. 212 */ 213 void Clear(); 214 void Delete(); 215 void DeleteAll(); 216 void Flush(); 217 218 /* ----------------------------------------------------------------------------------------------------- 219 * Standard primitives 220 */ 221 void Write(const wxString& name, const wxString& value, bool ignoreEmpty = false); 222 wxString Read(const wxString& key, const wxString& defaultVal = wxEmptyString); 223 bool Read(const wxString& key, wxString* str); 224 void Write(const wxString& key, const char* str); 225 226 void Write(const wxString& name, int value); 227 bool Read(const wxString& name, int* value); 228 int ReadInt(const wxString& name, int defaultVal = 0); 229 230 void Write(const wxString& name, bool value); 231 bool Read(const wxString& name, bool* value); 232 bool ReadBool(const wxString& name, bool defaultVal = false); 233 234 void Write(const wxString& name, double value); 235 bool Read(const wxString& name, double* value); 236 double ReadDouble(const wxString& name, double defaultVal = 0.0f); 237 238 /* ----------------------------------------------------------------------------------------------------- 239 * Set and unset keys, or test for existence. Note that these functions cannot be used to remove paths 240 * or test existence of paths (it may be used to implicitly create paths, though). 241 */ 242 bool Exists(const wxString& name); 243 void Set(const wxString& name); 244 void UnSet(const wxString& name); 245 246 /* ----------------------------------------------------------------------------------------------------- 247 * Compound objects 248 */ 249 void Write(const wxString& name, const wxArrayString& as); 250 void Read(const wxString& name, wxArrayString* as); 251 wxArrayString ReadArrayString(const wxString& name); 252 253 void WriteBinary(const wxString& name, const wxString& source); 254 void WriteBinary(const wxString& name, void* ptr, size_t len); 255 wxString ReadBinary(const wxString& name); 256 257 void Write(const wxString& name, const wxColour& c); 258 bool Read(const wxString& name, wxColour* value); 259 wxColour ReadColour(const wxString& name, const wxColour& defaultVal = *wxBLACK); 260 261 262 /* ----------------------------------------------------------------------------------------------------- 263 * Single serializable objects 264 */ 265 void Write(const wxString& name, const ISerializable& object); 266 bool Read(const wxString& name, ISerializable* object); 267 268 269 /* ----------------------------------------------------------------------------------------------------- 270 * Maps and sets of primitive types 271 */ 272 void Write(const wxString& name, const ConfigManagerContainer::StringToStringMap& map); 273 void Read(const wxString& name, ConfigManagerContainer::StringToStringMap* map); 274 ConfigManagerContainer::StringToStringMap ReadSSMap(const wxString& name); 275 276 void Write(const wxString& name, const ConfigManagerContainer::IntToStringMap& map); 277 void Read(const wxString& name, ConfigManagerContainer::IntToStringMap* map); 278 ConfigManagerContainer::IntToStringMap ReadISMap(const wxString& name); 279 280 void Write(const wxString& name, const ConfigManagerContainer::StringSet& set); 281 void Read(const wxString& name, ConfigManagerContainer::StringSet* map); 282 ConfigManagerContainer::StringSet ReadSSet(const wxString& name); 283 284 285 /* ----------------------------------------------------------------------------------------------------- 286 * Maps of serialized objects. You are responsible for deleting the objects in the map/set. 287 * 288 * Usage: 289 * ------ 290 * typedef std::map<wxString, MySerializableClass *> MyMap; 291 * MyMap objMap; 292 * cfg->Read("name", &objMap); 293 * map["somekey"]->DoSomething(); 294 */ 295 void Write(const wxString& name, const ConfigManagerContainer::SerializableObjectMap* map); 296 Read(const wxString & name,std::map<wxString,T * > * map)297 template <typename T> void Read(const wxString& name, std::map<wxString, T*> *map) 298 { 299 wxString key(name); 300 TiXmlHandle ph(AssertPath(key)); 301 TiXmlElement* e = 0; 302 if(TiXmlNode *n = ph.FirstChild(key.mb_str(wxConvUTF8)).FirstChild("objmap").Node()) 303 while(n->IterateChildren(e) && (e = n->IterateChildren(e)->ToElement())) 304 { 305 T *obj = new T; 306 obj->SerializeIn(wxBase64::Decode(cbC2U(e->FirstChild()->ToText()->Value()))); 307 (*map)[cbC2U(e->Value())] = obj; 308 } 309 } 310 }; 311 312 /** Wrapper class for reading or writing config values, without the need for the full path. 313 * It provides a way to sandbox a part of the code from the namespace details 314 * or the full path used to access the config values. 315 */ 316 class DLLIMPORT ConfigManagerWrapper 317 { 318 public: ConfigManagerWrapper()319 ConfigManagerWrapper() {} ConfigManagerWrapper(wxString namespace_,wxString basepath)320 ConfigManagerWrapper(wxString namespace_, wxString basepath) : m_namespace(namespace_), m_basepath(basepath) 321 { 322 if (!m_basepath.EndsWith(wxT("/"))) 323 m_basepath += wxT("/"); 324 } IsValid()325 bool IsValid() const { return !m_namespace.empty(); } GetBasepath()326 const wxString& GetBasepath() const { return m_basepath; } 327 328 void Write(const wxString& name, const wxString& value, bool ignoreEmpty = false); 329 wxString Read(const wxString& key, const wxString& defaultVal = wxEmptyString); 330 331 bool Read(const wxString& key, wxString* str); 332 void Write(const wxString& key, const char* str); 333 334 void Write(const wxString& name, int value); 335 bool Read(const wxString& name, int* value); 336 int ReadInt(const wxString& name, int defaultVal = 0); 337 338 void Write(const wxString& name, bool value); 339 bool Read(const wxString& name, bool* value); 340 bool ReadBool(const wxString& name, bool defaultVal = false); 341 342 void Write(const wxString& name, double value); 343 bool Read(const wxString& name, double* value); 344 double ReadDouble(const wxString& name, double defaultVal = 0.0f); 345 346 private: 347 wxString m_namespace; 348 wxString m_basepath; 349 }; 350 351 /// Read the list of batch build plugins and return them. The list won't be empty; at least the compiler plugin will be 352 /// added to the to it. The list contain the library names of the plugins and differs on every OS. 353 DLLIMPORT wxArrayString cbReadBatchBuildPlugins(); 354 /// Write the list of batch build plugins in the config. 355 /// @param bbpluigns List of library plugin names. 356 /// @param messageBoxParent Set as a parent to the message box that will be shown in case of errors. 357 DLLIMPORT void cbWriteBatchBuildPlugins(wxArrayString bbplugins, wxWindow *messageBoxParent); 358 359 /* ------------------------------------------------------------------------------------------------------------------ 360 * "Builder pattern" class for ConfigManager 361 * 362 * ################################################################ 363 * ###### Do not use this class. Do not even think about it. ###### 364 * ################################################################ 365 * 366 * ---> use Manager::Get()->GetConfigManager("yournamespace") instead. 367 * 368 * Manager::Get()->GetConfigManager("yournamespace") is guaranteed to always work while 369 * the builder class and its interfaces may be changed any time without prior notice. 370 */ 371 372 WX_DECLARE_STRING_HASH_MAP(ConfigManager*, NamespaceMap); 373 374 class DLLIMPORT CfgMgrBldr : public Mgr<CfgMgrBldr> 375 { 376 friend class ConfigManager; 377 friend class Mgr<CfgMgrBldr>; 378 NamespaceMap namespaces; 379 TiXmlDocument *doc; 380 TiXmlDocument *volatile_doc; 381 wxCriticalSection cs; 382 bool r; 383 wxString cfg; 384 385 void Flush(); 386 void Close(); 387 void SwitchTo(const wxString& absFN); 388 void SwitchToR(const wxString& absFN); 389 ConfigManager* Build(const wxString& name_space); 390 wxString FindConfigFile(const wxString& filename); 391 wxString DetermineExecutablePath(); 392 protected: 393 CfgMgrBldr(); 394 ~CfgMgrBldr() override; 395 396 public: 397 static ConfigManager* GetConfigManager(const wxString& name_space); 398 399 /// Return the path to the current configuration file. 400 /// This should be used only to print it in the log during start up. 401 wxString GetConfigFile() const; 402 }; 403 404 #endif 405 406