00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "configDeclaration.h"
00016 #include "configVariableCore.h"
00017 #include "pstrtod.h"
00018
00019
00020
00021
00022
00023
00024
00025
00026 ConfigDeclaration::
00027 ConfigDeclaration(ConfigPage *page, ConfigVariableCore *variable,
00028 const string &string_value, int decl_seq) :
00029 _page(page),
00030 _variable(variable),
00031 _string_value(string_value),
00032 _decl_seq(decl_seq),
00033 _got_words(false)
00034 {
00035 if (!_page->is_special()) {
00036 _variable->add_declaration(this);
00037 }
00038 }
00039
00040
00041
00042
00043
00044
00045
00046 ConfigDeclaration::
00047 ~ConfigDeclaration() {
00048 if (!_page->is_special()) {
00049 _variable->remove_declaration(this);
00050 }
00051 }
00052
00053
00054
00055
00056
00057
00058
00059 void ConfigDeclaration::
00060 set_string_word(int n, const string &value) {
00061 if (!_got_words) {
00062 get_words();
00063 }
00064
00065 while (n >= (int)_words.size()) {
00066 Word w;
00067 w._flags = 0;
00068 _words.push_back(w);
00069 }
00070
00071 _words[n]._str = value;
00072 _words[n]._flags = 0;
00073
00074
00075 Words::const_iterator wi = _words.begin();
00076 _string_value = (*wi)._str;
00077 ++wi;
00078
00079 while (wi != _words.end()) {
00080 _string_value += " ";
00081 _string_value += (*wi)._str;
00082 ++wi;
00083 }
00084 invalidate_cache();
00085 }
00086
00087
00088
00089
00090
00091
00092
00093 void ConfigDeclaration::
00094 set_bool_word(int n, bool value) {
00095 if (value) {
00096 set_string_word(n, "1");
00097 } else {
00098 set_string_word(n, "0");
00099 }
00100
00101 _words[n]._flags |= (F_checked_bool | F_valid_bool);
00102 _words[n]._bool = value;
00103 invalidate_cache();
00104 }
00105
00106
00107
00108
00109
00110
00111
00112 void ConfigDeclaration::
00113 set_int_word(int n, int value) {
00114 ostringstream strm;
00115 strm << value;
00116 set_string_word(n, strm.str());
00117
00118 _words[n]._flags |= (F_checked_int | F_valid_int);
00119 _words[n]._int = value;
00120 invalidate_cache();
00121 }
00122
00123
00124
00125
00126
00127
00128
00129 void ConfigDeclaration::
00130 set_int64_word(int n, PN_int64 value) {
00131 ostringstream strm;
00132 strm << value;
00133 set_string_word(n, strm.str());
00134
00135 _words[n]._flags |= (F_checked_int64 | F_valid_int64);
00136 _words[n]._int_64 = value;
00137 invalidate_cache();
00138 }
00139
00140
00141
00142
00143
00144
00145
00146 void ConfigDeclaration::
00147 set_double_word(int n, double value) {
00148 ostringstream strm;
00149 strm << value;
00150 set_string_word(n, strm.str());
00151
00152 _words[n]._flags |= (F_checked_double | F_valid_double);
00153 _words[n]._double = value;
00154 invalidate_cache();
00155 }
00156
00157
00158
00159
00160
00161
00162 void ConfigDeclaration::
00163 output(ostream &out) const {
00164 out << get_variable()->get_name() << " " << get_string_value();
00165 }
00166
00167
00168
00169
00170
00171
00172 void ConfigDeclaration::
00173 write(ostream &out) const {
00174 out << get_variable()->get_name() << " " << get_string_value();
00175 if (!get_variable()->is_used()) {
00176 out << " (not used)";
00177 }
00178 out << "\n";
00179 }
00180
00181
00182
00183
00184
00185
00186 void ConfigDeclaration::
00187 get_words() {
00188 if (!_got_words) {
00189 _words.clear();
00190 vector_string words;
00191 extract_words(_string_value, words);
00192 _words.reserve(words.size());
00193
00194 for (vector_string::const_iterator wi = words.begin();
00195 wi != words.end();
00196 ++wi) {
00197 Word w;
00198 w._str = (*wi);
00199 w._flags = 0;
00200 _words.push_back(w);
00201 }
00202
00203 _got_words = true;
00204 }
00205 }
00206
00207
00208
00209
00210
00211
00212
00213 void ConfigDeclaration::
00214 check_bool_word(int n) {
00215 if (!_got_words) {
00216 get_words();
00217 }
00218
00219 if (n >= 0 && n < (int)_words.size()) {
00220 Word &word = _words[n];
00221 if ((word._flags & F_checked_bool) == 0) {
00222 word._flags |= F_checked_bool;
00223
00224 string s = downcase(word._str);
00225 if (s.empty()) {
00226 word._bool = false;
00227
00228 } else if (s == "#t" || s == "1" || s[0] == 't') {
00229 word._bool = true;
00230
00231 } else if (s == "#f" || s == "0" || s[0] == 'f') {
00232 word._bool = false;
00233
00234 } else {
00235
00236 check_double_word(n);
00237 if ((word._flags & F_checked_double) != 0) {
00238 word._bool = (word._double != 0.0);
00239 } else {
00240 word._bool = false;
00241 }
00242
00243 prc_cat->warning()
00244 << "Invalid bool value for ConfigVariable "
00245 << get_variable()->get_name() << ": " << word._str << "\n";
00246 return;
00247 }
00248
00249 word._flags |= F_valid_bool;
00250 }
00251 }
00252 }
00253
00254
00255
00256
00257
00258
00259
00260 void ConfigDeclaration::
00261 check_int_word(int n) {
00262 if (!_got_words) {
00263 get_words();
00264 }
00265
00266 if (n >= 0 && n < (int)_words.size()) {
00267 Word &word = _words[n];
00268 if ((word._flags & F_checked_int) == 0) {
00269 word._flags |= F_checked_int;
00270
00271
00272
00273 word._int = 0;
00274 bool overflow = false;
00275
00276 string::const_iterator pi = word._str.begin();
00277 if (pi != word._str.end() && (*pi) == '-') {
00278 ++pi;
00279
00280 while (pi != word._str.end() && isdigit(*pi)) {
00281 int next = word._int * 10 - (int)((*pi) - '0');
00282 if ((int)(next / 10) != word._int) {
00283
00284 overflow = true;
00285 }
00286 word._int = next;
00287 ++pi;
00288 }
00289
00290 } else {
00291
00292 while (pi != word._str.end() && isdigit(*pi)) {
00293 int next = word._int * 10 + (int)((*pi) - '0');
00294 if ((int)(next / 10) != word._int) {
00295
00296 overflow = true;
00297 }
00298 word._int = next;
00299 ++pi;
00300 }
00301 }
00302
00303 if (pi == word._str.end() && !overflow) {
00304 word._flags |= F_valid_int;
00305 } else {
00306 prc_cat->warning()
00307 << "Invalid integer value for ConfigVariable "
00308 << get_variable()->get_name() << ": " << word._str << "\n";
00309 }
00310 }
00311 }
00312 }
00313
00314
00315
00316
00317
00318
00319
00320 void ConfigDeclaration::
00321 check_int64_word(int n) {
00322 if (!_got_words) {
00323 get_words();
00324 }
00325
00326 if (n >= 0 && n < (int)_words.size()) {
00327 Word &word = _words[n];
00328 if ((word._flags & F_checked_int64) == 0) {
00329 word._flags |= F_checked_int64;
00330
00331 word._int_64 = 0;
00332 bool overflow = false;
00333
00334 string::const_iterator pi = word._str.begin();
00335 if (pi != word._str.end() && (*pi) == '-') {
00336 ++pi;
00337
00338 while (pi != word._str.end() && isdigit(*pi)) {
00339 PN_int64 next = word._int_64 * 10 - (int)((*pi) - '0');
00340 if ((PN_int64)(next / 10) != word._int_64) {
00341
00342 overflow = true;
00343 }
00344 word._int_64 = next;
00345 ++pi;
00346 }
00347
00348 } else {
00349
00350 while (pi != word._str.end() && isdigit(*pi)) {
00351 PN_int64 next = word._int_64 * 10 + (int)((*pi) - '0');
00352 if ((PN_int64)(next / 10) != word._int_64) {
00353
00354 overflow = true;
00355 }
00356 word._int_64 = next;
00357 ++pi;
00358 }
00359 }
00360
00361 if (pi == word._str.end() && !overflow) {
00362 word._flags |= F_valid_int64;
00363 } else {
00364 prc_cat->warning()
00365 << "Invalid int64 value for ConfigVariable "
00366 << get_variable()->get_name() << ": " << word._str << "\n";
00367 }
00368 }
00369 }
00370 }
00371
00372
00373
00374
00375
00376
00377
00378 void ConfigDeclaration::
00379 check_double_word(int n) {
00380 if (!_got_words) {
00381 get_words();
00382 }
00383
00384 if (n >= 0 && n < (int)_words.size()) {
00385 Word &word = _words[n];
00386 if ((word._flags & F_checked_double) == 0) {
00387 word._flags |= F_checked_double;
00388
00389 const char *nptr = word._str.c_str();
00390 char *endptr;
00391 word._double = pstrtod(nptr, &endptr);
00392
00393 if (*endptr == '\0') {
00394 word._flags |= F_valid_double;
00395 } else {
00396 prc_cat->warning()
00397 << "Invalid floating-point value for ConfigVariable "
00398 << get_variable()->get_name() << ": " << word._str << "\n";
00399 }
00400 }
00401 }
00402 }
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415 int ConfigDeclaration::
00416 extract_words(const string &str, vector_string &words) {
00417 int num_words = 0;
00418
00419 size_t pos = 0;
00420 while (pos < str.length() && isspace((unsigned int)str[pos])) {
00421 pos++;
00422 }
00423 while (pos < str.length()) {
00424 size_t word_start = pos;
00425 while (pos < str.length() && !isspace((unsigned int)str[pos])) {
00426 pos++;
00427 }
00428 words.push_back(str.substr(word_start, pos - word_start));
00429 num_words++;
00430
00431 while (pos < str.length() && isspace((unsigned int)str[pos])) {
00432 pos++;
00433 }
00434 }
00435
00436 return num_words;
00437 }
00438
00439
00440
00441
00442
00443
00444
00445 string ConfigDeclaration::
00446 downcase(const string &s) {
00447 string result;
00448 result.reserve(s.size());
00449 string::const_iterator p;
00450 for (p = s.begin(); p != s.end(); ++p) {
00451 result += tolower(*p);
00452 }
00453 return result;
00454 }