|
1 /****************************************************************************** |
|
2 * |
|
3 * |
|
4 * |
|
5 * |
|
6 * Copyright (C) 1997-2008 by Dimitri van Heesch. |
|
7 * |
|
8 * Permission to use, copy, modify, and distribute this software and its |
|
9 * documentation under the terms of the GNU General Public License is hereby |
|
10 * granted. No representations are made about the suitability of this software |
|
11 * for any purpose. It is provided "as is" without express or implied warranty. |
|
12 * See the GNU General Public License for more details. |
|
13 * |
|
14 * Documents produced by Doxygen are derivative works derived from the |
|
15 * input used in their production; they are not affected by this license. |
|
16 * |
|
17 */ |
|
18 |
|
19 #ifndef CONFIG_H |
|
20 #define CONFIG_H |
|
21 |
|
22 #include "qtbc.h" |
|
23 #include <qstrlist.h> |
|
24 #include <qfile.h> |
|
25 #include <qdict.h> |
|
26 #include <qlist.h> |
|
27 #include <qtextstream.h> |
|
28 |
|
29 /*! \brief Abstract base class for any configuration option. |
|
30 * |
|
31 */ |
|
32 class ConfigOption |
|
33 { |
|
34 friend class Config; |
|
35 |
|
36 public: |
|
37 |
|
38 /*! The type of option */ |
|
39 enum OptionType |
|
40 { |
|
41 O_Info, //<! A section header |
|
42 O_List, //<! A list of items |
|
43 O_Enum, //<! A fixed set of items |
|
44 O_String, //<! A single item |
|
45 O_Int, //<! An integer value |
|
46 O_Bool, //<! A boolean value |
|
47 O_Obsolete //<! An obsolete option |
|
48 }; |
|
49 enum |
|
50 { |
|
51 /*! Maximum length of an option in the config file. Used for |
|
52 * alignment purposes. |
|
53 */ |
|
54 MAX_OPTION_LENGTH = 23 |
|
55 }; |
|
56 ConfigOption(OptionType t) : m_kind(t) |
|
57 { |
|
58 m_spaces.fill(' ',40); |
|
59 } |
|
60 virtual ~ConfigOption() |
|
61 { |
|
62 } |
|
63 |
|
64 /*! returns the kind of option this is. */ |
|
65 OptionType kind() const { return m_kind; } |
|
66 QCString name() const { return m_name; } |
|
67 QCString docs() const { return m_doc; } |
|
68 |
|
69 QCString dependsOn() const { return m_dependency; } |
|
70 void addDependency(const char *dep) { m_dependency = dep; } |
|
71 void setEncoding(const QCString &e) { m_encoding = e; } |
|
72 |
|
73 protected: |
|
74 virtual void writeTemplate(QTextStream &t,bool sl,bool upd) = 0; |
|
75 virtual void convertStrToVal() {} |
|
76 virtual void substEnvVars() = 0; |
|
77 virtual void writeXML(QTextStream&) {} |
|
78 virtual void init() {} |
|
79 |
|
80 QCString convertToComment(const QCString &s); |
|
81 void writeBoolValue(QTextStream &t,bool v); |
|
82 void writeIntValue(QTextStream &t,int i); |
|
83 void writeStringValue(QTextStream &t,QCString &s); |
|
84 void writeStringList(QTextStream &t,QStrList &l); |
|
85 |
|
86 QCString m_spaces; |
|
87 QCString m_name; |
|
88 QCString m_doc; |
|
89 QCString m_dependency; |
|
90 QCString m_encoding; |
|
91 OptionType m_kind; |
|
92 }; |
|
93 |
|
94 /*! \brief Section marker for grouping the configuration options |
|
95 * |
|
96 */ |
|
97 class ConfigInfo : public ConfigOption |
|
98 { |
|
99 public: |
|
100 ConfigInfo(const char *name,const char *doc) |
|
101 : ConfigOption(O_Info) |
|
102 { |
|
103 m_name = name; |
|
104 m_doc = doc; |
|
105 } |
|
106 void writeTemplate(QTextStream &t, bool sl,bool) |
|
107 { |
|
108 if (!sl) |
|
109 { |
|
110 t << "\n"; |
|
111 } |
|
112 t << "#---------------------------------------------------------------------------\n"; |
|
113 t << "# " << m_doc << endl; |
|
114 t << "#---------------------------------------------------------------------------\n"; |
|
115 } |
|
116 void substEnvVars() {} |
|
117 }; |
|
118 |
|
119 /*! \brief Option of the list type. |
|
120 * |
|
121 */ |
|
122 class ConfigList : public ConfigOption |
|
123 { |
|
124 public: |
|
125 enum WidgetType { String, File, Dir, FileAndDir }; |
|
126 ConfigList(const char *name,const char *doc) |
|
127 : ConfigOption(O_List) |
|
128 { |
|
129 m_name = name; |
|
130 m_doc = doc; |
|
131 m_widgetType = String; |
|
132 } |
|
133 void addValue(const char *v) { m_value.append(v); } |
|
134 void setWidgetType(WidgetType w) { m_widgetType = w; } |
|
135 WidgetType widgetType() const { return m_widgetType; } |
|
136 QStrList *valueRef() { return &m_value; } |
|
137 void writeTemplate(QTextStream &t,bool sl,bool) |
|
138 { |
|
139 if (!sl) |
|
140 { |
|
141 t << endl; |
|
142 t << convertToComment(m_doc); |
|
143 t << endl; |
|
144 } |
|
145 t << m_name << m_spaces.left(MAX_OPTION_LENGTH-m_name.length()) << "="; |
|
146 writeStringList(t,m_value); |
|
147 t << "\n"; |
|
148 } |
|
149 void substEnvVars(); |
|
150 void writeXML(QTextStream&); |
|
151 void init() { m_value.clear(); } |
|
152 private: |
|
153 QStrList m_value; |
|
154 WidgetType m_widgetType; |
|
155 }; |
|
156 |
|
157 /*! \brief Option of the enum type. |
|
158 * |
|
159 */ |
|
160 class ConfigEnum : public ConfigOption |
|
161 { |
|
162 public: |
|
163 ConfigEnum(const char *name,const char *doc,const char *defVal) |
|
164 : ConfigOption(O_Enum) |
|
165 { |
|
166 m_name = name; |
|
167 m_doc = doc; |
|
168 m_value = defVal; |
|
169 m_defValue = defVal; |
|
170 } |
|
171 void addValue(const char *v) { m_valueRange.append(v); } |
|
172 QStrListIterator iterator() |
|
173 { |
|
174 return QStrListIterator(m_valueRange); |
|
175 } |
|
176 QCString *valueRef() { return &m_value; } |
|
177 void substEnvVars(); |
|
178 void writeTemplate(QTextStream &t,bool sl,bool) |
|
179 { |
|
180 if (!sl) |
|
181 { |
|
182 t << endl; |
|
183 t << convertToComment(m_doc); |
|
184 t << endl; |
|
185 } |
|
186 t << m_name << m_spaces.left(MAX_OPTION_LENGTH-m_name.length()) << "="; |
|
187 writeStringValue(t,m_value); |
|
188 t << "\n"; |
|
189 } |
|
190 void writeXML(QTextStream&); |
|
191 void init() { m_value = m_defValue.copy(); } |
|
192 |
|
193 private: |
|
194 QStrList m_valueRange; |
|
195 QCString m_value; |
|
196 QCString m_defValue; |
|
197 }; |
|
198 |
|
199 /*! \brief Option of the string type. |
|
200 * |
|
201 */ |
|
202 class ConfigString : public ConfigOption |
|
203 { |
|
204 public: |
|
205 enum WidgetType { String, File, Dir }; |
|
206 ConfigString(const char *name,const char *doc) |
|
207 : ConfigOption(O_String) |
|
208 { |
|
209 m_name = name; |
|
210 m_doc = doc; |
|
211 m_widgetType = String; |
|
212 } |
|
213 ~ConfigString() |
|
214 { |
|
215 } |
|
216 void setWidgetType(WidgetType w) { m_widgetType = w; } |
|
217 WidgetType widgetType() const { return m_widgetType; } |
|
218 void setDefaultValue(const char *v) { m_defValue = v; } |
|
219 QCString *valueRef() { return &m_value; } |
|
220 void writeTemplate(QTextStream &t,bool sl,bool) |
|
221 { |
|
222 if (!sl) |
|
223 { |
|
224 t << endl; |
|
225 t << convertToComment(m_doc); |
|
226 t << endl; |
|
227 } |
|
228 t << m_name << m_spaces.left(MAX_OPTION_LENGTH-m_name.length()) << "="; |
|
229 writeStringValue(t,m_value); |
|
230 t << "\n"; |
|
231 } |
|
232 void substEnvVars(); |
|
233 void writeXML(QTextStream&); |
|
234 void init() { m_value = m_defValue.copy(); } |
|
235 |
|
236 private: |
|
237 QCString m_value; |
|
238 QCString m_defValue; |
|
239 WidgetType m_widgetType; |
|
240 }; |
|
241 |
|
242 /*! \brief Option of the integer type. |
|
243 * |
|
244 */ |
|
245 class ConfigInt : public ConfigOption |
|
246 { |
|
247 public: |
|
248 ConfigInt(const char *name,const char *doc,int minVal,int maxVal,int defVal) |
|
249 : ConfigOption(O_Int) |
|
250 { |
|
251 m_name = name; |
|
252 m_doc = doc; |
|
253 m_value = defVal; |
|
254 m_defValue = defVal; |
|
255 m_minVal = minVal; |
|
256 m_maxVal = maxVal; |
|
257 } |
|
258 QCString *valueStringRef() { return &m_valueString; } |
|
259 int *valueRef() { return &m_value; } |
|
260 int minVal() const { return m_minVal; } |
|
261 int maxVal() const { return m_maxVal; } |
|
262 void convertStrToVal(); |
|
263 void substEnvVars(); |
|
264 void writeTemplate(QTextStream &t,bool sl,bool upd) |
|
265 { |
|
266 if (!sl) |
|
267 { |
|
268 t << endl; |
|
269 t << convertToComment(m_doc); |
|
270 t << endl; |
|
271 } |
|
272 t << m_name << m_spaces.left(MAX_OPTION_LENGTH-m_name.length()) << "="; |
|
273 if (upd && !m_valueString.isEmpty()) |
|
274 { |
|
275 writeStringValue(t,m_valueString); |
|
276 } |
|
277 else |
|
278 { |
|
279 writeIntValue(t,m_value); |
|
280 } |
|
281 t << "\n"; |
|
282 } |
|
283 void writeXML(QTextStream&); |
|
284 void init() { m_value = m_defValue; } |
|
285 private: |
|
286 int m_value; |
|
287 int m_defValue; |
|
288 int m_minVal; |
|
289 int m_maxVal; |
|
290 QCString m_valueString; |
|
291 }; |
|
292 |
|
293 /*! \brief Option of the boolean type. |
|
294 * |
|
295 */ |
|
296 class ConfigBool : public ConfigOption |
|
297 { |
|
298 public: |
|
299 ConfigBool(const char *name,const char *doc,bool defVal) |
|
300 : ConfigOption(O_Bool) |
|
301 { |
|
302 m_name = name; |
|
303 m_doc = doc; |
|
304 m_value = defVal; |
|
305 m_defValue = defVal; |
|
306 } |
|
307 QCString *valueStringRef() { return &m_valueString; } |
|
308 bool *valueRef() { return &m_value; } |
|
309 void convertStrToVal(); |
|
310 void substEnvVars(); |
|
311 void setValueString(const QCString &v) { m_valueString = v; } |
|
312 void writeTemplate(QTextStream &t,bool sl,bool upd) |
|
313 { |
|
314 if (!sl) |
|
315 { |
|
316 t << endl; |
|
317 t << convertToComment(m_doc); |
|
318 t << endl; |
|
319 } |
|
320 t << m_name << m_spaces.left(MAX_OPTION_LENGTH-m_name.length()) << "="; |
|
321 if (upd && !m_valueString.isEmpty()) |
|
322 { |
|
323 writeStringValue(t,m_valueString); |
|
324 } |
|
325 else |
|
326 { |
|
327 writeBoolValue(t,m_value); |
|
328 } |
|
329 t << "\n"; |
|
330 } |
|
331 void writeXML(QTextStream&); |
|
332 void init() { m_value = m_defValue; } |
|
333 private: |
|
334 bool m_value; |
|
335 bool m_defValue; |
|
336 QCString m_valueString; |
|
337 }; |
|
338 |
|
339 /*! \brief Section marker for obsolete options |
|
340 * |
|
341 */ |
|
342 class ConfigObsolete : public ConfigOption |
|
343 { |
|
344 public: |
|
345 ConfigObsolete(const char *name,OptionType t) : ConfigOption(t) |
|
346 { m_name = name; } |
|
347 void writeTemplate(QTextStream &,bool,bool) {} |
|
348 void substEnvVars() {} |
|
349 void writeXML(QTextStream&); |
|
350 }; |
|
351 |
|
352 |
|
353 // some convenience macros |
|
354 #define Config_getString(val) Config::instance()->getString(__FILE__,__LINE__,val) |
|
355 #define Config_getInt(val) Config::instance()->getInt(__FILE__,__LINE__,val) |
|
356 #define Config_getList(val) Config::instance()->getList(__FILE__,__LINE__,val) |
|
357 #define Config_getEnum(val) Config::instance()->getEnum(__FILE__,__LINE__,val) |
|
358 #define Config_getBool(val) Config::instance()->getBool(__FILE__,__LINE__,val) |
|
359 |
|
360 /*! \brief Singleton for configuration variables. |
|
361 * |
|
362 * This object holds the global static variables |
|
363 * read from a user-supplied configuration file. |
|
364 * The static member instance() can be used to get |
|
365 * a pointer to the one and only instance. |
|
366 * |
|
367 * Set all variables to their default values by |
|
368 * calling Config::instance()->init() |
|
369 * |
|
370 */ |
|
371 class Config |
|
372 { |
|
373 public: |
|
374 ///////////////////////////// |
|
375 // public API |
|
376 ///////////////////////////// |
|
377 |
|
378 /*! Returns the one and only instance of this class */ |
|
379 static Config *instance() |
|
380 { |
|
381 if (m_instance==0) m_instance = new Config; |
|
382 return m_instance; |
|
383 } |
|
384 /*! Delete the instance */ |
|
385 static void deleteInstance() |
|
386 { |
|
387 delete m_instance; |
|
388 m_instance=0; |
|
389 } |
|
390 |
|
391 /*! Returns an iterator that can by used to iterate over the |
|
392 * configuration options. |
|
393 */ |
|
394 QListIterator<ConfigOption> iterator() |
|
395 { |
|
396 return QListIterator<ConfigOption>(*m_options); |
|
397 } |
|
398 |
|
399 /*! |
|
400 * @name Getting configuration values. |
|
401 * @{ |
|
402 */ |
|
403 |
|
404 /*! Returns the value of the string option with name \a fileName. |
|
405 * The arguments \a num and \a name are for debugging purposes only. |
|
406 * There is a convenience function Config_getString() for this. |
|
407 */ |
|
408 QCString &getString(const char *fileName,int num,const char *name) const; |
|
409 |
|
410 /*! Returns the value of the list option with name \a fileName. |
|
411 * The arguments \a num and \a name are for debugging purposes only. |
|
412 * There is a convenience function Config_getList() for this. |
|
413 */ |
|
414 QStrList &getList(const char *fileName,int num,const char *name) const; |
|
415 |
|
416 /*! Returns the value of the enum option with name \a fileName. |
|
417 * The arguments \a num and \a name are for debugging purposes only. |
|
418 * There is a convenience function Config_getEnum() for this. |
|
419 */ |
|
420 QCString &getEnum(const char *fileName,int num,const char *name) const; |
|
421 |
|
422 /*! Returns the value of the integer option with name \a fileName. |
|
423 * The arguments \a num and \a name are for debugging purposes only. |
|
424 * There is a convenience function Config_getInt() for this. |
|
425 */ |
|
426 int &getInt(const char *fileName,int num,const char *name) const; |
|
427 |
|
428 /*! Returns the value of the boolean option with name \a fileName. |
|
429 * The arguments \a num and \a name are for debugging purposes only. |
|
430 * There is a convenience function Config_getBool() for this. |
|
431 */ |
|
432 bool &getBool(const char *fileName,int num,const char *name) const; |
|
433 |
|
434 /*! Returns the ConfigOption corresponding with \a name or 0 if |
|
435 * the option is not supported. |
|
436 */ |
|
437 ConfigOption *get(const char *name) const |
|
438 { |
|
439 return m_dict->find(name); |
|
440 } |
|
441 /* @} */ |
|
442 |
|
443 /*! |
|
444 * @name Adding configuration options. |
|
445 * @{ |
|
446 */ |
|
447 |
|
448 /*! Starts a new configuration section with \a name and description \a doc. |
|
449 * \returns An object representing the option. |
|
450 */ |
|
451 ConfigInfo *addInfo(const char *name,const char *doc) |
|
452 { |
|
453 ConfigInfo *result = new ConfigInfo(name,doc); |
|
454 m_options->append(result); |
|
455 return result; |
|
456 } |
|
457 |
|
458 /*! Adds a new string option with \a name and documentation \a doc. |
|
459 * \returns An object representing the option. |
|
460 */ |
|
461 ConfigString *addString(const char *name, |
|
462 const char *doc) |
|
463 { |
|
464 ConfigString *result = new ConfigString(name,doc); |
|
465 m_options->append(result); |
|
466 m_dict->insert(name,result); |
|
467 return result; |
|
468 } |
|
469 |
|
470 /*! Adds a new enumeration option with \a name and documentation \a doc |
|
471 * and initial value \a defVal. |
|
472 * \returns An object representing the option. |
|
473 */ |
|
474 ConfigEnum *addEnum(const char *name, |
|
475 const char *doc, |
|
476 const char *defVal) |
|
477 { |
|
478 ConfigEnum *result = new ConfigEnum(name,doc,defVal); |
|
479 m_options->append(result); |
|
480 m_dict->insert(name,result); |
|
481 return result; |
|
482 } |
|
483 |
|
484 /*! Adds a new string option with \a name and documentation \a doc. |
|
485 * \returns An object representing the option. |
|
486 */ |
|
487 ConfigList *addList(const char *name, |
|
488 const char *doc) |
|
489 { |
|
490 ConfigList *result = new ConfigList(name,doc); |
|
491 m_options->append(result); |
|
492 m_dict->insert(name,result); |
|
493 return result; |
|
494 } |
|
495 |
|
496 /*! Adds a new integer option with \a name and documentation \a doc. |
|
497 * The integer has a range between \a minVal and \a maxVal and a |
|
498 * default value of \a defVal. |
|
499 * \returns An object representing the option. |
|
500 */ |
|
501 ConfigInt *addInt(const char *name, |
|
502 const char *doc, |
|
503 int minVal,int maxVal,int defVal) |
|
504 { |
|
505 ConfigInt *result = new ConfigInt(name,doc,minVal,maxVal,defVal); |
|
506 m_options->append(result); |
|
507 m_dict->insert(name,result); |
|
508 return result; |
|
509 } |
|
510 |
|
511 /*! Adds a new boolean option with \a name and documentation \a doc. |
|
512 * The boolean has a default value of \a defVal. |
|
513 * \returns An object representing the option. |
|
514 */ |
|
515 ConfigBool *addBool(const char *name, |
|
516 const char *doc, |
|
517 bool defVal) |
|
518 { |
|
519 ConfigBool *result = new ConfigBool(name,doc,defVal); |
|
520 m_options->append(result); |
|
521 m_dict->insert(name,result); |
|
522 return result; |
|
523 } |
|
524 /*! Adds an option that has become obsolete. */ |
|
525 ConfigOption *addObsolete(const char *name) |
|
526 { |
|
527 ConfigObsolete *option = new ConfigObsolete(name,ConfigOption::O_Obsolete); |
|
528 m_dict->insert(name,option); |
|
529 m_obsolete->append(option); |
|
530 return option; |
|
531 } |
|
532 /*! @} */ |
|
533 |
|
534 /*! Writes a template configuration to stream \a t. If \a shortIndex |
|
535 * is \c TRUE the description of each configuration option will |
|
536 * be omitted. |
|
537 */ |
|
538 void writeTemplate(QTextStream &t,bool shortIndex,bool updateOnly); |
|
539 |
|
540 /** Write XML representation of the config file */ |
|
541 void writeXML(QTextStream &t); |
|
542 |
|
543 ///////////////////////////// |
|
544 // internal API |
|
545 ///////////////////////////// |
|
546 |
|
547 /*! Converts the string values read from the configuration file |
|
548 * to real values for non-string type options (like int, and bools) |
|
549 */ |
|
550 void convertStrToVal(); |
|
551 |
|
552 /*! Replaces references to environment variable by the actual value |
|
553 * of the environment variable. |
|
554 */ |
|
555 void substituteEnvironmentVars(); |
|
556 |
|
557 /*! Checks if the values of the variable are correct, adjusts them |
|
558 * if needed, and report any errors. |
|
559 */ |
|
560 void check(); |
|
561 |
|
562 /*! Initialize config variables to their default value */ |
|
563 void init(); |
|
564 |
|
565 /*! Parse a configuration data in string \a str. |
|
566 * \returns TRUE if successful, or FALSE if the string could not be |
|
567 * parsed. |
|
568 */ |
|
569 bool parseString(const char *fn,const char *str); |
|
570 |
|
571 /*! Parse a configuration file with name \a fn. |
|
572 * \returns TRUE if successful, FALSE if the file could not be |
|
573 * opened or read. |
|
574 */ |
|
575 bool parse(const char *fn); |
|
576 |
|
577 /*! Called from the constructor, will add doxygen's default options |
|
578 * to the configuration object |
|
579 */ |
|
580 void create(); |
|
581 |
|
582 protected: |
|
583 |
|
584 Config() |
|
585 { |
|
586 m_options = new QList<ConfigOption>; |
|
587 m_obsolete = new QList<ConfigOption>; |
|
588 m_dict = new QDict<ConfigOption>(257); |
|
589 m_options->setAutoDelete(TRUE); |
|
590 m_obsolete->setAutoDelete(TRUE); |
|
591 m_initialized = FALSE; |
|
592 create(); |
|
593 } |
|
594 ~Config() |
|
595 { |
|
596 delete m_options; |
|
597 delete m_obsolete; |
|
598 delete m_dict; |
|
599 } |
|
600 |
|
601 private: |
|
602 QList<ConfigOption> *m_options; |
|
603 QList<ConfigOption> *m_obsolete; |
|
604 QDict<ConfigOption> *m_dict; |
|
605 static Config *m_instance; |
|
606 bool m_initialized; |
|
607 }; |
|
608 |
|
609 #endif |