00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "ArExport.h"
00028 #include "ariaOSDef.h"
00029 #include "ArConfig.h"
00030 #include "ArArgumentBuilder.h"
00031 #include "ArLog.h"
00032
00039 ArConfig::ArConfig(const char *baseDirectory,
00040 bool noBlanksBetweenParams,
00041 bool ignoreBounds,
00042 bool failOnBadSection) :
00043 myProcessFileCBList(),
00044 myNoBlanksBetweenParams(noBlanksBetweenParams),
00045 myBaseDirectory(),
00046 myParser(NULL),
00047 mySections(),
00048 myParserCB(this, &ArConfig::parseArgument),
00049 mySectionCB(this, &ArConfig::parseSection)
00050 {
00051 if (!myParser.addHandlerWithError("section", &mySectionCB))
00052 {
00053 ArLog::log(ArLog::Normal, "Could not add section to file parser, horrific failure");
00054 }
00055 myArgumentParser = NULL;
00056 setBaseDirectory(baseDirectory);
00057 myIgnoreBounds = ignoreBounds;
00058 myFailOnBadSection = failOnBadSection;
00059 myProcessFileCallbacksLogLevel = ArLog::Verbose;
00060 myUsingSections = false;
00061 mySectionBroken = false;
00062 myDuplicateParams = false;
00063 mySection = "";
00064 }
00065
00066 ArConfig::~ArConfig()
00067 {
00068 clearSections();
00069 }
00070
00071
00072 ArConfig::ArConfig(const ArConfig &config) :
00073 myProcessFileCBList(),
00074 myNoBlanksBetweenParams(config.myNoBlanksBetweenParams),
00075 myBaseDirectory(),
00076 myParser(NULL),
00077 mySections(),
00078 myParserCB(this, &ArConfig::parseArgument),
00079 mySectionCB(this, &ArConfig::parseSection)
00080 {
00081 myArgumentParser = NULL;
00082 setBaseDirectory(config.getBaseDirectory());
00083 myIgnoreBounds = config.myIgnoreBounds;
00084 myFailOnBadSection = config.myFailOnBadSection;
00085 myProcessFileCallbacksLogLevel = config.myProcessFileCallbacksLogLevel;
00086 mySectionBroken = config.mySectionBroken;
00087 mySection = config.mySection;
00088 myUsingSections = config.myUsingSections;
00089 myDuplicateParams = config.myDuplicateParams;
00090
00091 std::list<ArConfigSection *>::const_iterator it;
00092 for (it = config.mySections.begin();
00093 it != config.mySections.end();
00094 it++)
00095 {
00096 mySections.push_back(new ArConfigSection(*(*it)));
00097 }
00098 myParser.remHandler(&myParserCB);
00099 myParser.remHandler(&mySectionCB);
00100 addParserHandlers();
00101
00102 }
00103
00104
00105 ArConfig &ArConfig::operator=(const ArConfig &config)
00106 {
00107 if (this != &config) {
00108
00109
00110
00111
00112
00113
00114
00115 myArgumentParser = NULL;
00116 setBaseDirectory(config.getBaseDirectory());
00117 myNoBlanksBetweenParams = config.myNoBlanksBetweenParams;
00118 myIgnoreBounds = config.myIgnoreBounds;
00119 myFailOnBadSection = config.myFailOnBadSection;
00120 mySection = config.mySection;
00121 mySectionBroken = config.mySectionBroken;
00122 myUsingSections = config.myUsingSections;
00123 myDuplicateParams = config.myDuplicateParams;
00124 mySections.clear();
00125 std::list<ArConfigSection *>::const_iterator it;
00126 for (it = config.mySections.begin();
00127 it != config.mySections.end();
00128 it++)
00129 {
00130 mySections.push_back(new ArConfigSection(*(*it)));
00131 }
00132 myParser.remHandler(&myParserCB);
00133 myParser.remHandler(&mySectionCB);
00134 addParserHandlers();
00135
00136 }
00137 return *this;
00138
00139 }
00140
00141 void ArConfig::clearSections(void)
00142 {
00143 while (mySections.begin() != mySections.end())
00144 {
00145 delete mySections.front();
00146 mySections.pop_front();
00147 }
00148 }
00149
00150 void ArConfig::clearAll(void)
00151 {
00152 clearSections();
00153 myProcessFileCBList.clear();
00154 }
00155
00156 void ArConfig::addParserHandlers(void)
00157 {
00158 std::list<ArConfigSection *>::const_iterator it;
00159 std::list<ArConfigArg> *params;
00160 std::list<ArConfigArg>::iterator pit;
00161
00162 if (!myParser.addHandlerWithError("section", &mySectionCB))
00163 ArLog::log(ArLog::Verbose,
00164 "ArConfig: Could not add section parser (probably unimportant)");
00165
00166 for (it = mySections.begin();
00167 it != mySections.end();
00168 it++)
00169 {
00170 params = (*it)->getParams();
00171 if (params == NULL)
00172 continue;
00173 for (pit = params->begin(); pit != params->end(); pit++)
00174 {
00175 if (!myParser.addHandlerWithError((*pit).getName(), &myParserCB))
00176 ArLog::log(ArLog::Verbose,
00177 "ArConfig: Could not add keyword %s (probably unimportant)",
00178 (*pit).getName());
00179 }
00180 }
00181
00182 }
00183
00188 void ArConfig::setSectionComment(const char *sectionName,
00189 const char *comment)
00190 {
00191 ArConfigSection *section = findSection(sectionName);
00192
00193 if (section == NULL)
00194 {
00195 ArLog::log(ArLog::Verbose, "Making new section '%s'", sectionName);
00196 section = new ArConfigSection(sectionName, comment);
00197 mySections.push_back(section);
00198 }
00199 else
00200 section->setComment(comment);
00201 }
00202
00203 bool ArConfig::addParam(const ArConfigArg &arg, const char *sectionName,
00204 ArPriority::Priority priority)
00205 {
00206 ArConfigSection *section = findSection(sectionName);
00207
00208
00209 if (section == NULL)
00210 {
00211 ArLog::log(ArLog::Verbose, "Making new section '%s'", sectionName);
00212 section = new ArConfigSection(sectionName);
00213 mySections.push_back(section);
00214 }
00215
00216 std::list<ArConfigArg> *params = section->getParams();
00217
00218 if (params == NULL)
00219 {
00220 ArLog::log(ArLog::Terse, "Something has gone hideously wrong in ArConfig::addParam");
00221 return false;
00222 }
00223
00224
00225
00226 std::list<ArConfigSection *>::iterator sectionIt;
00227
00228 for (sectionIt = mySections.begin();
00229 sectionIt != mySections.end();
00230 sectionIt++)
00231 {
00232
00233
00234
00235 if (strlen(arg.getName()) > 0 &&
00236 (*sectionIt)->findParam(arg.getName()) != NULL &&
00237 strcasecmp((*sectionIt)->getName(), section->getName()) != 0)
00238 {
00239 ArLog::log(ArLog::Normal,
00240 "Parameter %s duplicated in section %s and %s",
00241 arg.getName(), (*sectionIt)->getName(), section->getName());
00242 myDuplicateParams = true;
00243 }
00244 }
00245
00246
00247 if (!myParser.addHandlerWithError(arg.getName(), &myParserCB))
00248 {
00249 ArLog::log(ArLog::Verbose, "Could not add parameter '%s' to file parser, probably already there.",
00250 arg.getName());
00251
00252 }
00253
00254
00255 params->push_back(arg);
00256 params->back().setConfigPriority(priority);
00257 params->back().setIgnoreBounds(myIgnoreBounds);
00258
00259 ArLog::log(ArLog::Verbose, "Added parameter '%s'", arg.getName());
00260
00261 return true;
00262 }
00263
00267 bool ArConfig::addComment(const char *comment, const char *sectionName,
00268 ArPriority::Priority priority)
00269 {
00270 return addParam(ArConfigArg(comment), sectionName, priority);
00271 }
00272
00273
00274
00286 bool ArConfig::parseSection(ArArgumentBuilder *arg,
00287 char *errorBuffer,
00288 size_t errorBufferLen)
00289 {
00290 if (myFailOnBadSection && errorBuffer != NULL)
00291 errorBuffer[0] = '\0';
00292
00293 std::list<ArConfigSection *>::iterator sectionIt;
00294 ArConfigSection *section = NULL;
00295
00296 if (myFailOnBadSection && errorBuffer != NULL)
00297 errorBuffer[0] = '\0';
00298 for (sectionIt = mySections.begin();
00299 sectionIt != mySections.end();
00300 sectionIt++)
00301 {
00302 section = (*sectionIt);
00303 if (ArUtil::strcasecmp(section->getName(), arg->getFullString()) == 0)
00304 {
00305 ArLog::log(ArLog::Verbose, "Config switching to section '%s'",
00306 arg->getFullString());
00307
00308
00309 mySection = arg->getFullString();
00310 mySectionBroken = false;
00311 myUsingSections = true;
00312 return true;
00313 }
00314 }
00315
00316 mySection = "";
00317 mySectionBroken = true;
00318
00319 if (myFailOnBadSection)
00320 {
00321 snprintf(errorBuffer, errorBufferLen, "ArConfig: Could not find section '%s'",
00322 arg->getFullString());
00323
00324 ArLog::log(ArLog::Terse,
00325 "ArConfig: Could not find section '%s', failing",
00326 arg->getFullString());
00327 return false;
00328 }
00329 else
00330 {
00331 ArLog::log(ArLog::Normal,
00332 "ArConfig: Ignoring section '%s'",
00333 arg->getFullString());
00334 return true;
00335 }
00336 }
00337
00349 bool ArConfig::parseArgument(ArArgumentBuilder *arg,
00350 char *errorBuffer,
00351 size_t errorBufferLen)
00352 {
00353 std::list<ArConfigSection *>::iterator sectionIt;
00354 std::list<ArConfigArg>::iterator paramIt;
00355 ArConfigSection *section = NULL;
00356 std::list<ArConfigArg> *params = NULL;
00357 ArConfigArg *param = NULL;
00358 int valInt = 0;
00359 double valDouble = 0;
00360 bool valBool = false;
00361 bool ret = true;
00362
00363 if (mySectionBroken)
00364 {
00365 ArLog::log(ArLog::Verbose, "Skipping parameter %s because section broken",
00366 arg->getExtraString());
00367 if (myFailOnBadSection)
00368 {
00369 snprintf(errorBuffer, errorBufferLen,
00370 "Failed because broken config section");
00371 return false;
00372 }
00373 else
00374 {
00375 return true;
00376 }
00377 }
00378
00379
00380 if (myDuplicateParams && myUsingSections && mySection.size() <= 0)
00381 {
00382 snprintf(errorBuffer, errorBufferLen,
00383 "%s not in section, client needs an upgrade",
00384 arg->getExtraString());
00385
00386 ArLog::log(ArLog::Normal,
00387 "%s not in a section, client needs an upgrade",
00388 arg->getExtraString());
00389 return false;
00390 }
00391
00392 if (errorBuffer != NULL)
00393 errorBuffer[0] = '\0';
00394 for (sectionIt = mySections.begin();
00395 sectionIt != mySections.end();
00396 sectionIt++)
00397 {
00398 section = (*sectionIt);
00399
00400
00401 if (mySection.size() > 0 &&
00402 ArUtil::strcasecmp(mySection, section->getName()))
00403 continue;
00404 params = section->getParams();
00405
00406 for (paramIt = params->begin(); paramIt != params->end(); paramIt++)
00407 {
00408 if (strcasecmp((*paramIt).getName(), arg->getExtraString()) == 0)
00409 {
00410 param = &(*paramIt);
00411 if (param->getType() != ArConfigArg::STRING &&
00412 param->getType() != ArConfigArg::FUNCTOR &&
00413 arg->getArg(0) == NULL)
00414 {
00415 ArLog::log(ArLog::Verbose, "ArConfig: parameter '%s' has no argument.",
00416 param->getName());
00417 continue;
00418 }
00419 if (param->getType() == ArConfigArg::DESCRIPTION_HOLDER)
00420 {
00421
00422 }
00423
00424 else if (param->getType() == ArConfigArg::INT)
00425 {
00426
00427 if (!arg->isArgInt(0))
00428 {
00429 ArLog::log(ArLog::Terse, "ArConfig: parameter '%s' is an integer parameterbut was given non-integer argument of '%s'", param->getName(), arg->getArg(0));
00430 ret = false;
00431 if (errorBuffer != NULL)
00432 snprintf(errorBuffer, errorBufferLen, "%s is an integer parameter but was given non-integer argument of '%s'", param->getName(), arg->getArg(0));
00433 continue;
00434 }
00435 valInt = arg->getArgInt(0);
00436 if (param->setInt(valInt, errorBuffer, errorBufferLen))
00437 {
00438 ArLog::log(ArLog::Verbose, "Set parameter '%s' to '%d'",
00439 param->getName(), valInt);
00440 continue;
00441 }
00442 else
00443 {
00444 ArLog::log(ArLog::Verbose, "Could not parameter '%s' to '%d'",
00445 param->getName(), valInt);
00446 ret = false;
00447 continue;
00448 }
00449 }
00450 else if (param->getType() == ArConfigArg::DOUBLE)
00451 {
00452
00453 if (!arg->isArgDouble(0))
00454 {
00455 ArLog::log(ArLog::Terse, "ArConfig: parameter '%s' is a double parameter but was given non-double argument of '%s'", param->getName(), arg->getArg(0));
00456 if (errorBuffer != NULL)
00457 snprintf(errorBuffer, errorBufferLen, "%s is a double parameter but was given non-double argument of '%s'", param->getName(), arg->getArg(0));
00458
00459 ret = false;
00460 continue;
00461 }
00462 valDouble = arg->getArgDouble(0);
00463 if (param->setDouble(valDouble, errorBuffer, errorBufferLen))
00464 {
00465 ArLog::log(ArLog::Verbose, "Set parameter '%s' to '%.10f'",
00466 param->getName(), valDouble);
00467 continue;
00468 }
00469 else
00470 {
00471 ArLog::log(ArLog::Verbose, "Could not set parameter '%s' to '%.10f'",
00472 param->getName(), valDouble);
00473 ret = false;
00474 continue;
00475 }
00476 }
00477 else if (param->getType() == ArConfigArg::BOOL)
00478 {
00479
00480 if (!arg->isArgBool(0))
00481 {
00482 ArLog::log(ArLog::Terse, "ArConfig: parameter '%s' is a bool parameter but was given non-bool argument of '%s'", param->getName(), arg->getArg(0));
00483 ret = false;
00484 if (errorBuffer != NULL)
00485 snprintf(errorBuffer, errorBufferLen, "%s is a bool parameter but was given non-bool argument of '%s'", param->getName(), arg->getArg(0));
00486 continue;
00487 }
00488 valBool = arg->getArgBool(0);
00489 if (param->setBool(valBool, errorBuffer, errorBufferLen))
00490 {
00491 ArLog::log(ArLog::Verbose, "Set parameter '%s' to %s",
00492 param->getName(), valBool ? "true" : "false" );
00493 continue;
00494 }
00495 else
00496 {
00497 ArLog::log(ArLog::Verbose, "Could not set parameter '%s' to %s",
00498 param->getName(), valBool ? "true" : "false" );
00499 ret = false;
00500 continue;
00501 }
00502 }
00503 else if (param->getType() == ArConfigArg::STRING)
00504 {
00505 if (param->setString(arg->getFullString()))
00506 {
00507 ArLog::log(ArLog::Verbose, "Set parameter string '%s' to '%s'",
00508 param->getName(), param->getString());
00509 continue;
00510 }
00511 else
00512 {
00513 ArLog::log(ArLog::Verbose, "Could not set string parameter '%s' to '%s'",
00514 param->getName(), param->getString());
00515 if (errorBuffer != NULL && errorBuffer[0] == '\0')
00516 snprintf(errorBuffer, errorBufferLen, "%s could not be set to '%s'.", param->getName(), arg->getFullString());
00517
00518 ret = false;
00519 continue;
00520 }
00521 }
00522 else if (param->getType() == ArConfigArg::FUNCTOR)
00523 {
00524 if (param->setArgWithFunctor(arg))
00525 {
00526 ArLog::log(ArLog::Verbose, "Set arg '%s' with '%s'",
00527 param->getName(), arg->getFullString());
00528 continue;
00529 }
00530 else
00531 {
00532 ArLog::log(ArLog::Verbose, "Could not set parameter '%s' to '%s'",
00533 param->getName(), arg->getFullString());
00534
00535 if (errorBuffer != NULL && errorBuffer[0] == '\0')
00536 snprintf(errorBuffer, errorBufferLen, "%s could not be set to '%s'.", param->getName(), arg->getFullString());
00537 ret = false;
00538 continue;
00539 }
00540 }
00541 else
00542 {
00543 ArLog::log(ArLog::Terse, "Have no argument type for config '%s', got string '%s'.\n", param->getName(), arg->getFullString());
00544 }
00545 }
00546 }
00547 }
00548 return ret;
00549 }
00550
00564 bool ArConfig::parseFile(const char *fileName, bool continueOnErrors,
00565 bool noFileNotFoundMessage,
00566 char *errorBuffer,
00567 size_t errorBufferLen)
00568 {
00569 bool ret = true;
00570
00571 myFileName = fileName;
00572 if (errorBuffer != NULL)
00573 errorBuffer[0] = '\0';
00574
00575
00576 ret = myParser.parseFile(fileName, continueOnErrors, noFileNotFoundMessage);
00577
00578 if (errorBuffer != NULL && errorBuffer[0] != '\0')
00579 {
00580 errorBuffer = NULL;
00581 errorBufferLen = 0;
00582 }
00583
00584
00585
00586
00587 if (myArgumentParser != NULL && (ret || continueOnErrors))
00588 ret = ret && parseArgumentParser(myArgumentParser, continueOnErrors,
00589 errorBuffer, errorBufferLen);
00590
00591
00592 if (errorBuffer != NULL && errorBuffer[0] != '\0')
00593 {
00594 errorBuffer = NULL;
00595 errorBufferLen = 0;
00596 }
00597
00598
00599
00600
00601 if (ret || continueOnErrors)
00602 ret = ret && callProcessFileCallBacks(continueOnErrors, errorBuffer,
00603 errorBufferLen);
00604
00605
00606 if (errorBuffer != NULL && errorBuffer[0] != '\0')
00607 {
00608 errorBuffer = NULL;
00609 errorBufferLen = 0;
00610 }
00611
00612 return ret;
00613 }
00614
00627 bool ArConfig::writeFile(const char *fileName, bool append,
00628 std::set<std::string> *alreadyWritten,
00629 bool writePriorities)
00630 {
00631 FILE *file;
00632
00633
00634 char line[1024];
00635
00636 char startLine[128];
00637
00638 std::set<std::string> writtenSet;
00639 std::set<std::string> *written;
00640 if (alreadyWritten != NULL)
00641 written = alreadyWritten;
00642 else
00643 written = &writtenSet;
00644
00645 ArConfigArg *param = NULL;
00646
00647 std::list<ArArgumentBuilder *>::const_iterator argIt;
00648 const std::list<ArArgumentBuilder *> *argList = NULL;
00649
00650 bool commented = false;
00651
00652 std::string realFileName;
00653 if (fileName[0] == '/' || fileName[0] == '\\')
00654 {
00655 realFileName = fileName;
00656 }
00657 else
00658 {
00659 realFileName = myBaseDirectory;
00660 realFileName += fileName;
00661 }
00662
00663 unsigned int startCommentColumn = 25;
00664 std::string mode;
00665
00666 if (append)
00667 mode = "a";
00668 else
00669 mode = "w";
00670
00671 if ((file = fopen(realFileName.c_str(), mode.c_str())) == NULL)
00672 {
00673 ArLog::log(ArLog::Terse, "ArConfig: Cannot open file '%s' for writing",
00674 realFileName.c_str());
00675 return false;
00676 }
00677
00678 bool firstSection = true;
00679 std::list<ArConfigSection *>::iterator sectionIt;
00680 std::list<ArConfigArg>::iterator paramIt;
00681 ArConfigSection *section = NULL;
00682 std::list<ArConfigArg> *params = NULL;
00683 for (sectionIt = mySections.begin();
00684 sectionIt != mySections.end();
00685 sectionIt++)
00686 {
00687 section = (*sectionIt);
00689 written->clear();
00690
00691 if (!firstSection)
00692 fprintf(file, "\n");
00693 firstSection = false;
00694
00695 if (section->getName() != NULL && strlen(section->getName()) > 0)
00696 {
00697
00698 fprintf(file, "Section %s\n", section->getName());
00699 }
00700 sprintf(line, "; ");
00701 if (section->getComment() != NULL && strlen(section->getComment()) > 0)
00702 {
00703 ArArgumentBuilder descr;
00704 descr.add(section->getComment());
00705 for (unsigned int i = 0; i < descr.getArgc(); i++)
00706 {
00707
00708
00709 if (strlen(line) + strlen(descr.getArg(i)) > 78)
00710 {
00711 fprintf(file, "%s\n", line);
00712 sprintf(line, "; ");
00713 sprintf(line, "%s %s", line, descr.getArg(i));
00714 }
00715
00716 else
00717 {
00718 sprintf(line, "%s %s", line, descr.getArg(i));
00719 }
00720 }
00721
00722 fprintf(file, "%s\n", line);
00723 }
00724
00725 params = section->getParams();
00726
00727 for (paramIt = params->begin(); paramIt != params->end(); paramIt++)
00728 {
00729 commented = false;
00730 param = &(*paramIt);
00731
00732 if (written != NULL &&
00733 param->getType() != ArConfigArg::DESCRIPTION_HOLDER &&
00734 written->find(param->getName()) != written->end())
00735 continue;
00736 else if (written != NULL &&
00737 param->getType() != ArConfigArg::DESCRIPTION_HOLDER)
00738 {
00739 written->insert(param->getName());
00740 }
00741
00742
00743
00744 if (param->getType() == ArConfigArg::FUNCTOR)
00745 {
00746
00747 sprintf(line, "; ");
00748 if (param->getDescription() != NULL &&
00749 strlen(param->getDescription()) > 0)
00750 {
00751 ArArgumentBuilder descr;
00752 descr.add(param->getDescription());
00753 for (unsigned int i = 0; i < descr.getArgc(); i++)
00754 {
00755
00756
00757 if (strlen(line) + strlen(descr.getArg(i)) > 78)
00758 {
00759 fprintf(file, "%s\n", line);
00760 sprintf(line, "; ");
00761 sprintf(line, "%s %s", line, descr.getArg(i));
00762 }
00763
00764 else
00765 {
00766 sprintf(line, "%s %s", line, descr.getArg(i));
00767 }
00768 }
00769
00770 fprintf(file, "%s\n", line);
00771 }
00772
00773 argList = param->getArgsWithFunctor();
00774 if (argList != NULL)
00775 for (argIt = argList->begin(); argIt != argList->end(); argIt++)
00776 fprintf(file, "%s %s\n", param->getName(), (*argIt)->getFullString());
00777
00778
00779 continue;
00780 }
00781
00782 sprintf(line, "%s", param->getName());
00783 if (param->getType() == ArConfigArg::INT)
00784 {
00785 sprintf(line, "%s %d", line, param->getInt());
00786 }
00787 else if (param->getType() == ArConfigArg::DOUBLE)
00788 {
00789 sprintf(line, "%s %g", line, param->getDouble());
00790 }
00791 else if (param->getType() == ArConfigArg::STRING)
00792 {
00793 sprintf(line, "%s %s", line, param->getString());
00794 }
00795 else if (param->getType() == ArConfigArg::BOOL)
00796 {
00797 sprintf(line, "%s %s", line, param->getBool() ? "true" : "false");
00798 }
00799 else if (param->getType() == ArConfigArg::FUNCTOR)
00800 {
00801 }
00802 else if (param->getType() == ArConfigArg::DESCRIPTION_HOLDER)
00803 {
00804 if (strlen(param->getDescription()) == 0)
00805 {
00806 fprintf(file, "\n");
00807 continue;
00808 }
00809 }
00810 else
00811 {
00812 ArLog::log(ArLog::Terse, "ArConfig no argument type");
00813 }
00814
00815 if (param->getType() == ArConfigArg::DESCRIPTION_HOLDER)
00816 sprintf(startLine, "; ");
00817 else
00818 sprintf(startLine, "%%-%ds;", startCommentColumn);
00819
00820
00821 if (strlen(line) >= startCommentColumn)
00822 sprintf(line, "%-s ;", line);
00823
00824 else
00825 sprintf(line, startLine, line);
00826
00827 if (param->getType() == ArConfigArg::INT)
00828 {
00829 if (param->getMinInt() != INT_MIN && param->getMaxInt() != INT_MAX)
00830 {
00831 sprintf(line, "%s range [%d, %d], ", line,
00832 param->getMinInt(), param->getMaxInt());
00833 }
00834 else if (param->getMinInt() != INT_MIN)
00835 sprintf(line, "%s minumum %d, ", line, param->getMinInt());
00836 else if (param->getMaxInt() != INT_MAX)
00837 sprintf(line, "%s maximum %d, ", line, param->getMaxInt());
00838 }
00839 if (param->getType() == ArConfigArg::DOUBLE)
00840 {
00841 if (param->getMinDouble() != -HUGE_VAL &&
00842 param->getMaxDouble() != HUGE_VAL)
00843 sprintf(line, "%s range [%g, %g], ", line, param->getMinDouble(),
00844 param->getMaxDouble());
00845 else if (param->getMinDouble() != -HUGE_VAL)
00846 sprintf(line, "%s minimum %g, ", line,
00847 param->getMinDouble());
00848 else if (param->getMaxDouble() != HUGE_VAL)
00849 sprintf(line, "%s Maximum %g, ", line,
00850 param->getMaxDouble());
00851 }
00852
00853
00854 if (param->getDescription() != NULL &&
00855 strlen(param->getDescription()) > 0)
00856 {
00857 ArArgumentBuilder descr;
00858 descr.add(param->getDescription());
00859 for (unsigned int i = 0; i < descr.getArgc(); i++)
00860 {
00861
00862
00863 if (strlen(line) + strlen(descr.getArg(i)) > 78)
00864 {
00865 fprintf(file, "%s\n", line);
00866 sprintf(line, startLine, "");
00867 sprintf(line, "%s %s", line, descr.getArg(i));
00868 }
00869
00870 else
00871 {
00872 sprintf(line, "%s %s", line, descr.getArg(i));
00873 }
00874 }
00875
00876 fprintf(file, "%s\n", line);
00877 }
00878
00879 else
00880 fprintf(file, "%s\n", line);
00881
00882 if (writePriorities)
00883 {
00884 sprintf(line, startLine, "");
00885 fprintf(file, "%s Priority: %s\n", line,
00886 ArPriority::getPriorityName(param->getConfigPriority()));
00887 }
00888
00889 if (!myNoBlanksBetweenParams)
00890 fprintf(file, "\n");
00891 }
00892 }
00893 fclose(file);
00894 return true;
00895 }
00896
00897 const char *ArConfig::getBaseDirectory(void) const
00898 {
00899 return myBaseDirectory.c_str();
00900 }
00901
00902 void ArConfig::setBaseDirectory(const char *baseDirectory)
00903 {
00904 if (baseDirectory != NULL && strlen(baseDirectory) > 0)
00905 myBaseDirectory = baseDirectory;
00906 else
00907 myBaseDirectory = "";
00908
00909 myParser.setBaseDirectory(baseDirectory);
00910 }
00911
00912 const char *ArConfig::getFileName(void) const
00913 {
00914 return myFileName.c_str();
00915 }
00916
00933 void ArConfig::addProcessFileCB(ArRetFunctor<bool> *functor,
00934 int priority)
00935 {
00936 myProcessFileCBList.insert(
00937 std::pair<int, ProcessFileCBType *>(-priority,
00938 new ProcessFileCBType(functor)));
00939 }
00940
00944 void ArConfig::remProcessFileCB(ArRetFunctor<bool> *functor)
00945 {
00946 std::multimap<int, ProcessFileCBType *>::iterator it;
00947 ProcessFileCBType *cb;
00948
00949 for (it = myProcessFileCBList.begin(); it != myProcessFileCBList.end(); ++it)
00950 {
00951 if ((*it).second->haveFunctor(functor))
00952 {
00953 cb = (*it).second;
00954 myProcessFileCBList.erase(it);
00955 delete cb;
00956 remProcessFileCB(functor);
00957 }
00958 }
00959 }
00960
00984 void ArConfig::addProcessFileWithErrorCB(
00985 ArRetFunctor2<bool, char *, size_t> *functor,
00986 int priority)
00987 {
00988 myProcessFileCBList.insert(
00989 std::pair<int, ProcessFileCBType *>(-priority,
00990 new ProcessFileCBType(functor)));
00991 }
00992
00996 void ArConfig::remProcessFileCB(
00997 ArRetFunctor2<bool, char *, size_t> *functor)
00998 {
00999 std::multimap<int, ProcessFileCBType *>::iterator it;
01000 ProcessFileCBType *cb;
01001
01002 for (it = myProcessFileCBList.begin(); it != myProcessFileCBList.end(); ++it)
01003 {
01004 if ((*it).second->haveFunctor(functor))
01005 {
01006 cb = (*it).second;
01007 myProcessFileCBList.erase(it);
01008 delete cb;
01009 remProcessFileCB(functor);
01010 }
01011 }
01012 }
01013
01014 bool ArConfig::callProcessFileCallBacks(bool continueOnErrors,
01015 char *errorBuffer,
01016 size_t errorBufferLen)
01017 {
01018 bool ret = true;
01019 std::multimap<int, ProcessFileCBType *>::iterator it;
01020 ProcessFileCBType *callback;
01021 ArLog::LogLevel level = myProcessFileCallbacksLogLevel;
01022
01023
01024 mySection = "";
01025
01026
01027
01028
01029
01030 if (errorBuffer != NULL)
01031 errorBuffer[0] = '\0';
01032
01033 ArLog::log(level, "ArConfig: Processing file");
01034 for (it = myProcessFileCBList.begin();
01035 it != myProcessFileCBList.end();
01036 ++it)
01037 {
01038 callback = (*it).second;
01039 if (callback->getName() != NULL && callback->getName()[0] != '\0')
01040 ArLog::log(level, "ArConfig: Processing functor '%s' (%d)",
01041 callback->getName(), -(*it).first);
01042 else
01043 ArLog::log(level, "ArConfig: Processing unnamed functor (%d)", -(*it).first);
01044 if (!(*it).second->call(errorBuffer, errorBufferLen))
01045 {
01046
01047
01048
01049
01050 if (errorBuffer != NULL && errorBuffer[0] != '\0')
01051 {
01052 errorBuffer = NULL;
01053 errorBufferLen = 0;
01054 }
01055 ret = false;
01056 if (!continueOnErrors)
01057 {
01058 if (callback->getName() != NULL && callback->getName()[0] != '\0')
01059 ArLog::log(ArLog::Normal, "ArConfig: Failed, stopping because the '%s' process file callback failed",
01060 callback->getName());
01061 else
01062 ArLog::log(ArLog::Normal, "ArConfig: Failed, stopping because unnamed process file callback failed");
01063 break;
01064 }
01065 else
01066 {
01067 if (callback->getName() != NULL && callback->getName()[0] != '\0')
01068 ArLog::log(ArLog::Normal, "ArConfig: Failed but continuing, the '%s' process file callback failed",
01069 callback->getName());
01070 else
01071 ArLog::log(ArLog::Normal, "ArConfig: Failed but continuing, an unnamed process file callback failed");
01072 }
01073
01074 }
01075 }
01076 if (ret || continueOnErrors)
01077 {
01078 ArLog::log(level, "ArConfig: Processing with own processFile");
01079 if (!processFile())
01080 ret = false;
01081 }
01082 ArLog::log(level, "ArConfig: Done processing file, ret is %s",
01083 ArUtil::convertBool(ret));
01084
01085 return ret;
01086 }
01087
01088
01089 std::list<ArConfigSection *> *ArConfig::getSections(void)
01090 {
01091 return &mySections;
01092 }
01093
01094 void ArConfig::setNoBlanksBetweenParams(bool noBlanksBetweenParams)
01095 {
01096 myNoBlanksBetweenParams = noBlanksBetweenParams;
01097 }
01098
01099 bool ArConfig::getNoBlanksBetweenParams(void)
01100 {
01101 return myNoBlanksBetweenParams;
01102 }
01103
01109 void ArConfig::useArgumentParser(ArArgumentParser *parser)
01110 {
01111 myArgumentParser = parser;
01112 }
01113
01114 bool ArConfig::parseArgumentParser(ArArgumentParser *parser,
01115 bool continueOnError,
01116 char *errorBuffer,
01117 size_t errorBufferLen)
01118 {
01119 std::list<ArConfigSection *>::iterator sectionIt;
01120 std::list<ArConfigArg>::iterator paramIt;
01121 ArConfigSection *section = NULL;
01122 ArConfigArg *param = NULL;
01123 std::list<ArConfigArg> *params = NULL;
01124
01125 bool ret;
01126 size_t i;
01127 std::string strArg;
01128 std::string strUndashArg;
01129 ArArgumentBuilder builder;
01130 bool plainMatch;
01131
01132 for (i = 0; i < parser->getArgc(); i++)
01133 {
01134 if (parser->getArg(i) == NULL)
01135 {
01136 ArLog::log(ArLog::Terse, "ArConfig set up wrong (parseArgumentParser broken).");
01137 if (errorBuffer != NULL)
01138 strncpy(errorBuffer,
01139 "ArConfig set up wrong (parseArgumentParser broken).",
01140 errorBufferLen);
01141 return false;
01142 }
01143 strArg = parser->getArg(i);
01144 if (parser->getArg(i)[0] == '-')
01145 strUndashArg += &parser->getArg(i)[1];
01146 else
01147 strUndashArg = "";
01148
01149 for (sectionIt = mySections.begin();
01150 sectionIt != mySections.end();
01151 sectionIt++)
01152 {
01153 section = (*sectionIt);
01154 params = section->getParams();
01155 for (paramIt = params->begin(); paramIt != params->end(); paramIt++)
01156 {
01157 param = &(*paramIt);
01158
01159
01160
01161
01162
01163
01164 if (strlen(param->getName()) > 0 &&
01165 ((plainMatch = ArUtil::strcasecmp(param->getName(),strArg)) == 0 ||
01166 ArUtil::strcasecmp(param->getName(), strUndashArg) == 0))
01167 {
01168 if (plainMatch == 0)
01169 builder.setExtraString(strArg.c_str());
01170 else
01171 builder.setExtraString(strUndashArg.c_str());
01172 if (i+1 < parser->getArgc())
01173 {
01174 builder.add(parser->getArg(i+1));
01175 parser->removeArg(i+1);
01176 }
01177 parser->removeArg(i);
01178
01179
01180 std::string oldSection = mySection;
01181 bool oldSectionBroken = mySectionBroken;
01182 bool oldUsingSections = myUsingSections;
01183 bool oldDuplicateParams = myDuplicateParams;
01184 mySection = section->getName();
01185 mySectionBroken = false;
01186 myUsingSections = true;
01187 myDuplicateParams = false;
01188 ret = parseArgument(&builder, errorBuffer, errorBufferLen);
01189 mySection = oldSection;
01190 mySectionBroken = oldSectionBroken;
01191 myUsingSections = oldUsingSections;
01192 myDuplicateParams = oldDuplicateParams;
01193
01194
01195
01196 if (ret || continueOnError)
01197 {
01198
01199 return ret && parseArgumentParser(parser, continueOnError,
01200 errorBuffer, errorBufferLen);
01201 }
01202 else
01203 return false;
01204 }
01205 }
01206 }
01207 }
01208
01209 return true;
01210 }
01211
01212 ArConfigSection::ArConfigSection(const char *name,
01213 const char *comment)
01214 {
01215 myName = name;
01216 if (comment != NULL)
01217 myComment = comment;
01218 else
01219 myComment = "";
01220 }
01221
01222
01223 ArConfigSection::ArConfigSection(const ArConfigSection §ion)
01224 {
01225 myName = section.myName;
01226 myComment = section.myComment;
01227 for (std::list<ArConfigArg>::const_iterator it = section.myParams.begin();
01228 it != section.myParams.end();
01229 it++)
01230 {
01231 myParams.push_back(*it);
01232 }
01233 }
01234
01235 ArConfigSection &ArConfigSection::operator=(const ArConfigSection §ion)
01236 {
01237 if (this != §ion)
01238 {
01239
01240 myName = section.getName();
01241 myComment = section.getComment();
01242
01243 myParams.clear();
01244
01245 for (std::list<ArConfigArg>::const_iterator it = section.myParams.begin();
01246 it != section.myParams.end();
01247 it++)
01248 {
01249 myParams.push_back(*it);
01250 }
01251 }
01252 return *this;
01253 }
01254
01255
01256
01257 ArConfigSection::~ArConfigSection()
01258 {
01259
01260 }
01261
01262
01263 ArConfigSection *ArConfig::findSection(const char *sectionName) const
01264 {
01265 ArConfigSection *section = NULL;
01266 ArConfigSection *tempSection = NULL;
01267
01268 for (std::list<ArConfigSection *>::const_iterator sectionIt = mySections.begin();
01269 sectionIt != mySections.end();
01270 sectionIt++)
01271 {
01272 tempSection = (*sectionIt);
01273 if (ArUtil::strcasecmp(tempSection->getName(), sectionName) == 0)
01274 {
01275 section = tempSection;
01276 }
01277 }
01278 return section;
01279
01280 }
01281
01282 ArConfigArg *ArConfigSection::findParam(const char *paramName)
01283 {
01284 ArConfigArg *param = NULL;
01285 ArConfigArg *tempParam = NULL;
01286
01287 for (std::list<ArConfigArg>::iterator pIter = myParams.begin();
01288 pIter != myParams.end();
01289 pIter++)
01290 {
01291
01292 tempParam = &(*pIter);
01293 if (ArUtil::strcasecmp(tempParam->getName(), paramName) == 0)
01294 {
01295 param = tempParam;
01296 }
01297 }
01298 return param;
01299
01300 }
01301
01302
01303