00001 #ifndef Impala_Basis_CmdOptions_h
00002 #define Impala_Basis_CmdOptions_h
00003
00004 #include <vector>
00005 #include <iterator>
00006
00007 #include "Basis/FileName.h"
00008 #include "Basis/FileReadString.h"
00009 #include "Basis/FileExists.h"
00010 #include "Basis/LogSystem.h"
00011 #include "Basis/ILog.h"
00012
00013 namespace Impala
00014 {
00015
00016 class CmdOptions
00017 {
00018 public:
00019
00020 static CmdOptions&
00021 GetInstance()
00022 {
00023 static CmdOptions theCmdOptions;
00024 return theCmdOptions;
00025 }
00026
00027 void
00028 Initialise(bool stdVideoOptions = false, bool stdGaussOptions = false,
00029 bool stdDatabaseOptions = false)
00030 {
00031 if (stdVideoOptions)
00032 {
00033 AddOption(0, "wndWidth", "size", "-1");
00034 AddOption(0, "wndHeight", "size", "-1");
00035 AddOption(0, "viewScale", "scale", "1.0");
00036 AddOption('s', "src", "type", "",
00037 "dx|avi|mpeg2|mpeg2es|lavc|lavcnoidx|lavcwithidx|lavcwriteidx");
00038 AddOption(0, "srcWindow", "type", "",
00039 "size;3;copyreal|size;5;rgb2ooo|size;5;gauss;0.75;0;0;3.0");
00040 AddOption(0, "step", "", "0");
00041 AddOption(0, "loop", "", "0");
00042 AddOption(0, "startFrame","nr", "0");
00043 AddOption(0, "stepSize", "nr", "1");
00044 AddOption(0, "numberFrames", "nr", "-1");
00045 AddOption(0, "delay", "nrFrames","0");
00046 AddOption(0, "jmp","type","pos","pos|pts");
00047 AddOption(0, "fixIdx", "Fix Broken indexes for LAVC", "1");
00048 }
00049 if (stdGaussOptions)
00050 {
00051 AddOption(0, "sigma", "val", "1.0");
00052 AddOption(0, "precision", "val", "3.0");
00053 AddOption(0, "recGauss", "", "0");
00054 AddOption(0, "disp", "mode", "LogMagnitude");
00055 AddOption(0, "logScale", "val", "32.0");
00056 }
00057 if (stdDatabaseOptions)
00058 {
00059 AddOption(0, "data", "path", ".", 0, true);
00060 AddOption(0, "dataServer", "machine:port", "", 0, true);
00061 AddOption(0, "mapi", "machine:port[:db]", "", 0, true);
00062 AddOption(0, "passwordFile", "filename", ".passwords", 0, true);
00063 AddOption(0, "videoSet", "filename", "", 0, true);
00064 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00065 AddOption(0, "videoSetRepository", "filename", "../videosets.txt",
00066 0, true);
00067 #endif // REPOSITORY_USED
00068 AddOption(0, "videoSetsRepository", "filename", "videosets.txt",
00069 0, true);
00070 AddOption(0, "imageSet", "filename", "", 0, true);
00071 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00072 AddOption(0, "imageSetRepository", "filename", "../imagesets.txt",
00073 0, true);
00074 #endif // REPOSITORY_USED
00075 AddOption(0, "imageSetsRepository", "filename", "imagesets.txt",
00076 0, true);
00077 AddOption(0, "override", "", "0");
00078 }
00079 AddOption(0, "tmpPath", "folder", "");
00080 #ifdef CUDA
00081 AddOption(0, "cudaDevice", "index", "0");
00082 #endif
00083 }
00084
00085 void
00086 AddOption(char optNameS, const char* optNameL, const char* parName,
00087 const char* defVal, const char* alternatives = 0,
00088 bool defaultFromEnv = false)
00089 {
00090 mOptNameS.push_back(optNameS);
00091 mOptNameL.push_back(String(optNameL));
00092 mOptParName.push_back(parName);
00093 String stringDef(defVal);
00094 if (defaultFromEnv)
00095 {
00096 char* str;
00097 str = getenv(optNameL);
00098 if (str != 0)
00099 stringDef = str;
00100 }
00101 mOptDefVal.push_back(stringDef);
00102 mOptVal.push_back(stringDef);
00103 if (alternatives)
00104 mOptAlt.push_back(alternatives);
00105 else
00106 mOptAlt.push_back("");
00107 mOptHideUsage.push_back(false);
00108 }
00109
00110 void
00111 SetDefault(char* optNameL, char* defVal)
00112 {
00113 int i = GetOptIdx(String(optNameL));
00114 if (i < 0)
00115 return;
00116 mOptVal[i] = String(defVal);
00117 }
00118
00119 bool
00120 ParseArgs(int argc, char* argv[], String usageStr, int nrReqArgs = 0)
00121 {
00122 if ((argc > 1) && (String(argv[1]) == "--version"))
00123 {
00124 std::cout << "Impala version " << IMPALA_VERSION_STR
00125 << ", svnversion " << SVN_VERSION_STR
00126 << ", build on " << __DATE__ << " at " << __TIME__
00127 << std::endl;
00128 return false;
00129 }
00130
00131 String parseError = DoParseArgs(argc, argv, usageStr, nrReqArgs);
00132 ConfigureLogSystem();
00133 if (parseError.empty())
00134 return true;
00135
00136 ILOG_ERROR(parseError);
00137 ShowUsage(argv[0], usageStr);
00138 return false;
00139 }
00140
00141 int
00142 GetNrArg()
00143 {
00144 return mArg.size();
00145 }
00146
00147 String
00148 GetArg(int i)
00149 {
00150 if ((i<0) || (i>=mArg.size()))
00151 {
00152 std::cout << "CmdOptions: no argument " << i << std::endl;
00153 return String("");
00154 }
00155 return mArg[i];
00156 }
00157
00158 String
00159 GetString(String optL, String defVal = "")
00160 {
00161 int i = GetOptIdx(optL);
00162 if (i < 0)
00163 return defVal;
00164 return mOptVal[i];
00165 }
00166
00167 int
00168 GetInt(String optL, int defVal = -1)
00169 {
00170 int i = GetOptIdx(optL);
00171 if (i < 0)
00172 return defVal;
00173 String s = mOptVal[i];
00174 return atoi(s);
00175 }
00176
00177 double
00178 GetDouble(String optL, double defVal = -1)
00179 {
00180 int i = GetOptIdx(optL);
00181 if (i < 0)
00182 return defVal;
00183 String s = mOptVal[i];
00184 return atof(s);
00185 }
00186
00187 bool
00188 GetBool(String optL, bool defVal = false)
00189 {
00190 int i = GetOptIdx(optL);
00191 if (i < 0)
00192 return defVal;
00193 String s = mOptVal[i];
00194 if (atoi(s) != 0)
00195 return true;
00196 if (s == "yes" || s == "true")
00197 return true;
00198 return false;
00199 }
00200
00201 void
00202 PrintArgs(std::ostream& os)
00203 {
00204 for (int i = 0 ; i < mOptNameL.size() ; ++i)
00205 os << mOptNameL[i] << " => " << mOptVal[i] << "\n";
00206 os << std::endl;
00207 }
00208
00209 void
00210 HideUsageFor(String parameter)
00211 {
00212 int idx = GetOptIdx(parameter);
00213 if (idx < 0)
00214 return;
00215 mOptHideUsage[idx] = true;
00216 }
00217
00218 private:
00219
00220 CmdOptions()
00221 {
00222 AddOption('v', "verb", "level", "0");
00223 AddOption(0, "debug", "", "0");
00224 AddOption(0, "debugCat", "categories separated with ';' or ':'", "");
00225 AddOption(0, "logProperties", "fileName", "./log4cpp.properties");
00226 AddOption(0, "logFile", "fileName", "");
00227 AddOption(0, "logLayout", "layoutPattern",
00228 "%d{%a%d %H:%M:%S,%l} %-5p [%c %x] %m%n");
00229 AddOption(0, "noErrorLog", "", "0");
00230 AddOption(0, "jobErrorLog", "fileName", "");
00231 AddOption(0, "exitOnErrorLogged", "", "0");
00232 AddOption(0, "logFlushOutput", "flag", "0");
00233 AddOption(0, "showProgress", "flag", "1");
00234 AddOption(0, "ini", "filename", "");
00235 }
00236
00237 CmdOptions(const CmdOptions&)
00238 {
00239 }
00240
00241 CmdOptions&
00242 operator=(const CmdOptions&)
00243 {
00244 }
00245
00246 virtual
00247 ~CmdOptions()
00248 {
00249 }
00250
00251 int
00252 NrOpt()
00253 {
00254 return mOptNameL.size();
00255 }
00256
00257 int
00258 GetOptIdx(String s)
00259 {
00260 for (int i=0 ; i<NrOpt() ; i++)
00261 {
00262 if ((s.size() == 1) && (s[0] == mOptNameS[i]))
00263 return i;
00264 if (s.compare(mOptNameL[i]) == 0)
00265 return i;
00266 }
00267 return -1;
00268 }
00269
00270 bool
00271 IsOpt(String s)
00272 {
00273 return (s[0] == '-');
00274 }
00275
00276 bool
00277 IsOptS(String s)
00278 {
00279 return ((s[0] == '-') && (s[1] != '-'));
00280 }
00281
00282 bool
00283 IsOptL(String s)
00284 {
00285 return ((s[0] == '-') && (s[1] == '-'));
00286 }
00287
00288 void
00289 CheckDynamicOption(String s)
00290 {
00291 if (StringStartsWith(s, "data::"))
00292 {
00293 AddOption(0, s.c_str(), "prefixPath", "");
00294 }
00295 if (StringStartsWith(s, "dataServer::"))
00296 {
00297 AddOption(0, s.c_str(), "otherServer", "");
00298 }
00299 }
00300
00301 String
00302 DoParseArgs(int argc, char* argv[], String usageStr, int nrReqArgs)
00303 {
00304 if (argc < nrReqArgs + 1)
00305 {
00306 for(int i=0 ; i<argc ; i++)
00307 std::cout << argv[i] << std::endl;
00308 return "Need more arguments: " + MakeString(argc-1) + " found, "
00309 + MakeString(nrReqArgs) + " expected";
00310 }
00311
00312
00313 String fileName(argv[0]);
00314 bool sawIniOption = false;
00315 fileName = FileNameBase(fileName) + ".ini";
00316 int i = 1;
00317 while (i < argc)
00318 {
00319 String s = String(argv[i]);
00320 if (s == "--ini")
00321 {
00322 if (i+1 >= argc)
00323 return "Missing value for --ini";
00324
00325 if (argv[i+1][0] == '-')
00326 return "Missing value for --ini";
00327
00328 sawIniOption = true;
00329 fileName = String(argv[i+1]);
00330 break;
00331 }
00332 i++;
00333 }
00334 if (sawIniOption && !FileExists(fileName))
00335 return "Couldn't open ini file " + fileName;
00336
00337 ReadIniFile(fileName);
00338
00339 i = 1;
00340 while (i < argc)
00341 {
00342 String s = String(argv[i]);
00343 if ((s == "-h") || (s == "--help"))
00344 return "help";
00345
00346 if (IsOpt(s))
00347 {
00348 s = s.substr(s.rfind('-',2)+1);
00349 CheckDynamicOption(s);
00350 int idx = GetOptIdx(s);
00351 if (idx < 0)
00352 {
00353 if (s != "ini")
00354 return "Unknown option --" + s;
00355
00356 }
00357 else if (mOptParName[idx] != "")
00358 {
00359 if (i+1 >= argc)
00360 return "Missing value for --" + s;
00361
00362 if (argv[i+1][0] == '-')
00363 return "Missing value for --" + s;
00364
00365 String tmp(argv[i+1]);
00366 if (tmp[0] == '"')
00367 {
00368 while (tmp[tmp.size()-1] != '"')
00369 {
00370 i++;
00371 if (i + 1 >= argc)
00372 return "Quoted string not terminated";
00373
00374 tmp = tmp + " " + String(argv[i+1]);
00375 }
00376 tmp = tmp.substr(1, tmp.size()-2);
00377 if (tmp[0] == '"')
00378 tmp = tmp.substr(1, tmp.size()-2);
00379 }
00380 mOptVal[idx] = tmp;
00381 i++;
00382 }
00383 else
00384 {
00385 mOptVal[idx] = "1";
00386 }
00387 }
00388 else
00389 {
00390 if (s[0] == '"')
00391 s = s.substr(1, s.size()-2);
00392 mArg.push_back(s);
00393 }
00394 i++;
00395 }
00396
00397 if (mArg.size() < nrReqArgs)
00398 return "Need more arguments";
00399
00400 return String();
00401 }
00402
00403 void
00404 ShowUsage(char* progName, String usageStr)
00405 {
00406 std::cout << std::endl;
00407 std::cout << "Usage : " << progName << " " << usageStr << std::endl;
00408 std::cout << std::endl;
00409 std::cout << " Options:" << std::endl;
00410 std::cout << " -h --help" << std::endl;
00411 std::cout << " --version" << std::endl;
00412 for (int i=0 ; i<NrOpt() ; i++)
00413 {
00414 if (mOptParName[i] == "read from ini file")
00415 continue;
00416 if (mOptHideUsage[i])
00417 continue;
00418 if (mOptNameS[i])
00419 std::cout << " -" << mOptNameS[i];
00420 else
00421 std::cout << " ";
00422 std::cout << " --" << mOptNameL[i] << " " << mOptParName[i];
00423 if (! mOptDefVal[i].empty())
00424 std::cout << " [default: " << mOptDefVal[i] <<"]";
00425 if (! mOptAlt[i].empty())
00426 std::cout << " [" << mOptParName[i] << " in " << mOptAlt[i]
00427 << "]";
00428 std::cout << std::endl;
00429 }
00430 }
00431
00432 void
00433 ReadIniFile(String fileName)
00434 {
00435 std::vector<String> lines;
00436 std::back_insert_iterator<std::vector<String> > bi(lines);
00437 FileReadString(bi, fileName, true, false);
00438 for (int i=0 ; i<lines.size() ; i++)
00439 {
00440 String& s = lines[i];
00441 if (s[0] == '#')
00442 continue;
00443 String::size_type pos = 0;
00444 while (s[pos] == ' ')
00445 pos++;
00446 String::size_type end = s.find(' ', pos);
00447 String name = s.substr(pos, end - pos);
00448 if (end == String::npos)
00449 continue;
00450
00451 pos = end;
00452 while (s[pos] == ' ')
00453 pos++;
00454 char delim = (s[pos] == '"') ? '"' : ' ';
00455 if (delim == '"')
00456 pos++;
00457 end = s.find(delim, pos);
00458 String value = s.substr(pos, end - pos);
00459
00460 int index = GetOptIdx(name);
00461 if (index == -1)
00462 AddOption(0, name.c_str(), "read from ini file", value.c_str());
00463 else
00464 mOptVal[index] = value;
00465 }
00466 }
00467
00468 void
00469 ConfigureLogSystem()
00470 {
00471 LogSystem::LogSystemConfig logConfig;
00472 logConfig.mLogProperties = GetString("logProperties");
00473 logConfig.mLogLayout = GetString("logLayout");
00474 logConfig.mLogFile = GetString("logFile");
00475 logConfig.mLogFlushOutput = GetBool("logFlushOutput");
00476 logConfig.mLogLevel = GetInt("logLevel");
00477 logConfig.mDebug = GetBool("debug");
00478 logConfig.mDebugCat = StringReplaceAll(GetString("debugCat"), ":", ";", false);
00479 logConfig.mNoErrorLog = GetBool("noErrorLog");
00480 logConfig.mJobErrorLog = GetString("jobErrorLog");
00481 logConfig.mExitOnError = GetBool("exitOnErrorLogged");
00482 LogSystem::GetInstance().Configure(logConfig);
00483 }
00484
00485 std::vector<char> mOptNameS;
00486 std::vector<String> mOptNameL;
00487 std::vector<String> mOptDefVal;
00488
00489
00490 std::vector<String> mOptVal;
00491 std::vector<String> mOptParName;
00492 std::vector<String> mOptAlt;
00493 std::vector<bool> mOptHideUsage;
00494 std::vector<String> mArg;
00495
00496 ILOG_VAR_DECL;
00497 };
00498
00499 ILOG_VAR_INIT(CmdOptions, Impala);
00500
00501 }
00502
00503 #endif