| 1 | /////////////////////////////////////////////////////////////////////////////// |
| 2 | // Name: wx/confbase.h |
| 3 | // Purpose: declaration of the base class of all config implementations |
| 4 | // (see also: fileconf.h and msw/regconf.h and iniconf.h) |
| 5 | // Author: Karsten Ballueder & Vadim Zeitlin |
| 6 | // Modified by: |
| 7 | // Created: 07.04.98 (adapted from appconf.h) |
| 8 | // RCS-ID: $Id$ |
| 9 | // Copyright: (c) 1997 Karsten Ballueder Ballueder@usa.net |
| 10 | // Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> |
| 11 | // Licence: wxWindows licence |
| 12 | /////////////////////////////////////////////////////////////////////////////// |
| 13 | |
| 14 | #ifndef _WX_CONFBASE_H_ |
| 15 | #define _WX_CONFBASE_H_ |
| 16 | |
| 17 | #include "wx/defs.h" |
| 18 | #include "wx/string.h" |
| 19 | #include "wx/object.h" |
| 20 | #include "wx/base64.h" |
| 21 | |
| 22 | class WXDLLIMPEXP_FWD_BASE wxArrayString; |
| 23 | |
| 24 | // ---------------------------------------------------------------------------- |
| 25 | // constants |
| 26 | // ---------------------------------------------------------------------------- |
| 27 | |
| 28 | /// shall we be case sensitive in parsing variable names? |
| 29 | #ifndef wxCONFIG_CASE_SENSITIVE |
| 30 | #define wxCONFIG_CASE_SENSITIVE 0 |
| 31 | #endif |
| 32 | |
| 33 | /// separates group and entry names (probably shouldn't be changed) |
| 34 | #ifndef wxCONFIG_PATH_SEPARATOR |
| 35 | #define wxCONFIG_PATH_SEPARATOR wxT('/') |
| 36 | #endif |
| 37 | |
| 38 | /// introduces immutable entries |
| 39 | // (i.e. the ones which can't be changed from the local config file) |
| 40 | #ifndef wxCONFIG_IMMUTABLE_PREFIX |
| 41 | #define wxCONFIG_IMMUTABLE_PREFIX wxT('!') |
| 42 | #endif |
| 43 | |
| 44 | #if wxUSE_CONFIG |
| 45 | |
| 46 | /// should we use registry instead of configuration files under Windows? |
| 47 | // (i.e. whether wxConfigBase::Create() will create a wxFileConfig (if it's |
| 48 | // false) or wxRegConfig (if it's true and we're under Win32)) |
| 49 | #ifndef wxUSE_CONFIG_NATIVE |
| 50 | #define wxUSE_CONFIG_NATIVE 1 |
| 51 | #endif |
| 52 | |
| 53 | // not all compilers can deal with template Read/Write() methods, define this |
| 54 | // symbol if the template functions are available |
| 55 | #if (!defined(__VISUALC__) || __VISUALC__ > 1200) && \ |
| 56 | !defined( __VMS ) && \ |
| 57 | !(defined(__HP_aCC) && defined(__hppa)) && \ |
| 58 | !defined (__DMC__) |
| 59 | #define wxHAS_CONFIG_TEMPLATE_RW |
| 60 | #endif |
| 61 | |
| 62 | // Style flags for constructor style parameter |
| 63 | enum |
| 64 | { |
| 65 | wxCONFIG_USE_LOCAL_FILE = 1, |
| 66 | wxCONFIG_USE_GLOBAL_FILE = 2, |
| 67 | wxCONFIG_USE_RELATIVE_PATH = 4, |
| 68 | wxCONFIG_USE_NO_ESCAPE_CHARACTERS = 8, |
| 69 | wxCONFIG_USE_SUBDIR = 16 |
| 70 | }; |
| 71 | |
| 72 | // ---------------------------------------------------------------------------- |
| 73 | // abstract base class wxConfigBase which defines the interface for derived |
| 74 | // classes |
| 75 | // |
| 76 | // wxConfig organizes the items in a tree-like structure (modelled after the |
| 77 | // Unix/Dos filesystem). There are groups (directories) and keys (files). |
| 78 | // There is always one current group given by the current path. |
| 79 | // |
| 80 | // Keys are pairs "key_name = value" where value may be of string or integer |
| 81 | // (long) type (TODO doubles and other types such as wxDate coming soon). |
| 82 | // ---------------------------------------------------------------------------- |
| 83 | |
| 84 | class WXDLLIMPEXP_BASE wxConfigBase : public wxObject |
| 85 | { |
| 86 | public: |
| 87 | // constants |
| 88 | // the type of an entry |
| 89 | enum EntryType |
| 90 | { |
| 91 | Type_Unknown, |
| 92 | Type_String, |
| 93 | Type_Boolean, |
| 94 | Type_Integer, // use Read(long *) |
| 95 | Type_Float // use Read(double *) |
| 96 | }; |
| 97 | |
| 98 | // static functions |
| 99 | // sets the config object, returns the previous pointer |
| 100 | static wxConfigBase *Set(wxConfigBase *pConfig); |
| 101 | // get the config object, creates it on demand unless DontCreateOnDemand |
| 102 | // was called |
| 103 | static wxConfigBase *Get(bool createOnDemand = true) |
| 104 | { if ( createOnDemand && (!ms_pConfig) ) Create(); return ms_pConfig; } |
| 105 | // create a new config object: this function will create the "best" |
| 106 | // implementation of wxConfig available for the current platform, see |
| 107 | // comments near definition wxUSE_CONFIG_NATIVE for details. It returns |
| 108 | // the created object and also sets it as ms_pConfig. |
| 109 | static wxConfigBase *Create(); |
| 110 | // should Get() try to create a new log object if the current one is NULL? |
| 111 | static void DontCreateOnDemand() { ms_bAutoCreate = false; } |
| 112 | |
| 113 | // ctor & virtual dtor |
| 114 | // ctor (can be used as default ctor too) |
| 115 | // |
| 116 | // Not all args will always be used by derived classes, but including |
| 117 | // them all in each class ensures compatibility. If appName is empty, |
| 118 | // uses wxApp name |
| 119 | wxConfigBase(const wxString& appName = wxEmptyString, |
| 120 | const wxString& vendorName = wxEmptyString, |
| 121 | const wxString& localFilename = wxEmptyString, |
| 122 | const wxString& globalFilename = wxEmptyString, |
| 123 | long style = 0); |
| 124 | |
| 125 | // empty but ensures that dtor of all derived classes is virtual |
| 126 | virtual ~wxConfigBase(); |
| 127 | |
| 128 | // path management |
| 129 | // set current path: if the first character is '/', it's the absolute path, |
| 130 | // otherwise it's a relative path. '..' is supported. If the strPath |
| 131 | // doesn't exist it is created. |
| 132 | virtual void SetPath(const wxString& strPath) = 0; |
| 133 | // retrieve the current path (always as absolute path) |
| 134 | virtual const wxString& GetPath() const = 0; |
| 135 | |
| 136 | // enumeration: all functions here return false when there are no more items. |
| 137 | // you must pass the same lIndex to GetNext and GetFirst (don't modify it) |
| 138 | // enumerate subgroups |
| 139 | virtual bool GetFirstGroup(wxString& str, long& lIndex) const = 0; |
| 140 | virtual bool GetNextGroup (wxString& str, long& lIndex) const = 0; |
| 141 | // enumerate entries |
| 142 | virtual bool GetFirstEntry(wxString& str, long& lIndex) const = 0; |
| 143 | virtual bool GetNextEntry (wxString& str, long& lIndex) const = 0; |
| 144 | // get number of entries/subgroups in the current group, with or without |
| 145 | // it's subgroups |
| 146 | virtual size_t GetNumberOfEntries(bool bRecursive = false) const = 0; |
| 147 | virtual size_t GetNumberOfGroups(bool bRecursive = false) const = 0; |
| 148 | |
| 149 | // tests of existence |
| 150 | // returns true if the group by this name exists |
| 151 | virtual bool HasGroup(const wxString& strName) const = 0; |
| 152 | // same as above, but for an entry |
| 153 | virtual bool HasEntry(const wxString& strName) const = 0; |
| 154 | // returns true if either a group or an entry with a given name exist |
| 155 | bool Exists(const wxString& strName) const |
| 156 | { return HasGroup(strName) || HasEntry(strName); } |
| 157 | |
| 158 | // get the entry type |
| 159 | virtual EntryType GetEntryType(const wxString& name) const |
| 160 | { |
| 161 | // by default all entries are strings |
| 162 | return HasEntry(name) ? Type_String : Type_Unknown; |
| 163 | } |
| 164 | |
| 165 | // key access: returns true if value was really read, false if default used |
| 166 | // (and if the key is not found the default value is returned.) |
| 167 | |
| 168 | // read a string from the key |
| 169 | bool Read(const wxString& key, wxString *pStr) const; |
| 170 | bool Read(const wxString& key, wxString *pStr, const wxString& defVal) const; |
| 171 | |
| 172 | // read a number (long) |
| 173 | bool Read(const wxString& key, long *pl) const; |
| 174 | bool Read(const wxString& key, long *pl, long defVal) const; |
| 175 | |
| 176 | // read an int (wrapper around `long' version) |
| 177 | bool Read(const wxString& key, int *pi) const; |
| 178 | bool Read(const wxString& key, int *pi, int defVal) const; |
| 179 | |
| 180 | // read a double |
| 181 | bool Read(const wxString& key, double* val) const; |
| 182 | bool Read(const wxString& key, double* val, double defVal) const; |
| 183 | |
| 184 | // read a float |
| 185 | bool Read(const wxString& key, float* val) const; |
| 186 | bool Read(const wxString& key, float* val, float defVal) const; |
| 187 | |
| 188 | // read a bool |
| 189 | bool Read(const wxString& key, bool* val) const; |
| 190 | bool Read(const wxString& key, bool* val, bool defVal) const; |
| 191 | |
| 192 | #if wxUSE_BASE64 |
| 193 | // read a binary data block |
| 194 | bool Read(const wxString& key, wxMemoryBuffer* data) const |
| 195 | { return DoReadBinary(key, data); } |
| 196 | // no default version since it does not make sense for binary data |
| 197 | #endif // wxUSE_BASE64 |
| 198 | |
| 199 | #ifdef wxHAS_CONFIG_TEMPLATE_RW |
| 200 | // read other types, for which wxFromString is defined |
| 201 | template <typename T> |
| 202 | bool Read(const wxString& key, T* value) const |
| 203 | { |
| 204 | wxString s; |
| 205 | if ( !Read(key, &s) ) |
| 206 | return false; |
| 207 | return wxFromString(s, value); |
| 208 | } |
| 209 | |
| 210 | template <typename T> |
| 211 | bool Read(const wxString& key, T* value, const T& defVal) const |
| 212 | { |
| 213 | const bool found = Read(key, value); |
| 214 | if ( !found ) |
| 215 | { |
| 216 | if (IsRecordingDefaults()) |
| 217 | ((wxConfigBase *)this)->Write(key, defVal); |
| 218 | *value = defVal; |
| 219 | } |
| 220 | return found; |
| 221 | } |
| 222 | #endif // wxHAS_CONFIG_TEMPLATE_RW |
| 223 | |
| 224 | // convenience functions returning directly the value |
| 225 | wxString Read(const wxString& key, |
| 226 | const wxString& defVal = wxEmptyString) const |
| 227 | { wxString s; (void)Read(key, &s, defVal); return s; } |
| 228 | |
| 229 | // we have to provide a separate version for C strings as otherwise the |
| 230 | // template Read() would be used |
| 231 | wxString Read(const wxString& key, const char* defVal) const |
| 232 | { return Read(key, wxString(defVal)); } |
| 233 | wxString Read(const wxString& key, const wchar_t* defVal) const |
| 234 | { return Read(key, wxString(defVal)); } |
| 235 | |
| 236 | long ReadLong(const wxString& key, long defVal) const |
| 237 | { long l; (void)Read(key, &l, defVal); return l; } |
| 238 | |
| 239 | double ReadDouble(const wxString& key, double defVal) const |
| 240 | { double d; (void)Read(key, &d, defVal); return d; } |
| 241 | |
| 242 | bool ReadBool(const wxString& key, bool defVal) const |
| 243 | { bool b; (void)Read(key, &b, defVal); return b; } |
| 244 | |
| 245 | template <typename T> |
| 246 | T ReadObject(const wxString& key, T const& defVal) const |
| 247 | { T t; (void)Read(key, &t, defVal); return t; } |
| 248 | |
| 249 | // for compatibility with wx 2.8 |
| 250 | long Read(const wxString& key, long defVal) const |
| 251 | { return ReadLong(key, defVal); } |
| 252 | |
| 253 | |
| 254 | // write the value (return true on success) |
| 255 | bool Write(const wxString& key, const wxString& value) |
| 256 | { return DoWriteString(key, value); } |
| 257 | |
| 258 | bool Write(const wxString& key, long value) |
| 259 | { return DoWriteLong(key, value); } |
| 260 | |
| 261 | bool Write(const wxString& key, double value) |
| 262 | { return DoWriteDouble(key, value); } |
| 263 | |
| 264 | bool Write(const wxString& key, bool value) |
| 265 | { return DoWriteBool(key, value); } |
| 266 | |
| 267 | #if wxUSE_BASE64 |
| 268 | bool Write(const wxString& key, const wxMemoryBuffer& buf) |
| 269 | { return DoWriteBinary(key, buf); } |
| 270 | #endif // wxUSE_BASE64 |
| 271 | |
| 272 | // we have to provide a separate version for C strings as otherwise they |
| 273 | // would be converted to bool and not to wxString as expected! |
| 274 | bool Write(const wxString& key, const char *value) |
| 275 | { return Write(key, wxString(value)); } |
| 276 | bool Write(const wxString& key, const unsigned char *value) |
| 277 | { return Write(key, wxString(value)); } |
| 278 | bool Write(const wxString& key, const wchar_t *value) |
| 279 | { return Write(key, wxString(value)); } |
| 280 | |
| 281 | |
| 282 | // we also have to provide specializations for other types which we want to |
| 283 | // handle using the specialized DoWriteXXX() instead of the generic template |
| 284 | // version below |
| 285 | bool Write(const wxString& key, char value) |
| 286 | { return DoWriteLong(key, value); } |
| 287 | |
| 288 | bool Write(const wxString& key, unsigned char value) |
| 289 | { return DoWriteLong(key, value); } |
| 290 | |
| 291 | bool Write(const wxString& key, short value) |
| 292 | { return DoWriteLong(key, value); } |
| 293 | |
| 294 | bool Write(const wxString& key, unsigned short value) |
| 295 | { return DoWriteLong(key, value); } |
| 296 | |
| 297 | bool Write(const wxString& key, unsigned int value) |
| 298 | { return DoWriteLong(key, value); } |
| 299 | |
| 300 | bool Write(const wxString& key, int value) |
| 301 | { return DoWriteLong(key, value); } |
| 302 | |
| 303 | bool Write(const wxString& key, unsigned long value) |
| 304 | { return DoWriteLong(key, value); } |
| 305 | |
| 306 | bool Write(const wxString& key, float value) |
| 307 | { return DoWriteDouble(key, value); } |
| 308 | |
| 309 | // Causes ambiguities in VC++ 6 and OpenVMS (at least) |
| 310 | #if ( (!defined(__VISUALC__) || __VISUALC__ > 1200) && !defined( __VMS ) && !defined (__DMC__)) |
| 311 | // for other types, use wxToString() |
| 312 | template <typename T> |
| 313 | bool Write(const wxString& key, T const& value) |
| 314 | { return Write(key, wxToString(value)); } |
| 315 | #endif |
| 316 | |
| 317 | // permanently writes all changes |
| 318 | virtual bool Flush(bool bCurrentOnly = false) = 0; |
| 319 | |
| 320 | // renaming, all functions return false on failure (probably because the new |
| 321 | // name is already taken by an existing entry) |
| 322 | // rename an entry |
| 323 | virtual bool RenameEntry(const wxString& oldName, |
| 324 | const wxString& newName) = 0; |
| 325 | // rename a group |
| 326 | virtual bool RenameGroup(const wxString& oldName, |
| 327 | const wxString& newName) = 0; |
| 328 | |
| 329 | // delete entries/groups |
| 330 | // deletes the specified entry and the group it belongs to if |
| 331 | // it was the last key in it and the second parameter is true |
| 332 | virtual bool DeleteEntry(const wxString& key, |
| 333 | bool bDeleteGroupIfEmpty = true) = 0; |
| 334 | // delete the group (with all subgroups) |
| 335 | virtual bool DeleteGroup(const wxString& key) = 0; |
| 336 | // delete the whole underlying object (disk file, registry key, ...) |
| 337 | // primarily for use by uninstallation routine. |
| 338 | virtual bool DeleteAll() = 0; |
| 339 | |
| 340 | // options |
| 341 | // we can automatically expand environment variables in the config entries |
| 342 | // (this option is on by default, you can turn it on/off at any time) |
| 343 | bool IsExpandingEnvVars() const { return m_bExpandEnvVars; } |
| 344 | void SetExpandEnvVars(bool bDoIt = true) { m_bExpandEnvVars = bDoIt; } |
| 345 | // recording of default values |
| 346 | void SetRecordDefaults(bool bDoIt = true) { m_bRecordDefaults = bDoIt; } |
| 347 | bool IsRecordingDefaults() const { return m_bRecordDefaults; } |
| 348 | // does expansion only if needed |
| 349 | wxString ExpandEnvVars(const wxString& str) const; |
| 350 | |
| 351 | // misc accessors |
| 352 | wxString GetAppName() const { return m_appName; } |
| 353 | wxString GetVendorName() const { return m_vendorName; } |
| 354 | |
| 355 | // Used wxIniConfig to set members in constructor |
| 356 | void SetAppName(const wxString& appName) { m_appName = appName; } |
| 357 | void SetVendorName(const wxString& vendorName) { m_vendorName = vendorName; } |
| 358 | |
| 359 | void SetStyle(long style) { m_style = style; } |
| 360 | long GetStyle() const { return m_style; } |
| 361 | |
| 362 | protected: |
| 363 | static bool IsImmutable(const wxString& key) |
| 364 | { return !key.IsEmpty() && key[0] == wxCONFIG_IMMUTABLE_PREFIX; } |
| 365 | |
| 366 | // return the path without trailing separator, if any: this should be called |
| 367 | // to sanitize paths referring to the group names before passing them to |
| 368 | // wxConfigPathChanger as "/foo/bar/" should be the same as "/foo/bar" and it |
| 369 | // isn't interpreted in the same way by it (and this can't be changed there |
| 370 | // as it's not the same for the entries names) |
| 371 | static wxString RemoveTrailingSeparator(const wxString& key); |
| 372 | |
| 373 | // do read/write the values of different types |
| 374 | virtual bool DoReadString(const wxString& key, wxString *pStr) const = 0; |
| 375 | virtual bool DoReadLong(const wxString& key, long *pl) const = 0; |
| 376 | virtual bool DoReadDouble(const wxString& key, double* val) const; |
| 377 | virtual bool DoReadBool(const wxString& key, bool* val) const; |
| 378 | #if wxUSE_BASE64 |
| 379 | virtual bool DoReadBinary(const wxString& key, wxMemoryBuffer* buf) const = 0; |
| 380 | #endif // wxUSE_BASE64 |
| 381 | |
| 382 | virtual bool DoWriteString(const wxString& key, const wxString& value) = 0; |
| 383 | virtual bool DoWriteLong(const wxString& key, long value) = 0; |
| 384 | virtual bool DoWriteDouble(const wxString& key, double value); |
| 385 | virtual bool DoWriteBool(const wxString& key, bool value); |
| 386 | #if wxUSE_BASE64 |
| 387 | virtual bool DoWriteBinary(const wxString& key, const wxMemoryBuffer& buf) = 0; |
| 388 | #endif // wxUSE_BASE64 |
| 389 | |
| 390 | private: |
| 391 | // are we doing automatic environment variable expansion? |
| 392 | bool m_bExpandEnvVars; |
| 393 | // do we record default values? |
| 394 | bool m_bRecordDefaults; |
| 395 | |
| 396 | // static variables |
| 397 | static wxConfigBase *ms_pConfig; |
| 398 | static bool ms_bAutoCreate; |
| 399 | |
| 400 | // Application name and organisation name |
| 401 | wxString m_appName; |
| 402 | wxString m_vendorName; |
| 403 | |
| 404 | // Style flag |
| 405 | long m_style; |
| 406 | |
| 407 | DECLARE_ABSTRACT_CLASS(wxConfigBase) |
| 408 | }; |
| 409 | |
| 410 | // a handy little class which changes current path to the path of given entry |
| 411 | // and restores it in dtor: so if you declare a local variable of this type, |
| 412 | // you work in the entry directory and the path is automatically restored |
| 413 | // when the function returns |
| 414 | // Taken out of wxConfig since not all compilers can cope with nested classes. |
| 415 | class WXDLLIMPEXP_BASE wxConfigPathChanger |
| 416 | { |
| 417 | public: |
| 418 | // ctor/dtor do path changing/restoring of the path |
| 419 | wxConfigPathChanger(const wxConfigBase *pContainer, const wxString& strEntry); |
| 420 | ~wxConfigPathChanger(); |
| 421 | |
| 422 | // get the key name |
| 423 | const wxString& Name() const { return m_strName; } |
| 424 | |
| 425 | // this method must be called if the original path (i.e. the current path at |
| 426 | // the moment of creation of this object) could have been deleted to prevent |
| 427 | // us from restoring the not existing (any more) path |
| 428 | // |
| 429 | // if the original path doesn't exist any more, the path will be restored to |
| 430 | // the deepest still existing component of the old path |
| 431 | void UpdateIfDeleted(); |
| 432 | |
| 433 | private: |
| 434 | wxConfigBase *m_pContainer; // object we live in |
| 435 | wxString m_strName, // name of entry (i.e. name only) |
| 436 | m_strOldPath; // saved path |
| 437 | bool m_bChanged; // was the path changed? |
| 438 | |
| 439 | wxDECLARE_NO_COPY_CLASS(wxConfigPathChanger); |
| 440 | }; |
| 441 | |
| 442 | |
| 443 | #endif // wxUSE_CONFIG |
| 444 | |
| 445 | /* |
| 446 | Replace environment variables ($SOMETHING) with their values. The format is |
| 447 | $VARNAME or ${VARNAME} where VARNAME contains alphanumeric characters and |
| 448 | '_' only. '$' must be escaped ('\$') in order to be taken literally. |
| 449 | */ |
| 450 | |
| 451 | WXDLLIMPEXP_BASE wxString wxExpandEnvVars(const wxString &sz); |
| 452 | |
| 453 | /* |
| 454 | Split path into parts removing '..' in progress |
| 455 | */ |
| 456 | WXDLLIMPEXP_BASE void wxSplitPath(wxArrayString& aParts, const wxString& path); |
| 457 | |
| 458 | #endif // _WX_CONFBASE_H_ |
| 459 | |