MLPACK
1.0.4
|
00001 00024 #ifndef __MLPACK_CORE_UTIL_CLI_HPP 00025 #define __MLPACK_CORE_UTIL_CLI_HPP 00026 00027 #include <list> 00028 #include <iostream> 00029 #include <map> 00030 #include <string> 00031 00032 #include <boost/any.hpp> 00033 #include <boost/program_options.hpp> 00034 00035 #include "timers.hpp" 00036 #include "cli_deleter.hpp" // To make sure we can delete the singleton. 00037 00053 #define PROGRAM_INFO(NAME, DESC) static mlpack::util::ProgramDoc \ 00054 io_programdoc_dummy_object = mlpack::util::ProgramDoc(NAME, DESC); 00055 00073 #define PARAM_FLAG(ID, DESC, ALIAS) \ 00074 PARAM_FLAG_INTERNAL(ID, DESC, ALIAS); 00075 00097 #define PARAM_INT(ID, DESC, ALIAS, DEF) \ 00098 PARAM(int, ID, DESC, ALIAS, DEF, false) 00099 00121 #define PARAM_FLOAT(ID, DESC, ALIAS, DEF) \ 00122 PARAM(float, ID, DESC, ALIAS, DEF, false) 00123 00145 #define PARAM_DOUBLE(ID, DESC, ALIAS, DEF) \ 00146 PARAM(double, ID, DESC, ALIAS, DEF, false) 00147 00170 #define PARAM_STRING(ID, DESC, ALIAS, DEF) \ 00171 PARAM(std::string, ID, DESC, ALIAS, DEF, false) 00172 00194 #define PARAM_VECTOR(T, ID, DESC, ALIAS) \ 00195 PARAM(std::vector<T>, ID, DESC, ALIAS, std::vector<T>(), false) 00196 00197 // A required flag doesn't make sense and isn't given here. 00198 00219 #define PARAM_INT_REQ(ID, DESC, ALIAS) PARAM(int, ID, DESC, ALIAS, 0, true) 00220 00243 #define PARAM_FLOAT_REQ(ID, DESC, ALIAS) PARAM(float, ID, DESC, ALIAS, 0.0f, \ 00244 true) 00245 00266 #define PARAM_DOUBLE_REQ(ID, DESC, ALIAS) PARAM(double, ID, DESC, ALIAS, \ 00267 0.0f, true) 00268 00289 #define PARAM_STRING_REQ(ID, DESC, ALIAS) PARAM(std::string, ID, DESC, \ 00290 ALIAS, "", true); 00291 00312 #define PARAM_VECTOR_REQ(T, ID, DESC, ALIAS) PARAM(std::vector<T>, ID, DESC, \ 00313 ALIAS, std::vector<T>(), true); 00314 00320 // These are ugly, but necessary utility functions we must use to generate a 00321 // unique identifier inside of the PARAM() module. 00322 #define JOIN(x, y) JOIN_AGAIN(x, y) 00323 #define JOIN_AGAIN(x, y) x ## y 00324 00340 #ifdef __COUNTER__ 00341 #define PARAM(T, ID, DESC, ALIAS, DEF, REQ) static mlpack::util::Option<T> \ 00342 JOIN(io_option_dummy_object_, __COUNTER__) \ 00343 (false, DEF, ID, DESC, ALIAS, REQ); 00344 00346 #define PARAM_FLAG_INTERNAL(ID, DESC, ALIAS) static \ 00347 mlpack::util::Option<bool> JOIN(__io_option_flag_object_, __COUNTER__) \ 00348 (ID, DESC, ALIAS); 00349 00351 #else 00352 // We have to do some really bizarre stuff since __COUNTER__ isn't defined. I 00353 // don't think we can absolutely guarantee success, but it should be "good 00354 // enough". We use the __LINE__ macro and the type of the parameter to try 00355 // and get a good guess at something unique. 00356 #define PARAM(T, ID, DESC, ALIAS, DEF, REQ) static mlpack::util::Option<T> \ 00357 JOIN(JOIN(io_option_dummy_object_, __LINE__), opt) (false, DEF, ID, \ 00358 DESC, ALIAS, REQ); 00359 00361 #define PARAM_FLAG_INTERNAL(ID, DESC, ALIAS) static \ 00362 mlpack::util::Option<bool> JOIN(__io_option_flag_object_, __LINE__) \ 00363 (ID, DESC, ALIAS); 00364 00366 #endif 00367 00371 #define TYPENAME(x) (std::string(typeid(x).name())) 00372 00373 namespace po = boost::program_options; 00374 00375 namespace mlpack { 00376 00377 namespace util { 00378 00379 // Externally defined in option.hpp, this class holds information about the 00380 // program being run. 00381 class ProgramDoc; 00382 00383 }; // namespace util 00384 00389 struct ParamData 00390 { 00392 std::string name; 00394 std::string desc; 00396 std::string tname; 00398 boost::any value; 00400 bool wasPassed; 00402 bool isFlag; 00403 }; 00404 00530 class CLI 00531 { 00532 public: 00544 static void Add(const std::string& path, 00545 const std::string& description, 00546 const std::string& alias = "", 00547 bool required = false); 00548 00560 template<class T> 00561 static void Add(const std::string& identifier, 00562 const std::string& description, 00563 const std::string& alias = "", 00564 bool required = false); 00565 00573 static void AddFlag(const std::string& identifier, 00574 const std::string& description, 00575 const std::string& alias = ""); 00576 00581 static void DefaultMessages(); 00582 00588 static void Destroy(); 00589 00596 template<typename T> 00597 static T& GetParam(const std::string& identifier); 00598 00605 static std::string GetDescription(const std::string& identifier); 00606 00619 static CLI& GetSingleton(); 00620 00626 static bool HasParam(const std::string& identifier); 00627 00635 static std::string HyphenateString(const std::string& str, int padding); 00636 00643 static void ParseCommandLine(int argc, char** argv); 00644 00650 static void RemoveDuplicateFlags(po::basic_parsed_options<char>& bpo); 00651 00657 static void ParseStream(std::istream& stream); 00658 00662 static void Print(); 00663 00667 static void PrintHelp(const std::string& param = ""); 00668 00676 static void RegisterProgramDoc(util::ProgramDoc* doc); 00677 00681 ~CLI(); 00682 00683 private: 00685 po::options_description desc; 00686 00688 po::variables_map vmap; 00689 00691 std::list<std::string> requiredOptions; 00692 00694 typedef std::map<std::string, ParamData> gmap_t; 00695 gmap_t globalValues; 00696 00698 typedef std::map<std::string, std::string> amap_t; 00699 amap_t aliasValues; 00700 00702 static CLI* singleton; 00703 00705 bool didParse; 00706 00708 Timers timer; 00709 00711 friend class Timer; 00712 00713 public: 00715 util::ProgramDoc *doc; 00716 00717 private: 00724 static void AddAlias(const std::string& alias, const std::string& original); 00725 00733 static std::string AliasReverseLookup(const std::string& value); 00734 00735 #ifdef _WIN32 00736 00741 void FileTimeToTimeVal(timeval* tv); 00742 #endif 00743 00749 static void RequiredOptions(); 00750 00758 static std::string SanitizeString(const std::string& str); 00759 00763 static void UpdateGmap(); 00764 00768 CLI(); 00769 00775 CLI(const std::string& optionsName); 00776 00778 CLI(const CLI& other); 00779 }; 00780 00781 }; // namespace mlpack 00782 00783 // Include the actual definitions of templated methods 00784 #include "cli_impl.hpp" 00785 00786 #endif