diff options
Diffstat (limited to 'meowpp/Usage.h')
-rw-r--r-- | meowpp/Usage.h | 478 |
1 files changed, 0 insertions, 478 deletions
diff --git a/meowpp/Usage.h b/meowpp/Usage.h deleted file mode 100644 index d2becef..0000000 --- a/meowpp/Usage.h +++ /dev/null @@ -1,478 +0,0 @@ -#ifndef MEOW_USAGE_H__ -#define MEOW_USAGE_H__ - -#include "utility.h" - -#include <cstdlib> - -#include <algorithm> -#include <string> -#include <vector> -#include <map> - -namespace meow { -/*! - * @brief 管理參數設置, 自訂usage document, 分析argc, argv - * - * \b Usage 是用來分析argc, argv和輸出usage document的class. \n - * argc, argv的部份, 有以下規則 - * - \b -c 其中 \a c 可以代換成一個字符, 這種選像可能是 \b 有設置 或 \b 沒設置 - * - \b -c \a value 附加一個 \a value , 這種選項可以是 \b 選擇性 或 - * \b 必要的 , 另外可以給定value的預設值以及哪些value是可接受 - * - \a value 其他, 一律視為 \b process \b arguments - * - * @author cathook - */ -class Usage { -private: - typedef std::string String; - typedef std::vector<String> Strings; - //! 存 (value, description) - class Value { - private: - String value_; - String description_; - public: - Value() { } - Value(String const& value, String const& description) { - value_ = value; - description_ = stringReplace(description, "<value>", value); - } - String usage() const { - return stringPrintf("%8s%s : %s\n", - " ", value_.c_str(), description_.c_str()); - } - String value() const { - return value_; - } - bool operator==(Value const& b) const { - return (value_ == b.value_); - } - }; - typedef std::vector<Value> Values; - //! 存 option, 其中可能有value可能沒有 - class Option { - private: - Strings values_; - Values values_accept_; - String value_default_; - String value_type_; - String description_; - bool has_value_; - bool has_setup_; - bool must_setup_; - public: - Option() { - } - Option(String const& description) { - has_setup_ = false; - has_value_ = false; - description_ = description; - must_setup_ = false; - } - Option(String const& description, - String const& type, - String const& default_value, - bool must) { - has_setup_ = false; - has_value_ = true; - description_ = description; - value_type_ = type; - value_default_ = default_value; - must_setup_ = must; - } - Strings const& values() const { - return values_; - } - String value(size_t index) const { - if (!has_value_) return ""; - if (!has_setup_ || index >= values_.size()) return value_default_; - return values_[index]; - } - ssize_t valueAdd(String const& value) { - if (!has_value_) { - has_setup_ = true; - return 0; - } - if (values_accept_.size() > 0 && - std::find(values_accept_.begin(), values_accept_.end(), - Value(value, "")) == values_accept_.end()) - return -1; - values_.push_back(value); - has_setup_ = true; - return values_.size() - 1; - } - bool valueAcceptAdd(String const& value, String const& description) { - if (!has_value_) return false; - if (std::find(values_accept_.begin(), values_accept_.end(), - Value(value, "")) == values_accept_.end()) { - values_accept_.push_back(Value(value, description)); - } - return true; - } - bool valueAcceptChk(String const& value) { - if (!has_value_) return false; - return (values_accept_.empty() || - std::find(values_accept_.begin(), values_accept_.end(), - Value(value, "")) != values_accept_.end()); - } - bool hasSetup() const{ return has_setup_; } - bool hasValue() const{ return has_value_; } - bool chkSetup() const{ return !(must_setup_ && !has_setup_); } - - String usage(String opt, bool detail) const { - String ret(stringPrintf("%s%s ", (opt.size()>1 ? "--":"-"), opt.c_str())); - if (!detail) { - if (has_value_) ret += value_type_; - if (!must_setup_) ret = "[" + ret + "]"; - } - else { - if (has_value_) { - ret += value_type_ + " "; - String default_string(""); - if (value_default_ != "") - default_string = "defalut='" + value_default_ + "'"; - String optional_string(""); - if (!must_setup_) - optional_string = "optional"; - String tmp; - if (default_string.size() + optional_string.size() > 0) { - if (default_string.size() > 0 && optional_string.size() > 0) { - ret += "(" + optional_string + ", " + default_string + ")"; - } - else { - ret += "(" + optional_string + default_string + ")"; - } - } - } - ret += "\n"; - String accept_string; - for (size_t i = 0; i < values_accept_.size(); i++) { - if (i > 0) - accept_string += (i + 1 < values_accept_.size() ? ", " : " or "); - accept_string += "'" + values_accept_[i].value() + "'"; - } - if (accept_string.size() == 0) accept_string = "... (anything)"; - ret += " " + stringReplace(stringReplace(description_, - "<type>", - value_type_), - "<values>", - accept_string) + "\n"; - for (size_t i = 0; i < values_accept_.size(); i++) { - ret += values_accept_[i].usage(); - } - ret += "\n"; - } - return ret; - } - }; - typedef std::map<String, Option> Options; - typedef Options:: iterator OptionsIterator; - typedef Options::const_iterator OptionsIteratorK; - - String name_; - Options options_; - Strings usage_begin_; - Strings usage_end_; - Strings proc_arguments_; -public: - /*! - * @brief constructor - * - * 所有說明文字中 \a \<name\> 都會被代換成空字串 - */ - Usage() { - } - - /*! - * @brief constructor - * - * 所有說明文字中 \a "<name>" 都會被代換成空字串 \b name - */ - Usage(String const& name) { - name_ = name; - } - - - /*! - * @brief constructor - * - * 將另一個usage原封不動的複製過來 - */ - Usage(Usage const& usage) { - name_ = usage.name_; - options_ = usage.options_; - usage_begin_ = usage.usage_begin_; - usage_end_ = usage.usage_end_; - proc_arguments_ = usage.proc_arguments_; - } - - /*! - * @brief 將另一個usage的設置匯入 - * - * @param [in] usage 另一個usage - * @return \c true/false 表示 \b 是否成功 - */ - bool import(Usage const& usage) { - for (OptionsIteratorK - it = usage.options_.begin(); it != usage.options_.end(); ++it) { - if (options_.find(it->first) != options_.end()) - return false; - } - for (OptionsIteratorK - it = usage.options_.begin(); it != usage.options_.end(); ++it) { - options_.insert(std::pair<String, Option>(it->first, it->second)); - } - for (size_t i = 0; i < usage.usage_begin_.size(); ++i) - usage_begin_.push_back(usage.usage_begin_[i]); - for (size_t i = 0; i < usage.usage_end_.size(); ++i) - usage_end_.push_back(usage.usage_end_[i]); - return true; - } - - /*! - * @brief 將另一個usage的選項設置加進來 - * - * @param [in] usage 另一個usage - * @return \c true/false 表 \b 是否成功 - */ - bool update(Usage const& usage) { - for (OptionsIteratorK - it = usage.options_.begin(); it != usage.options_.end(); ++it) { - OptionsIterator my = options_.find(it->first); - if (my == options_.end()) continue; - for (size_t i = 0, I = it->second.values().size(); i < I; ++i) { - my->second.valueAdd(it->second.value(i)); - } - } - return true; - } - - /*! - * @brief 新增一個沒有額外選項的選項 - * - * @param [in] opt 指定字符 - * @param [in] des 即description, 用來解釋這個選項的意義用的 - * @return \c true/false 表 \b 是否成功 - */ - bool optionAdd(String opt, String const& des) { - if (options_.find(opt) != options_.end()) return false; - options_.insert(std::pair<String, Option>(opt, Option(des))); - return true; - } - - /*! - * @brief 新增一個有額外選項的選項 - * - * @param [in] opt 指定字符 - * @param [in] des 即description, 用來解釋這個選項的意義用的 - * @param [in] val_type 表示額外選項的型態, 寫在USAGE裡面給人看用的 - * @param [in] val_default 預設值, 若為空字串則當作沒有預設值 - * @param [in] must 表示是否一定要設定 - * @return \c true/false 表 \b 是否成功 - */ - bool optionAdd(String opt, String const& des, - String const& val_type, - String const& val_default, - bool must) { - if (options_.find(opt) != options_.end()) return false; - options_.insert(std::pair<String, Option>( - opt, Option(des, val_type, val_default, must))); - return true; - } - - /*! - * @brief 針對-(opt)新增一個可接受的額外選項 - * - * @param [in] opt 指定字符 - * @param [in] val 額外選項 - * @param [in] des 關於此額外選項的說明 - * @return \c true/false 表 \b 是否成功 - */ - bool optionValueAcceptAdd(String opt, String const& val, String const& des) { - OptionsIterator o = options_.find(opt); - if (o == options_.end()) return false; - return o->second.valueAcceptAdd(val, des); - } - - /*! - * @brief 回傳是否有設定此選項 - * - * @param [in] opt 指定字符 - * @return \c true/false 表 \b 是否有設定此選項 - */ - bool hasOptionSetup(String opt) const { - OptionsIteratorK o = options_.find(opt); - return (o != options_.end() && o->second.hasSetup()); - } - - /*! - * @brief 回傳參數 \b -(opt) 被設置幾次 - * - * @param [in] opt 指定字符 - * @return 回傳次數 - */ - size_t optionValuesSize(String opt) const { - OptionsIteratorK o = options_.find(opt); - if (o == options_.end()) return 0; - return o->second.values().size(); - } - - /*! - * @brief 回傳參數 \b -(opt) 的第 \b index 個額外選項 - * - * @param [in] opt 指定字符 - * @param [in] index 第幾個 - * @return 回傳參數 \b -(opt) 的第 \b index 個額外選項 - */ - String optionValue(String opt, size_t index) const { - OptionsIteratorK o = options_.find(opt); - if (o == options_.end()) return String(); - return o->second.value(index); - } - - /*! - * @brief 取得有幾個process arguments - * - * @return 有幾個process arguments - */ - size_t procArgsSize() const { - return proc_arguments_.size(); - } - - /*! - * @brief 取得第i個process argument - * - * @param [in] index 第幾個 - * @return 回傳第 \a index 個 \b process \b argument - */ - String procArg(size_t index) const { - if (index >= proc_arguments_.size()) { - return String(); - } - return proc_arguments_[index]; - } - - /*! - * @brief 取得process arguments array - * - * @return 一個 \c std::vector , 包含所有 \b Process \b arguments - */ - Strings const& procArgs() const{ - return proc_arguments_; - } - - /*! - * @brief 新增一段usage document於每個選項逐條說明之前 - * - * @param [in] des 要新增的usage document - */ - void usageBeginAdd(String const& des) { - usage_begin_.push_back(stringReplace(des, "<name>", name_)); - } - - /*! - * @brief 新增一段usage document於每個選項逐條說明之後 - * - * @param [in] des 要新增的usage document - */ - void usageEndAdd(String const& des) { - usage_end_.push_back(stringReplace(des, "<name>", name_)); - } - - /*! - * @brief 回傳usage string - * - * @return \b usage \b string - */ - String usage() const { - Usage::String out = stringPrintf("USAGE\n %s", name_.c_str()); - for (OptionsIteratorK - it = options_.begin(); it != options_.end(); ++it) - out += " " + it->second.usage(it->first, false); - out += "\n\nDESCRIPTION\n"; - for (size_t i = 0; i < usage_begin_.size(); ++i) { - out += " " + usage_begin_[i] + "\n\n"; - } - for (OptionsIteratorK - it = options_.begin(); it != options_.end(); ++it) { - out += it->second.usage(it->first, true); - } - for (size_t i = 0; i < usage_end_.size(); ++i) { - out += " " + usage_end_[i] + "\n\n"; - } - return out; - } - - /*! - * @brief 給定argc, argv, 將各參數設置 - * @param [in] argc,argv - * @param [out] errmsg 將錯誤訊息寫到這裡 - * (若給定NULL pointer, 則會把錯誤訊息忽略) - * @return \c true/false \b 成功與否 (否的話代表有錯誤的設定值在其中) - */ - bool arguments(int argc, char** argv, String* errmsg) { - String zzz; - String& err = (errmsg == NULL ? zzz : *errmsg); - for (int i = 0; i < argc; ++i) { - if (argv[i][0] == '-') { - String opt; - if (argv[i][1] == '-') { // long option - if (argv[i][2] == '\0' || argv[i][3] == '\0') { - err = stringPrintf("Invalid option '%s'", argv[i]); - return false; - } - opt = String(argv[i] + 2); - } - else { // short option - if (argv[i][1] == '\0' || argv[i][2] != '\0') { - err = stringPrintf("Invalid option '%s'", argv[i]); - return false; - } - opt = String(argv[i] + 1); - } - OptionsIterator o = options_.find(opt); - if (o == options_.end()) { - err = stringPrintf("Unknown option '%s'", argv[i]); - return false; - } - if (o->second.hasValue()) { - if (i + 1 >= argc) { - err = stringPrintf("Option '%s' need a value", argv[i]); - return false; - } - if (o->second.valueAdd(argv[i + 1]) < 0) { - err = stringPrintf("Invalid value '%s' of options '%s'", - argv[i + 1], argv[i]); - return false; - } - ++i; - } - else { - o->second.valueAdd(""); - } - } - else { - if (i == 0) { - // TODO: remember who am I - } - else { - proc_arguments_.push_back(String(argv[i] + (argv[i][0]=='\\' ? 1:0))); - } - } - } - for (OptionsIteratorK it = options_.begin(); it != options_.end(); ++it) { - if (it->second.chkSetup() == false) { - err += stringPrintf("No specify argument to '%s%s'\n", - (it->first.size() > 1 ? "--" : "-"), - it->first.c_str()); - return false; - } - } - return true; - } -}; - -} // meow - -#endif // MEOW_USAGE_H__ |