#include "dl_string.h" #include #include #include 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 FormatString2(const Vector2& arr) { auto W = arr.GetWidth(); auto H = arr.GetHeight(); using Index = decltype(W); //每一列得到一个最大宽度 std::vector 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 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 ParseCommand(std::string_view cmd) { std::vector 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); } }