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