1 // ANNA - Anna is Not Nothingness Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // http://redmine.teslayout.com/projects/anna-suite
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
17 // * Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
42 #include <anna/core/functions.hpp>
43 #include <anna/core/util/Configuration.hpp>
44 #include <anna/core/RuntimeException.hpp>
45 #include <anna/core/tracing/Logger.hpp>
46 #include <anna/core/tracing/TraceMethod.hpp>
51 const char* Configuration::defaultSection = "@global@";
53 void Configuration::load(const char* configFile)
54 throw(RuntimeException) {
55 LOGMETHOD(TraceMethod tm("Configuration", "load", ANNA_FILE_LOCATION));
59 string currentSection(defaultSection);
63 if((file = fopen(configFile, "r")) == NULL)
64 throw RuntimeException(configFile, errno, ANNA_FILE_LOCATION);
66 LOGDEBUG(Logger::write(Logger::Debug, "Configuration file", configFile, ANNA_FILE_LOCATION));
69 while(fgets(buffer, sizeof(buffer) - 1, file) != NULL) {
70 if((aux = strchr(buffer, '#')) != NULL)
73 if(anna_strlen(aux = strip(buffer)) <= 0)
76 if(processSection(nline, aux, currentSection) == true)
79 processVariable(nline, aux, currentSection);
82 } catch(RuntimeException& ex) {
90 bool Configuration::exists(const char* sectionName, const char* variableName) const
92 const VariableEx* var = find(string(sectionName), variableName);
93 return (var == NULL) ? false : !var->isNull();
96 void Configuration::setDefaultValue(const char* sectionName, const char* variableName, const char* defaultValue)
97 throw(RuntimeException) {
98 string section(sectionName);
99 VariableEx* var = find(section, variableName);
102 var = createVariable(section, variableName);
104 var->setDefaultValue(defaultValue);
106 string msg(sectionName);
110 msg += " | Default value: ";
112 Logger::write(Logger::Information, msg, ANNA_FILE_LOCATION);
116 const char* Configuration::getValue(const char* sectionName, const char* variableName, const bool strict) const
117 throw(RuntimeException) {
118 const VariableEx* variable = find(string(sectionName), variableName);
119 const char* result(NULL);
121 if(variable == NULL) {
122 string msg("Variable ");
126 msg += " is not defined";
127 throw RuntimeException(msg, ANNA_FILE_LOCATION);
130 if(variable->isNull() == false)
131 result = variable->getStringValue();
133 result = (strict == false) ? variable->getDefaultValue() : NULL;
138 int Configuration::getIntegerValue(const char* sectionName, const char* variableName, const bool strict) const
139 throw(RuntimeException) {
140 return atoi(getValue(sectionName, variableName, strict));
143 char* Configuration::strip(char* buffer) {
145 result = buffer + (anna_strlen(buffer) - 1);
147 while(result >= buffer && isspace(*result))
152 for(result = buffer; *result && isspace(*result); result ++);
157 bool Configuration::processSection(const int nline, char* buffer, string& currentSection) {
163 if((end = strchr(buffer, ']')) != NULL) {
164 *end = 0; // JASC, antes NULL
166 if(anna_strlen(section = strip(++ buffer)) > 0)
167 currentSection = section;
169 string msg("Invalid section name at line: ");
170 msg += functions::asString(nline);
171 throw RuntimeException(msg, ANNA_FILE_LOCATION);
181 void Configuration::processVariable(const int nline, char* buffer, const string& currentSection)
182 throw(RuntimeException) {
186 VariableEx* variable;
188 if((aux = anna_strchr(buffer , '=')) == NULL)
193 if(anna_strlen(variableName = strip(buffer)) <= 0) {
194 string msg("Invalid section name at line: ");
195 msg += functions::asString(nline);
196 throw RuntimeException(msg, ANNA_FILE_LOCATION);
199 if(anna_strlen(value = strip(aux + 1)) <= 0)
202 if((variable = find(currentSection, variableName)) != NULL) {
203 if(variable->isNull() == false) {
204 string msg("Duplicated variable | Section: ");
205 msg += currentSection;
206 msg += " | Variable: ";
209 msg += functions::asString(nline);
210 throw RuntimeException(msg, ANNA_FILE_LOCATION);
213 variable = createVariable(currentSection, variableName);
215 variable->setValue(value);
217 if(Logger::isActive(Logger::Information)) {
218 string msg(currentSection);
223 Logger::write(Logger::Information, variable->asString(), ANNA_FILE_LOCATION);
227 Configuration::VariableEx* Configuration::createVariable(const string& section, const char* variableName)
229 map <string, VariableEx::Vector*>::iterator isection(a_sections.find(section));
231 VariableEx::Vector* variables;
232 result = new VariableEx(variableName);
234 if(isection == a_sections.end()) {
235 variables = new VariableEx::Vector;
236 a_sections [section] = variables;
238 variables = isection->second;
240 variables->push_back(result);
244 Configuration::VariableEx* Configuration::find(const string& section, const char* variableName)
246 VariableEx* result(NULL);
247 map <string, VariableEx::Vector*>::iterator isection(a_sections.find(section));
249 if(isection == a_sections.end())
252 VariableEx::Vector* varVector(isection->second);
254 for(VariableEx::Vector::iterator vv = varVector->begin(), maxvv = varVector->end(); vv != maxvv; vv ++) {
255 if(!strcmp((*vv)->getName(), variableName)) {
264 void Configuration::removeAll()
266 map <string, VariableEx::Vector*>::iterator ii(a_sections.begin());
267 map <string, VariableEx::Vector*>::iterator end(a_sections.end());
268 VariableEx::Vector::iterator vv, maxvv;
269 VariableEx* variable;
271 for(; ii != end; ii ++) {
272 for(vv = ii->second->begin(), maxvv = ii->second->end(); vv != maxvv; vv ++) {