Files
dl_old/dl/base/dl_string.cpp
2026-04-08 18:43:02 +08:00

332 lines
5.8 KiB
C++

#include "dl_string.h"
#include <cstdarg>
#include <cstdio>
#include <wcwidth.h>
namespace dl
{
std::string to_string(std::error_code code)
{
return fmt::format("{}({}): {}",
code.category().name(),
code.value(),
CodeCvt::MultiByteToUtf8(code.message()));
}
std::string to_string(std::exception& e)
{
return CodeCvt::MultiByteToUtf8(e.what());
}
namespace String
{
std::string Sprintf(const char* format, ...)
{
va_list args;
int len;
va_start(args, format);
len = vsnprintf(nullptr, 0, format, args) + 1;
va_end(args);
std::string ret;
ret.resize(len);
va_start(args, format);
vsnprintf((char*)ret.data(), len, format, args);
va_end(args);
ret.pop_back();
return ret;
}
std::string CvtRelativePath(std::string path_cur, std::string_view path)
{
if (!IsRelativePath(path))
return std::string{ path };
//直到首位不是 “./”和“../”
size_t i = 0;
size_t size = path.size();
while ((i < size)
&& (path[i] == '.'))
{
if ((i + 1 < size)
&& (path[i + 1] == '/'))
{//当前目录
i += 2;
}
else if ((i + 2 < size)
&& (path[i + 1] == '.' && path[i + 2] == '/'))
{//向上目录
i += 3;
path_cur.pop_back();
Erase::TailFromLast(path_cur, '/');
}
else
break;
}
return path_cur + std::string(path.begin() + i, path.end());
}
bool GetPathAndRes(std::string_view path_root, std::string_view path_name, std::string& path_real, std::string& res_name, std::string_view name /*= ""*/)
{
if (IsRelativePath(path_name))
{
path_real = fmt::format("{}{}", path_root, path_name);
if (name.empty())
{
res_name = path_name;
if (Erase::TailFromLast(res_name, '.'))
res_name.pop_back();//去后缀
Every::Replace(res_name, '/', '.');//斜杠变.
}
else
res_name = name;
}
else
{
if (name.empty())
{
path_real = path_name;
res_name = "error";
log_err0("绝对路径加载,必须设定资源名字!");
return false;
}
else
{
path_real = path_name;
res_name = name;
}
}
return true;
}
std::string GetResName(std::string_view path_root, std::string_view path_name)
{
std::string name = std::string{ path_name };
auto iter_path = name.find(path_root);
if (iter_path != 0)
{
log_err0("路径错误:" + std::string{ name });
}
else
name.erase(0, path_root.size());
if (Erase::TailFromLast(name, '.'))//去后缀
{
name.pop_back();
}
if (Any::Equal(name, '\\'))
{
log_err("路径存在反斜杠:{}", name);
Every::Replace(name, '\\', '.');
}
Every::Replace(name, '/', '.');
return name;
}
std::vector<std::string> FormatString2(const Vector2<std::string>& arr)
{
auto W = arr.GetWidth();
auto H = arr.GetHeight();
using Index = decltype(W);
//每一列得到一个最大宽度
std::vector<Index> mul_col;
mul_col.resize(W);
for (Index j = 0; j < H; ++j)
{
for (Index i = 0; i < W; ++i)
{
if (arr[j][i].size() > mul_col[i])
mul_col[i] = (Index)arr[j][i].size();
}
}
//合并每行
std::vector<std::string> ret;
ret.resize(H);
for (Index i = 0; i < W; ++i)
{
std::string fmt = std::string("{:<") + std::to_string(mul_col[i] + 1) + "}";
for (Index j = 0; j < H; ++j)
{
ret[j] += fmt::vformat(fmt, fmt::make_format_args(arr[j][i]));
}
}
return ret;
}
std::vector<std::string> ParseCommand(std::string_view cmd)
{
std::vector<std::string> ret;
if (cmd.empty())
return ret;
size_t i = 0;
// 跳过起始空白
while (cmd[i] == ' ' || cmd[i] == '\t')
{
++i;
}
int mode = 0; // 空白模式、普通匹配、字符串模式
std::string temp;
while (cmd[i])
{
const char& ch = cmd[i];
if (mode == 0)
{
if (ch == '\"')
mode = 2;
else if (ch == ' ' || ch == '\t')
;
else
{
temp.push_back(ch);
mode = 1;
}
}
else if (mode == 1)
{
if (ch == ' ' || ch == '\t')
{
ret.push_back(temp);
temp.clear();
mode = 0;
}
else
temp.push_back(ch);
}
else if (mode == 2)
{
if (ch == '\"' && (i + 1 >= cmd.size() || cmd[i + 1] == ' ' || cmd[i + 1] == '\t'))
{
ret.push_back(temp);
temp.clear();
mode = 0;
}
else
{
temp.push_back(ch);
}
}
++i;
}
// 添加最后一个参数
if (!temp.empty())
ret.push_back(temp);
return ret;
}
std::string FillEndl(std::string_view str, char ch /*= ' '*/)
{
std::wstring wstr = CodeCvt::Utf8ToWideChar(str);
size_t max_w = 0;
size_t count = 0;
for (auto& iter : wstr)
{
if (iter != L'\n')
count += Wcwidth(iter);
else
{
if (count > max_w)
max_w = count;
count = 0;
}
}
std::wstring ret;
count = 0;
for (auto& iter : wstr)
{
if (iter != L'\n')
{
ret.push_back(iter);
count += Wcwidth(iter);
}
else
{
for (; count < max_w; ++count)
ret.push_back(ch);
ret.push_back(L'\n');
count = 0;
}
}
return CodeCvt::WideCharToUtf8(ret);
}
size_t Wcwidth(wchar_t ch)
{
int ret = wcwidth(ch);
//log_warn("{}:{}", GetUtf8ByWchar(ch), ret);
if (ret < 0)
ret = 0;
return ret;
}
}
std::string to_string(BufferView buf)
{
std::string ret = { (char*)buf.data(), buf.size() };
return ret;
}
std::string to_string_hex(BufferView buf, bool upper/* = false*/, bool add_tag /*= false*/)
{
std::string ret;
if (add_tag)
ret += "0x";
if (!upper)
{
for (size_t i = 0; i < buf.size(); ++i)
{
ret += fmt::format("{:02x}", (unsigned char)buf[i]);
}
}
else
{
for (size_t i = 0; i < buf.size(); ++i)
{
ret += fmt::format("{:02X}", (unsigned char)buf[i]);
}
}
return ret;
}
std::string to_string_check(BufferView buf, bool tips)
{
std::string ret = { (char*)buf.data(), buf.size() };
if (!CodeCvt::Utf8::Check(ret))
{
if(tips)
log_warn("转换失败,非utf8编码!");
return {};
}
return ret;
}
std::string to_string_auto(BufferView buf, bool add_tag /*= false*/)
{
std::string ret = to_string_check(buf, false);
if (!ret.empty())
return ret;
return to_string_hex(buf);
}
}