]>
Commit | Line | Data |
---|---|---|
1 | /////////////////////////////////////////////////////////////////////////////// | |
2 | // Name: 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 _T('/') | |
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 _T('!') | |
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 (modeled 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 bool | |
185 | bool Read(const wxString& key, bool* val) const; | |
186 | bool Read(const wxString& key, bool* val, bool defVal) const; | |
187 | ||
188 | #if wxUSE_BASE64 | |
189 | // read a binary data block | |
190 | bool Read(const wxString& key, wxMemoryBuffer* data) const | |
191 | { return DoReadBinary(key, data); } | |
192 | // no default version since it does not make sense for binary data | |
193 | #endif // wxUSE_BASE64 | |
194 | ||
195 | #ifdef wxHAS_CONFIG_TEMPLATE_RW | |
196 | // read other types, for which wxFromString is defined | |
197 | template <typename T> | |
198 | bool Read(const wxString& key, T* value) const | |
199 | { | |
200 | wxString s; | |
201 | if ( !Read(key, &s) ) | |
202 | return false; | |
203 | return wxFromString(s, value); | |
204 | } | |
205 | ||
206 | template <typename T> | |
207 | bool Read(const wxString& key, T* value, const T& defVal) const | |
208 | { | |
209 | const bool found = Read(key, value); | |
210 | if ( !found ) | |
211 | { | |
212 | if (IsRecordingDefaults()) | |
213 | ((wxConfigBase *)this)->Write(key, defVal); | |
214 | *value = defVal; | |
215 | } | |
216 | return found; | |
217 | } | |
218 | #endif // wxHAS_CONFIG_TEMPLATE_RW | |
219 | ||
220 | // convenience functions returning directly the value | |
221 | wxString Read(const wxString& key, | |
222 | const wxString& defVal = wxEmptyString) const | |
223 | { wxString s; (void)Read(key, &s, defVal); return s; } | |
224 | ||
225 | // we have to provide a separate version for C strings as otherwise the | |
226 | // template Read() would be used | |
227 | wxString Read(const wxString& key, const char* defVal) const | |
228 | { return Read(key, wxString(defVal)); } | |
229 | #if wxUSE_WCHAR_T | |
230 | wxString Read(const wxString& key, const wchar_t* defVal) const | |
231 | { return Read(key, wxString(defVal)); } | |
232 | #endif | |
233 | ||
234 | long ReadLong(const wxString& key, long defVal) const | |
235 | { long l; (void)Read(key, &l, defVal); return l; } | |
236 | ||
237 | double ReadDouble(const wxString& key, double defVal) const | |
238 | { double d; (void)Read(key, &d, defVal); return d; } | |
239 | ||
240 | bool ReadBool(const wxString& key, bool defVal) const | |
241 | { bool b; (void)Read(key, &b, defVal); return b; } | |
242 | ||
243 | template <typename T> | |
244 | T ReadObject(const wxString& key, T const& defVal) const | |
245 | { T t; (void)Read(key, &t, defVal); return t; } | |
246 | ||
247 | // for compatibility with wx 2.8 | |
248 | long Read(const wxString& key, long defVal) const | |
249 | { return ReadLong(key, defVal); } | |
250 | ||
251 | ||
252 | // write the value (return true on success) | |
253 | bool Write(const wxString& key, const wxString& value) | |
254 | { return DoWriteString(key, value); } | |
255 | ||
256 | bool Write(const wxString& key, long value) | |
257 | { return DoWriteLong(key, value); } | |
258 | ||
259 | bool Write(const wxString& key, double value) | |
260 | { return DoWriteDouble(key, value); } | |
261 | ||
262 | bool Write(const wxString& key, bool value) | |
263 | { return DoWriteBool(key, value); } | |
264 | ||
265 | #if wxUSE_BASE64 | |
266 | bool Write(const wxString& key, const wxMemoryBuffer& buf) | |
267 | { return DoWriteBinary(key, buf); } | |
268 | #endif // wxUSE_BASE64 | |
269 | ||
270 | // we have to provide a separate version for C strings as otherwise they | |
271 | // would be converted to bool and not to wxString as expected! | |
272 | bool Write(const wxString& key, const char *value) | |
273 | { return Write(key, wxString(value)); } | |
274 | bool Write(const wxString& key, const unsigned char *value) | |
275 | { return Write(key, wxString(value)); } | |
276 | #if wxUSE_WCHAR_T | |
277 | bool Write(const wxString& key, const wchar_t *value) | |
278 | { return Write(key, wxString(value)); } | |
279 | #endif | |
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 |