|
MASA-Core
|
00001 /******************************************************************************* 00002 * 00003 * Copyright (c) 2010-2015 Edans Sandes 00004 * 00005 * This file is part of MASA-Core. 00006 * 00007 * MASA-Core is free software: you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation, either version 3 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * MASA-Core is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with MASA-Core. If not, see <http://www.gnu.org/licenses/>. 00019 * 00020 ******************************************************************************/ 00021 00022 #include "ConfigParser.hpp" 00023 #include "../exceptions/IllegalArgumentException.hpp" 00024 00025 #include <stdio.h> 00026 #include <stdlib.h> 00027 #include <string.h> 00028 #include <wordexp.h> 00029 #include <sstream> 00030 using namespace std; 00031 00032 #define DEBUG (0) 00033 00034 ConfigParser::ConfigParser(config_option_t* options) { 00035 config_option_t* ptr = options; 00036 while (ptr->name != NULL && ptr->section != NULL) { 00037 this->options[ptr->section][ptr->name] = ptr; 00038 if (DEBUG) fprintf(stderr, "v: %s:%s %p def:%s\n", ptr->section, ptr->name, this->options[ptr->section][ptr->name], ptr->default_value_str.c_str()); 00039 00040 if (ptr->pointer == NULL) { 00041 //throw IllegalArgumentException("ConfigParser cannot be created. Missing flag pointer.", ptr->name); 00042 fprintf(stderr, "ConfigParser cannot be created. Missing flag pointer. %s:%s\n", ptr->section, ptr->name); 00043 return; 00044 } 00045 ptr->resolved_value_str = ptr->default_value_str; 00046 00047 ptr++; 00048 } 00049 00050 strcpy(section, "[global]"); 00051 } 00052 00053 ConfigParser::~ConfigParser() { 00054 00055 } 00056 00057 string ConfigParser::resolve_env(string in) { 00058 wordexp_t p; 00059 char **w; 00060 int i; 00061 00062 if (in.length() == 0) { 00063 throw IllegalArgumentException("Empty argument."); 00064 } 00065 00066 int ret = wordexp(in.c_str(), &p, WRDE_NOCMD | WRDE_UNDEF); 00067 std::stringstream var; 00068 var << "Variable: " << in; 00069 if (ret == WRDE_BADVAL) { 00070 throw IllegalArgumentException("An undefined environment variable was referenced.", var.str().c_str()); 00071 } else if (ret != 0) { 00072 throw IllegalArgumentException("Wrong environment variable expansion.", var.str().c_str()); 00073 } else if (p.we_wordc == 0) { 00074 throw IllegalArgumentException("No wildcard ('*') expansion.", var.str().c_str()); 00075 } else if (p.we_wordc > 1) { 00076 throw IllegalArgumentException("Ambiguous wildcard ('*') expansion.", var.str().c_str()); 00077 } 00078 w = p.we_wordv; 00079 string out = w[0]; 00080 wordfree(&p); 00081 00082 return out; 00083 } 00084 00085 void ConfigParser::printFile(FILE* file, bool resolve) { 00086 for(map<string, map<string, config_option_t*> >::iterator iter_sections = options.begin(); iter_sections != options.end(); ++iter_sections) { 00087 const char* section = iter_sections->first.c_str(); 00088 if (DEBUG) printf("\n%s\n", section); 00089 for(map<string, config_option_t*>::iterator iter = iter_sections->second.begin(); iter != iter_sections->second.end(); ++iter) { 00090 const char* k = iter->first.c_str(); 00091 const config_option_t* option = iter->second; 00092 fprintf(file, "%s\t%s\n", k, resolve ? option->resolved_value_str.c_str() : option->original_value_str.c_str()); 00093 } 00094 } 00095 } 00096 00097 void ConfigParser::tokenize(const char* _line, char* _param, char* _value) { 00098 char line[512]; 00099 char* param; 00100 char* value; 00101 strcpy(line, _line); 00102 while (line[strlen(line) - 1] == '\n' || line[strlen(line) - 1] == '\r') { 00103 line[strlen(line) - 1] = '\0'; 00104 } 00105 char* sharp = strchr(line, '#'); 00106 if (sharp != NULL) { 00107 *sharp = '\0'; 00108 } 00109 param = line; 00110 while (*param == '\t' || *param == ' ') { 00111 param++; 00112 } 00113 if (*param == '\0') { 00114 _param[0] = '\0'; 00115 return; 00116 } 00117 value = param; 00118 while (*value != '\t' && *value != ' ' && *value != '\0') { 00119 value++; 00120 } 00121 if (*value != '\0') { 00122 *value = '\0'; // terminating the parameter name token. 00123 value++; 00124 while (*value == '\t' || *value == ' ') { 00125 value++; 00126 } 00127 } 00128 00129 strcpy(_param, param); 00130 strcpy(_value, value); 00131 if (DEBUG) fprintf(stderr, "%s -> %s\n", param, value); 00132 } 00133 00134 void ConfigParser::parseValue(const char* section, const char* param, const char* value) { 00135 if (options[section][param] == NULL) { 00136 char msg[128]; 00137 sprintf(msg, "Unknown parameter `%s'.", param); 00138 throw IllegalArgumentException(msg); 00139 } 00140 config_option_t* option = options[section][param]; 00141 if (*value == '\0') { 00142 char msg[128]; 00143 sprintf(msg, "An argument must be supplied to the parameter: %s.\n", 00144 param); 00145 throw IllegalArgumentException(msg); 00146 } else { 00147 char *cpy_value = new char[strlen(value)+1]; 00148 strcpy(cpy_value, value); 00149 option->original_value_str = cpy_value; 00150 option->resolved_value_str = cpy_value; 00151 00152 option->parser(value, option); 00153 } 00154 } 00155 00156 void ConfigParser::parseLine(const char* line) { 00157 char param[128]; 00158 char value[128]; 00159 00160 tokenize(line, param, value); 00161 if (*param == '\0') { 00162 return; 00163 } 00164 if (*param == '[') { 00165 strcpy(section, param); 00166 if (options[section].size() == 0) { 00167 char msg[128]; 00168 sprintf(msg, "Unknown section `%s'.", param); 00169 throw IllegalArgumentException(msg); 00170 } 00171 return; 00172 } 00173 parseValue(section, param, value); 00174 } 00175 00176 void ConfigParser::parse_int (const char* value, config_option_t* option) { 00177 int* i = (int*)option->pointer; 00178 if ( sscanf ( value, "%d", i ) != 1 ) { 00179 char msg[128]; 00180 sprintf(msg, "Value must be an integer"); 00181 throw IllegalArgumentException(msg); 00182 } 00183 } 00184 00185 00186 void ConfigParser::parse_int_range (const char* value, config_option_t* option) { 00187 int* i = (int*)option->pointer; 00188 sscanf ( value, "%d", i ); 00189 int min; 00190 int max; 00191 sscanf (option->option, "%d %d", &min, &max); 00192 if ( *i < min || *i > max ) { 00193 char msg[128]; 00194 sprintf(msg, "Value must be in range %d..%d", min, max); 00195 throw IllegalArgumentException(msg); 00196 } 00197 } 00198 00199 void ConfigParser::parse_int_min (const char* value, config_option_t* option) { 00200 int* i = (int*)option->pointer; 00201 sscanf ( value, "%d", i ); 00202 int min; 00203 sscanf (option->option, "%d", &min); 00204 if ( *i < min ) { 00205 char msg[128]; 00206 sprintf(msg, "Value must be greater or equal to %d", min); 00207 throw IllegalArgumentException(msg); 00208 } 00209 } 00210 00211 void ConfigParser::parse_int_max (const char* value, config_option_t* option) { 00212 int* i = (int*)option->pointer; 00213 sscanf ( value, "%d", i ); 00214 int max; 00215 sscanf (option->option, "%d", &max); 00216 if ( *i > max ) { 00217 char msg[128]; 00218 sprintf(msg, "Value must be less or equal to %d", max); 00219 throw IllegalArgumentException(msg); 00220 } 00221 } 00222 00223 void ConfigParser::parse_longlong_size (const char* value, config_option_t* option) { 00224 long long* ll = (long long*)option->pointer; 00225 if (strcmp(value, "none") == 0) { 00226 *ll = 0; 00227 return; 00228 } 00229 00230 string str = value; 00231 char suffix = str[str.length()-1]; 00232 str[str.length()-1] = 0; 00233 switch ( suffix ) { 00234 case 'K': 00235 *ll = ( long long ) ( atof ( str.c_str() ) *1024LL ); 00236 break; 00237 case 'M': 00238 *ll = ( long long ) ( atof ( str.c_str() ) *1024*1024LL ); 00239 break; 00240 case 'G': 00241 *ll = ( long long ) ( atof ( str.c_str() ) *1024*1024*1024LL ); 00242 break; 00243 default: 00244 throw IllegalArgumentException("Wrong size suffix (use 'K', 'M' or 'G')."); 00245 } 00246 if ( *ll == 0 ) { 00247 throw IllegalArgumentException("Wrong disk size limit."); 00248 } 00249 char tmp[256]; 00250 sprintf(tmp, "%lld", *ll); 00251 option->resolved_value_str = tmp; 00252 } 00253 00254 void ConfigParser::parse_int_enum(const char* value, config_option_t* option) { 00255 int* i = (int*)option->pointer; 00256 00257 char option_cpy[256]; 00258 strncpy(option_cpy, option->option, sizeof(option_cpy)); 00259 option_cpy[sizeof(option_cpy)-1] = '\0'; 00260 00261 char* tok = strtok(option_cpy, ";"); 00262 int id = 0; 00263 while (tok != NULL) { 00264 if (strcmp(tok, value) == 0) { 00265 *i = id; 00266 return; 00267 } 00268 id++; 00269 tok = strtok(NULL, ";"); 00270 } 00271 00272 char msg[128]; 00273 sprintf(msg, "Option `%s' not recognized. Possible values are: %s", value, option->option); 00274 throw IllegalArgumentException(msg); 00275 } 00276 00277 void ConfigParser::parse_bool (const char* value, config_option_t* option) { 00278 int* b = (int*)option->pointer; 00279 if (strcmp(value, "enabled") == 0 || strcmp(value, "true") == 0) { 00280 *b = 1; 00281 return; 00282 } else if (strcmp(value, "disabled") == 0 || strcmp(value, "false") == 0) { 00283 *b = 0; 00284 return; 00285 } else { 00286 char msg[128]; 00287 sprintf(msg, "Value must be enabled/disable or true/false"); 00288 throw IllegalArgumentException(msg); 00289 } 00290 } 00291 00292 void ConfigParser::parse_path (const char* value, config_option_t* option) { 00293 string* path = (string*)option->pointer; 00294 *path = resolve_env(string(value)); 00295 option->resolved_value_str = *path; 00296 }
1.7.6.1