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