gctl/lib/utility/get_option.h

267 lines
9.2 KiB
C
Raw Normal View History

2024-09-10 15:45:07 +08:00
/********************************************************
*
*
*
*
*
*
* 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 <http://www.gnu.org/licenses/>.
*
* 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: <key><separator><value>
*
* @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<std::string> opt_name, std::initializer_list<bool> opt_manda);
/**
* @brief Set the options' group
*
* @param gp group
* @param opt_name Option names
*/
void set_group(int gp, std::initializer_list<std::string> 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 <separator> 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 <separator> 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<std::string> &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 <separator> 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<std::string> &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 <typename T>
T get_value_t(std::string key, char delimiter = '|', char sep = ' ')
{
// 分割待匹配的字符串
std::vector<std::string> 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<text_option> options_;
std::vector<int> group_idx_;
};
}
#endif //_GCTL_GETOPTION_H