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 "ArFileParser.h"
00030 #include "ArLog.h"
00031 #include "ariaUtil.h"
00032 #include <ctype.h>
00033
00034 ArFileParser::ArFileParser(const char *baseDirectory)
00035 {
00036 myRemainderHandler = NULL;
00037 setBaseDirectory(baseDirectory);
00038 resetCounters();
00039 }
00040
00041 ArFileParser::~ArFileParser(void)
00042 {
00043
00044 }
00045
00046 bool ArFileParser::addHandler(
00047 const char *keyword, ArRetFunctor1<bool, ArArgumentBuilder *> *functor)
00048 {
00049 std::map<std::string, HandlerCBType *, ArStrCaseCmpOp>::iterator it;
00050 if (keyword == NULL)
00051 {
00052 if (myRemainderHandler != NULL)
00053 {
00054 ArLog::log(ArLog::Verbose, "There is already a functor to handle unhandled lines");
00055 return false;
00056 }
00057 else
00058 {
00059 delete myRemainderHandler;
00060 myRemainderHandler = new HandlerCBType(functor);
00061 return true;
00062 }
00063 }
00064
00065 if ((it = myMap.find(keyword)) != myMap.end())
00066 {
00067 ArLog::log(ArLog::Verbose, "There is already a functor to handle keyword '%s'", keyword);
00068 return false;
00069 }
00070 ArLog::log(ArLog::Verbose, "keyword '%s' handler added", keyword);
00071 myMap[keyword] = new HandlerCBType(functor);
00072 return true;
00073 }
00074
00081 bool ArFileParser::addHandlerWithError(
00082 const char *keyword,
00083 ArRetFunctor3<bool, ArArgumentBuilder *, char *, size_t> *functor)
00084 {
00085 std::map<std::string, HandlerCBType *, ArStrCaseCmpOp>::iterator it;
00086 if (keyword == NULL)
00087 {
00088 if (myRemainderHandler != NULL)
00089 {
00090 ArLog::log(ArLog::Verbose, "There is already a functor to handle unhandled lines");
00091 return false;
00092 }
00093 else
00094 {
00095 delete myRemainderHandler;
00096 myRemainderHandler = new HandlerCBType(functor);
00097 return true;
00098 }
00099 }
00100
00101 if ((it = myMap.find(keyword)) != myMap.end())
00102 {
00103 ArLog::log(ArLog::Verbose, "There is already a functor to handle keyword '%s'", keyword);
00104 return false;
00105 }
00106 ArLog::log(ArLog::Verbose, "keyword '%s' handler added", keyword);
00107 myMap[keyword] = new HandlerCBType(functor);
00108 return true;
00109 }
00110
00111 bool ArFileParser::remHandler(const char *keyword,
00112 bool logIfCannotFind)
00113 {
00114 std::map<std::string, HandlerCBType *, ArStrCaseCmpOp>::iterator it;
00115 HandlerCBType *handler;
00116
00117 if (myRemainderHandler != NULL && keyword == NULL)
00118 {
00119 delete myRemainderHandler;
00120 myRemainderHandler = NULL;
00121 ArLog::log(ArLog::Verbose, "Functor for remainder handler removed");
00122 return true;
00123 }
00124
00125 if ((it = myMap.find(keyword)) == myMap.end())
00126 {
00127 if (logIfCannotFind)
00128 ArLog::log(ArLog::Normal, "There is no keyword '%s' to remove.",
00129 keyword);
00130 return false;
00131 }
00132 ArLog::log(ArLog::Verbose, "keyword '%s' removed", keyword);
00133 handler = (*it).second;
00134 myMap.erase(it);
00135 delete handler;
00136 remHandler(keyword, false);
00137 return true;
00138
00139 }
00140
00141 bool ArFileParser::remHandler(
00142 ArRetFunctor1<bool, ArArgumentBuilder *> *functor)
00143 {
00144 std::map<std::string, HandlerCBType *, ArStrCaseCmpOp>::iterator it;
00145 HandlerCBType *handler;
00146
00147 if (myRemainderHandler != NULL && myRemainderHandler->haveFunctor(functor))
00148 {
00149 delete myRemainderHandler;
00150 myRemainderHandler = NULL;
00151 ArLog::log(ArLog::Verbose, "Functor for remainder handler removed");
00152 return true;
00153 }
00154
00155 for (it = myMap.begin(); it != myMap.end(); it++)
00156 {
00157 if ((*it).second->haveFunctor(functor))
00158 {
00159 ArLog::log(ArLog::Verbose, "Functor for keyword '%s' removed.",
00160 (*it).first.c_str());
00161 handler = (*it).second;
00162 myMap.erase(it);
00163 delete handler;
00164 remHandler(functor);
00165 return true;
00166 }
00167 }
00168 return false;
00169
00170 }
00171
00172 bool ArFileParser::remHandler(
00173 ArRetFunctor3<bool, ArArgumentBuilder *, char *, size_t> *functor)
00174 {
00175 std::map<std::string, HandlerCBType *, ArStrCaseCmpOp>::iterator it;
00176 HandlerCBType *handler;
00177
00178 if (myRemainderHandler != NULL && myRemainderHandler->haveFunctor(functor))
00179 {
00180 delete myRemainderHandler;
00181 myRemainderHandler = NULL;
00182 ArLog::log(ArLog::Verbose, "Functor for remainder handler removed");
00183 return true;
00184 }
00185
00186 for (it = myMap.begin(); it != myMap.end(); it++)
00187 {
00188 if ((*it).second->haveFunctor(functor))
00189 {
00190 ArLog::log(ArLog::Verbose, "Functor for keyword '%s' removed.",
00191 (*it).first.c_str());
00192 handler = (*it).second;
00193 myMap.erase(it);
00194 delete handler;
00195 remHandler(functor);
00196 return true;
00197 }
00198 }
00199 return false;
00200
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 void ArFileParser::setBaseDirectory(const char *baseDirectory)
00218 {
00219 if (baseDirectory != NULL && strlen(baseDirectory) > 0)
00220 myBaseDir = baseDirectory;
00221 else
00222 myBaseDir = "";
00223 }
00224
00225 const char *ArFileParser::getBaseDirectory(void) const
00226 {
00227 return myBaseDir.c_str();
00228 }
00229
00230 void ArFileParser::resetCounters(void)
00231 {
00232 myLineNumber = 0;
00233 }
00234
00235 bool ArFileParser::parseLine(char *line,
00236 char *errorBuffer, size_t errorBufferLen)
00237 {
00238 char keyword[512];
00239 char *choppingPos;
00240 char *valueStart;
00241 size_t textStart;
00242 size_t len;
00243 size_t i;
00244 bool noArgs;
00245 std::map<std::string, HandlerCBType *, ArStrCaseCmpOp>::iterator it;
00246 HandlerCBType *handler;
00247
00248 myLineNumber++;
00249 noArgs = false;
00250
00251
00252 if ((choppingPos = strstr(line, ";")) != NULL)
00253 line[choppingPos-line] = '\0';
00254 if ((choppingPos = strstr(line, "#")) != NULL)
00255 line[choppingPos-line] = '\0';
00256
00257
00258
00259
00260 if ((choppingPos = strstr(line, "\n")) != NULL)
00261 line[choppingPos-line] = '\0';
00262
00263 while ((choppingPos = strstr(line, "\r")) != NULL)
00264 memmove(choppingPos, choppingPos + 1, strlen(line));
00265
00266
00267 len = strlen(line);
00268
00269
00270
00271 if (len == 0)
00272 {
00273 ArLog::log(ArLog::Verbose, "line %d: empty line", myLineNumber);
00274 return true;
00275 }
00276
00277 for (i = 0; i < len; i++)
00278 {
00279
00280 if (!isspace(line[i]))
00281 {
00282 textStart = i;
00283 break;
00284 };
00285 }
00286
00287 if (i == len)
00288 {
00289 ArLog::log(ArLog::Verbose, "line %d: just white space at start of line", myLineNumber);
00290 return true;
00291 }
00292
00293 for (i = textStart;
00294 i < len && i < sizeof(keyword) + textStart - 1;
00295 i++)
00296 {
00297
00298 if (isspace(line[i]))
00299 break;
00300
00301 else
00302 keyword[i-textStart] = line[i];
00303 }
00304 keyword[i] = '\0';
00305
00306
00307 for (; i < len; i++)
00308 {
00309
00310 if (!isspace(line[i]))
00311 {
00312 valueStart = &line[i];
00313 break;
00314 };
00315 }
00316
00317 ArUtil::lower(keyword, keyword, 512);
00318
00319
00320 if ((it = myMap.find(keyword)) != myMap.end())
00321 {
00322
00323
00324 handler = (*it).second;
00325
00326 if (i == len)
00327 noArgs = true;
00328 }
00329
00330 else
00331 {
00332
00333
00334 if (myRemainderHandler != NULL)
00335 {
00336 handler = myRemainderHandler;
00337
00338 valueStart = &line[textStart];
00339 }
00340
00341 else
00342 {
00343 ArLog::log(ArLog::Verbose,
00344 "line %d: unknown keyword '%s' line '%s', continuing",
00345 myLineNumber, keyword, &line[textStart]);
00346 return true;
00347 }
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 ArArgumentBuilder builder;
00361
00362 if (!noArgs)
00363 builder.add(valueStart);
00364
00365 builder.setExtraString(keyword);
00366
00367
00368 if (errorBuffer != NULL && errorBuffer[0] != '\0')
00369 {
00370 errorBuffer = NULL;
00371 errorBufferLen = 0;
00372 }
00373
00374
00375
00376 if (!handler->call(&builder, errorBuffer, errorBufferLen))
00377 {
00378
00379
00380 if (errorBuffer != NULL)
00381 {
00382 std::string errorString = errorBuffer;
00383 snprintf(errorBuffer, errorBufferLen, "Line %d: %s", myLineNumber,
00384 errorString.c_str());
00385
00386 }
00387 return false;
00388 }
00389 return true;
00390 }
00391
00407 bool ArFileParser::parseFile(const char *fileName,
00408 bool continueOnErrors,
00409 bool noFileNotFoundMessage,
00410 char *errorBuffer,
00411 size_t errorBufferLen)
00412 {
00413 FILE *file;
00414
00415 char line[10000];
00416 bool ret = true;
00417
00418 if (errorBuffer)
00419 errorBuffer[0] = '\0';
00420
00421 std::string realFileName;
00422 if (fileName[0] == '/' || fileName[0] == '\\')
00423 {
00424 realFileName = fileName;
00425 }
00426 else
00427 {
00428 realFileName = myBaseDir;
00429 realFileName += fileName;
00430 }
00431
00432 ArLog::log(ArLog::Verbose, "Opening file %s from fileName given %s and base directory %s", realFileName.c_str(), fileName, myBaseDir.c_str());
00433
00434
00435
00436 if ((file = fopen(realFileName.c_str(), "r")) == NULL)
00437 {
00438 if (errorBuffer != NULL)
00439 snprintf(errorBuffer, errorBufferLen, "cannot open file %s", fileName);
00440 if (!noFileNotFoundMessage)
00441 ArLog::log(ArLog::Terse, "ArFileParser::parseFile: Could not open file %s to parse file.", realFileName.c_str());
00442 return false;
00443 }
00451 resetCounters();
00452
00453 while (fgets(line, sizeof(line), file) != NULL)
00454 {
00455 if (!parseLine(line, errorBuffer, errorBufferLen))
00456 {
00457 ArLog::log(ArLog::Terse, "## Last error on line %d of file '%s'",
00458 myLineNumber, realFileName.c_str());
00459 ret = false;
00460 if (!continueOnErrors)
00461 break;
00462 }
00463 }
00464
00465 fclose(file);
00466 return ret;
00467 }
00468
00469
00470 bool ArFileParser::parseFile(FILE *file, char *buffer,
00471 int bufferLength,
00472 bool continueOnErrors,
00473 char *errorBuffer,
00474 size_t errorBufferLen)
00475 {
00476 if (errorBuffer)
00477 errorBuffer[0] = '\0';
00478
00479 if ((file == NULL) || (buffer == NULL) || (bufferLength <= 0))
00480 {
00481 if (errorBuffer != NULL)
00482 snprintf(errorBuffer, errorBufferLen, "parseFile: bad setup");
00483 return false;
00484 }
00485
00486 bool ret = true;
00487 resetCounters();
00488
00489
00490 while (fgets(buffer, bufferLength, file) != NULL)
00491 {
00492 if (!parseLine(buffer, errorBuffer, errorBufferLen))
00493 {
00494 ret = false;
00495 if (!continueOnErrors)
00496 break;
00497 }
00498 }
00499 return ret;
00500 }