gctl/lib/utility/stream_t.h
2024-09-10 15:45:07 +08:00

322 lines
9.6 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/********************************************************
* ██████╗ ██████╗████████╗██╗
* ██╔════╝ ██╔════╝╚══██╔══╝██║
* ██║ ███╗██║ ██║ ██║
* ██║ ██║██║ ██║ ██║
* ╚██████╔╝╚██████╗ ██║ ███████╗
* ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝
* 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