aboutsummaryrefslogtreecommitdiffstats
path: root/meowpp/Usage.h
diff options
context:
space:
mode:
Diffstat (limited to 'meowpp/Usage.h')
-rw-r--r--meowpp/Usage.h478
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__