/******************************************************** * ██████╗ ██████╗████████╗██╗ * ██╔════╝ ██╔════╝╚══██╔══╝██║ * ██║ ███╗██║ ██║ ██║ * ██║ ██║██║ ██║ ██║ * ╚██████╔╝╚██████╗ ██║ ███████╗ * ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝ * Geophysical Computational Tools & Library (GCTL) * * Copyright (c) 2023 Yi Zhang (yizhang-geo@zju.edu.cn) * * GCTL is distributed under a dual licensing scheme. You can redistribute * it and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either version 2 * of the License, or (at your option) any later version. You should have * received a copy of the GNU Lesser General Public License along with this * program. If not, see . * * If the terms and conditions of the LGPL v.2. would prevent you from using * the GCTL, please consider the option to obtain a commercial license for a * fee. These licenses are offered by the GCTL's original author. As a rule, * licenses are provided "as-is", unlimited in time for a one time fee. Please * send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget * to include some description of your company and the realm of its activities. * Also add information on how to contact you by electronic and paper mail. ******************************************************/ #ifndef _GCTL_GETOPTION_H #define _GCTL_GETOPTION_H // library's head file #include "../core/array.h" #include "stream.h" // system's head file #include "vector" #include "string" #include "iostream" #include "fstream" namespace gctl { /** * @brief Gets the key and value string from an input string. * * Format of the input string: * * @param[in] in_str The input string * @param[in] separator The separator string * @param key The key * @param value The value */ void parse_key_value(std::string in_str, std::string separator, std::string &key, std::string &value); struct text_option { int group; bool mandatory; std::string name, value; text_option(); void set(std::string n, bool m); void set_group(int g); }; /** * @brief Read options from a file and parse arguments. * */ class getoption { public: /** * @brief Construct a new getoption object. * */ getoption(){} /** * @brief Destroys the object. */ virtual ~getoption(); /** * @brief clear class objects */ void clear(); /** * @brief Initialize an option. * * @param opt_name Option name. * @param manda Wether the option is mandatory or not. * @param gp Group of the option. */ void add_option(std::string opt_name, bool manda = false, int gp = -1); /** * @brief Initialize the option list * * @param opt_name Option names * @param opt_manda Wether the options are mandatory or not. */ void add_options(std::initializer_list opt_name, std::initializer_list opt_manda); /** * @brief Set the options' group * * @param gp group * @param opt_name Option names */ void set_group(int gp, std::initializer_list opt_name); /** * @brief reading options and arguments from a file. * * @warning Any blank characters before and after an option or an argument * will be removed before it is saved. If there is more than one argument that * is recorded for an option, the arguments will be saved as a single string * separated by the connecting symbol. The default is comma. * * File format: * 1. Any line starts with the annotate symbol (default is #) will be skipped. * 2. Empty lines will be skipped. * 3. option-name option-value * * @param[in] filename File name of the options. * @param[in] separator The symbol that separates option and argument * @param[in] connector The symbol that connect multiple found arguments * @param[in] annotate The symbol which indicates a comment line. * * @return 0 for success and -1 for failure. */ void read_options(std::string filename, std::string separator = "=", std::string conntector = ",", char annotate = '#'); /** * @brief reading options and arguments from a string vector. * * @warning Any blank characters before and after an option or an argument * will be removed before it is saved. If there is more than one argument that * is recorded for an option, the arguments will be saved as a single string * separated by the connecting symbol. The default is comma. * * File format: * 1. Any line starts with the annotate symbol (default is #) will be skipped. * 2. Empty lines will be skipped. * 3. option-name option-value * * @param[in] str_vec Input string vector * @param[in] separator The symbol that separates option and argument * @param[in] connector The symbol that connect multiple found arguments * @param[in] annotate The symbol which indicates a comment line. * * @return 0 for success and -1 for failure. */ void read_options(const std::vector &str_vec, std::string separator = "=", std::string conntector = ",", char annotate = '#'); /** * @brief reading options and arguments from a string array. * * @warning Any blank characters before and after an option or an argument * will be removed before it is saved. If there is more than one argument that * is recorded for an option, the arguments will be saved as a single string * separated by the connecting symbol. The default is comma. * * File format: * 1. Any line starts with the annotate symbol (default is #) will be skipped. * 2. Empty lines will be skipped. * 3. option-name option-value * * @param[in] str_vec Input string vector * @param[in] separator The symbol that separates option and argument * @param[in] connector The symbol that connect multiple found arguments * @param[in] annotate The symbol which indicates a comment line. * * @return 0 for success and -1 for failure. */ void read_options(const gctl::array &str_vec, std::string separator = "=", std::string conntector = ",", char annotate = '#'); /** * @brief Check if all mandatory options are recorded. If an option is part of a group. It will not be checked here. * */ void check_mandatory(); /** * @brief Check if at least one option of the group is recorded * * @param gp */ void check_group(int gp); /** * @brief Check all groups * */ void check_groups(); /** * @brief display all recorded options and arguments. */ void show_options(std::ostream& outstream = std::clog, bool show_all = false); /** * @brief Check if an input key has value * * @param[in] key Key value of an option. Multilpe key values must be separated by a delimiter (default is '|'). e.g. 'Model|model|Model-file|model-file' declares four duplicated keys for a single option value. * @param[in] delimiter Delimiter of multiple key values. */ bool has_value(std::string key, char delimiter = '|'); /** * @brief Gets the argument according to an input key * * @warning An error string will be thrown out if the argument is not recorded. * * @param[in] key Key value of an option. Multilpe key values must be separated by a delimiter (default is '|'). e.g. 'Model|model|Model-file|model-file' declares four duplicated keys for a single option value. * @param[in] delimiter Delimiter of multiple key values. * * @return The found argument. */ std::string get_value(std::string key, char delimiter = '|'); /** * @brief Gets the argument according to an input key * * @warning An error string will be thrown out if the argument is not recorded. * * @param[in] key Key value of an option. Multilpe key values must be separated by a delimiter (default is '|'). e.g. 'Model|model|Model-file|model-file' declares four duplicated keys for a single option value. * @param[in] delimiter Delimiter of multiple key values. * * @return The found argument. */ template T get_value_t(std::string key, char delimiter = '|', char sep = ' ') { // 分割待匹配的字符串 std::vector tmp_keys; parse_string_to_vector(key, delimiter, tmp_keys); T out_val; for (size_t o = 0; o < options_.size(); o++) { for (size_t i = 0; i < tmp_keys.size(); i++) { if (tmp_keys[i] == options_[o].name) { str2type(options_[o].value, out_val, sep); return out_val; } } } throw runtime_error("[gctl::getoption::get_value] Option not found for: " + key); return out_val; } protected: std::vector options_; std::vector group_idx_; }; } #endif //_GCTL_GETOPTION_H