gctl/lib/utility/stream_t.h

322 lines
9.6 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_STREAM_TEMPLATE_H
#define _GCTL_STREAM_TEMPLATE_H
#include "string"
#include "sstream"
#include "../core/exceptions.h"
#include "../core/vector_t.h"
/**
* terminal control symbols
*/
#define GCTL_BOLD "\033[1m" ///< 设置终端字体与颜色为粗体
#define GCTL_BOLDRED "\033[1m\033[31m" ///< 设置终端字体与颜色为粗体红色
#define GCTL_BOLDGREEN "\033[1m\033[32m" ///< 设置终端字体与颜色为粗体绿色
#define GCTL_BOLDBLUE "\033[1m\033[34m" ///< 设置终端字体与颜色为粗体蓝色
#define GCTL_BOLDYELLOW "\033[1m\033[33m" ///< 设置后续字符字体为黄色加粗
#define GCTL_UNDERLINE "\033[1m\033[4m" ///< 设置终端字体为下划线
#define GCTL_RESET "\033[0m" ///< 重置字体与颜色设定
#define GCTL_CLEARLINE "\033[K" ///< 清空终端当前行
#define GCTL_CLEARALL "\033[2J" ///< 清空终端窗口
#define GCTL_MOVEUP(os, x) do {os << "\033[" << x << "A";} while (0); ///< 终端光标上移x行
#define GCTL_MOVEDOWN(os, x) do {os << "\033[" << x << "B";} while (0); ///< 终端光标下移x行
#define GCTL_MOVERIGHT(os, x) do {os << "\033[" << x << "C";} while (0); ///< 终端光标右移x列
#define GCTL_MOVELEFT(os, x) do {os << "\033[" << x << "D";} while (0); ///< 终端光标左移x列
#define GCTL_MOVETO(os, r, c) do {os << "\033[" << c << ";" << r << "H";} while (0); ///< 终端光标移动至r行c列位置
namespace gctl
{
template <typename ObjValType>
void type2ss(ObjValType in_val, std::stringstream &out_ss)
{
out_ss.clear();
out_ss << in_val;
return;
}
template <typename OutValType>
int str2type(std::string in_str, OutValType &out_val, char sep = ' ')
{
std::stringstream tmp_ss;
if (sep != ' ')
{
std::string new_str = in_str;
std::string old_sep;
old_sep = sep;
std::string new_sep = " ";
for(std::string::size_type pos(0); pos != std::string::npos; pos += new_sep.length())
{
if((pos = new_str.find(old_sep, pos)) != std::string::npos)
{
new_str.replace(pos,old_sep.length(), new_sep);
}
else break;
}
tmp_ss.clear();
tmp_ss.str(new_str);
}
else
{
tmp_ss.clear();
tmp_ss.str(in_str);
}
tmp_ss >> out_val;
if (tmp_ss.fail())
{
return -1;
}
return 0;
}
template <typename OutValType>
void str2type_vector(const std::vector<std::string> &in_vec,
std::vector<OutValType> &out_data)
{
if (!out_data.empty()) out_data.clear();
out_data.resize(in_vec.size());
for (int i = 0; i < out_data.size(); i++)
{
if (str2type(in_vec[i], out_data[i]))
{
throw gctl::runtime_error("[gctl::str2type_vector] Failed to parse: " + in_vec[i]);
}
}
return;
}
template <typename ValueType>
void type2str_vector(const std::vector<ValueType> &in_vec,
std::vector<std::string> &out_vec)
{
if (!out_vec.empty()) out_vec.clear();
out_vec.resize(in_vec.size());
for (size_t i = 0; i < in_vec.size(); i++)
{
out_vec[i] = std::to_string(in_vec[i]);
}
return;
}
template <typename ValueType>
void str2type_vector2d(const std::vector<std::vector<std::string>> &vec2d,
std::string order_str, std::vector<ValueType> &vec)
{
int idx;
std::string tmp_str;
std::stringstream tmp_ss(order_str);
std::getline(tmp_ss, tmp_str, ',');
tmp_ss.clear();
tmp_ss.str(tmp_str);
tmp_ss >> idx;
if (idx >= vec2d.size()) throw std::runtime_error("[gctl::str2type_vector2d] Invalid index.");
order_str = order_str.substr(order_str.find_first_of(',') + 1);
str2type_vector(vec2d[idx], vec);
return;
}
template <typename ValueType, typename... Args>
void str2type_vector2d(const std::vector<std::vector<std::string>> &vec2d,
std::string order_str, std::vector<ValueType> &vec, Args&... rest)
{
int idx;
std::string tmp_str;
std::stringstream tmp_ss(order_str);
std::getline(tmp_ss, tmp_str, ',');
tmp_ss.clear();
tmp_ss.str(tmp_str);
tmp_ss >> idx;
if (idx >= vec2d.size()) throw std::runtime_error("[gctl::str2type_vector2d] Invalid index.");
order_str = order_str.substr(order_str.find_first_of(',') + 1);
str2type_vector(vec2d[idx], vec);
str2type_vector2d(vec2d, order_str, rest...);
return;
}
template <typename ValueType>
void type2str_vector2d(std::vector<std::vector<ValueType>> &vec2d,
const std::vector<std::string> &vec)
{
std::vector<std::string> str_vec;
type2str_vector(vec, str_vec);
vec2d.push_back(str_vec);
return;
}
template <typename ValueType, typename... Args>
void type2str_vector2d(std::vector<std::vector<ValueType>> &vec2d,
const std::vector<std::string> &vec, Args&... rest)
{
std::vector<std::string> str_vec;
type2str_vector(vec, str_vec);
vec2d.push_back(str_vec);
type2str_vector2d(vec2d, rest...);
return;
}
/**
* @brief Parse a string argument into an element array
*
* @param[in] val_str The input value string
* @param out_vec The output array
* @param[in] separator The separator
*
* @tparam ValueType Runtime value type
*
* @return 0 for success, -1 for failure
*/
template <typename ValueType>
int parse_string_to_vector(std::string val_str, char separator, std::vector<ValueType> &out_vec)
{
val_str.erase(0, val_str.find_first_not_of(" \t"));
val_str.erase(val_str.find_last_not_of(" \t") + 1);
int pos;
bool bk = false;
ValueType val;
std::string l_str;
while (1)
{
pos = val_str.find(separator);
if (pos == val_str.npos)
{
l_str = val_str;
bk = true;
}
else
{
l_str = val_str.substr(0, pos);
val_str = val_str.substr(pos+1, val_str.length());
val_str.erase(0, val_str.find_first_not_of(" \t"));
}
// 如果输出也是字符串 就直接赋值即可避免l_str中含有空格会出现bug
if constexpr (std::is_same<ValueType, std::string>::value) val = l_str;
else str2type(l_str, val);
out_vec.push_back(val);
if (bk) break;
}
return 0;
}
/**
* @brief Parse a string argument into separated elements.
*
* @param[in] val_str The input value string
* @param[in] separator The separator
* @param[in] throw_err Throw out errors
* @param[in] fst_val The output values returned by quote
*
* @tparam ValueType Runtime value type
*
* @return Number of parsed strings
*/
template <typename ValueType>
int parse_string_to_value(std::string val_str, char separator, bool throw_err, ValueType &fst_val)
{
std::string tmp_str;
std::stringstream tmp_ss(val_str);
std::getline(tmp_ss, tmp_str, separator);
tmp_ss.clear();
tmp_ss.str(tmp_str);
tmp_ss >> fst_val;
if (throw_err && tmp_ss.fail())
{
throw std::runtime_error("Fail to parse the input string. From gctl::parse_string_to_value(...)");
}
else if (tmp_ss.fail())
{
return 0;
}
return 1;
}
/**
* @brief Parse a string argument into separated elements.
*
* @param[in] val_str The input value string
* @param[in] separator The separator
* @param[in] throw_err Throw out errors
* @param[in] fst_val The output values returned by quote
*
* @tparam ValueType Runtime value type
* @tparam Args Runtime value types of the rest arguments
*
* @return Number of parsed strings
*/
template <typename ValueType, typename... Args>
int parse_string_to_value(std::string val_str, char separator, bool throw_err, ValueType &fst_val, Args&... rest)
{
std::string tmp_str;
std::stringstream tmp_ss(val_str);
std::getline(tmp_ss, tmp_str, separator);
tmp_ss.clear();
tmp_ss.str(tmp_str);
tmp_ss >> fst_val;
if (throw_err && tmp_ss.fail())
{
throw std::runtime_error("Fail to parse the input string. From gctl::parse_string_to_value(...)");
}
else if (tmp_ss.fail())
{
return 0;
}
int position = val_str.find_first_of(separator);
if (position == std::string::npos) tmp_str = "";
else tmp_str = val_str.substr(position+1, val_str.length());
return parse_string_to_value(tmp_str, separator, throw_err, rest...) + 1;
}
}
#endif // _GCTL_STREAM_TEMPLATE_H