1 /***************************************************************************
2            configlang.h  -  Config file parser with gettext support
3                              -------------------
4     begin                : Thu May 15 2003
5     copyright            : (C) 2003 by Gabor Torok
6     email                : cctorok@yahoo.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 #ifndef CONFIG_LANG_H
18 #define CONFIG_LANG_H
19 #pragma once
20 
21 #include <vector>
22 #include <map>
23 #include <set>
24 
25 class ConfigValue;
26 class ConfigNode;
27 class ConfigLang;
28 
29 /// An individual configuration value.
30 
31 class ConfigValue {
32 public:
33 	enum TYPE {
34 		STRING_TYPE = 0,
35 		NUMBER_TYPE
36 	};
37 
38 private:
39 	int type;
40 	bool translatable;
41 	std::string valueStr, translateStr, original;
42 	float valueNum;
43 
44 public:
45 	ConfigValue( char const* value );
46 	ConfigValue( ConfigValue const& that );
47 	~ConfigValue();
48 
49 	float getAsFloat();
50 	const char *getAsString();
getOriginal()51 	inline std::string getOriginal() {
52 		return original;
53 	}
54 };
55 
56 /// A config node (cfg files can contain multiple blocks and levels).
57 
58 class ConfigNode {
59 private:
60 	ConfigNode *super;
61 	ConfigLang *config;
62 	std::string name;
63 	std::string id;
64 	std::map<std::string, ConfigValue*> values;
65 	std::vector<ConfigNode*> children;
66 	std::map<std::string, std::vector<ConfigNode*>*> childrenByName;
67 
68 public:
69 	ConfigNode( ConfigLang *config, std::string name );
70 	~ConfigNode();
71 	void addChild( ConfigNode *node );
72 	void addValue( std::string name, ConfigValue *value );
73 
getConfig()74 	inline ConfigLang *getConfig() {
75 		return config;
76 	}
getName()77 	inline std::string getName() {
78 		return name;
79 	}
getId()80 	inline std::string getId() {
81 		return id;
82 	}
getValues()83 	inline std::map<std::string, ConfigValue*>* getValues() {
84 		return &values;
85 	}
getChildren()86 	inline std::vector<ConfigNode*>* getChildren() {
87 		return &children;
88 	}
getSuper()89 	inline ConfigNode *getSuper() {
90 		return super;
91 	}
setSuper(ConfigNode * super)92 	inline void setSuper( ConfigNode *super ) {
93 		this->super = super;
94 	}
95 
96 	// convenience methods
getValueAsString(std::string name)97 	inline const char *getValueAsString( std::string name ) {
98 		if ( values.find( name ) == values.end() ) {
99 			return "";
100 		} else {
101 			return values[ name ]->getAsString();
102 		}
103 	}
104 
getValueAsFloat(std::string name)105 	inline float getValueAsFloat( std::string name ) {
106 		if ( values.find( name ) == values.end() ) {
107 			return 0;
108 		} else {
109 			return values[ name ]->getAsFloat();
110 		}
111 	}
112 
getValueAsInt(std::string name)113 	inline int getValueAsInt( std::string name ) {
114 		return toint( getValueAsFloat( name ) );
115 	}
116 
getValueAsBool(std::string name)117 	inline bool getValueAsBool( std::string name ) {
118 		if ( values.find( name ) == values.end() ) {
119 			return false;
120 		} else {
121 			return( !strcasecmp( values[ name ]->getAsString(), "true" ) ||
122 			        !strcasecmp( values[ name ]->getAsString(), "yes" ) ||
123 			        !strcasecmp( values[ name ]->getAsString(), "on" ) ||
124 			        values[ name ]->getAsFloat() > 0 );
125 		}
126 	}
127 
128 	void getKeys( std::set<std::string> *keyset );
129 
130 
hasValue(std::string name)131 	inline bool hasValue( std::string name ) {
132 		return( values.find( name ) != values.end() );
133 	}
134 
getChildrenByName(std::string name)135 	inline std::vector<ConfigNode*> *getChildrenByName( std::string name ) {
136 		if ( childrenByName.find( name ) == childrenByName.end() ) {
137 			return NULL;
138 		} else {
139 			return childrenByName[ name ];
140 		}
141 	}
142 
143 	void extendNode( std::string id );
144 
145 protected:
146 	// copy node's values and children into this node
147 	void copyFromNode( ConfigNode *node );
148 
149 };
150 
151 /// Configuration file parser.
152 
153 class ConfigLang {
154 private:
155 	std::map<std::string, ConfigNode*> idmap;
156 	ConfigNode *document;
157 	ConfigLang( char *config );
158 	ConfigLang( std::vector<std::string> *lines );
159 	void parse( char *config );
160 	void parse( std::vector<std::string> *lines );
161 	std::string cleanText( char *p, int n );
162 
163 public:
164 	~ConfigLang();
165 	void debug( ConfigNode *node, std::string indent, std::ostream &out );
debug()166 	inline void debug() {
167 		debug( document, "", std::cerr );
168 	}
getDocument()169 	inline ConfigNode *getDocument() {
170 		return document;
171 	}
getIdMap()172 	inline std::map<std::string, ConfigNode*> *getIdMap() {
173 		return &idmap;
174 	}
175 
176 	void setUpdate( char *message, int n = -1, int total = -1 );
177 
178 	static ConfigLang *load( const std::string& file, bool absolutePath = false );
179 	static ConfigLang *fromString( char *str );
180 	static ConfigLang *fromString( std::vector<std::string> *lines );
181 	void save( std::string& file, bool absolutePath = false );
182 };
183 
184 #endif
185 
186