14#include "ll/api/base/Concepts.h"
15#include "ll/api/base/Macro.h"
16#include "ll/api/base/StdInt.h"
18#include "ll/api/Expected.h"
20namespace ll::inline utils::string_utils {
23template <std::invocable<std::
string_view> Fn>
24constexpr void splitByPattern(Fn&& fn, std::string_view s, std::string_view pattern,
bool keepEmpty =
false) {
25 if (s.empty())
return;
27 while ((pos = s.find(pattern)) != std::string::npos) {
28 if (keepEmpty || pos != 0) {
29 if (!std::invoke(std::forward<Fn>(fn), s.substr(0, pos)))
return;
31 s = s.substr(pos + pattern.size());
33 if (keepEmpty || !s.empty()) std::invoke(std::forward<Fn>(fn), s);
35template <concepts::IsString T>
36[[nodiscard]]
constexpr decltype(
auto) splitByPattern(T&& str, std::string_view pattern,
bool keepEmpty =
false) {
37 using ReturnTypeElement = std::conditional_t<std::is_same_v<T&&, std::string&&>, std::string, std::string_view>;
38 std::vector<ReturnTypeElement> ret;
40 [&](std::string_view sv) {
41 ret.push_back(ReturnTypeElement{sv});
58constexpr std::string& replaceAll(std::string& str, std::string_view oldValue, std::string_view newValue) {
59 for (std::string::size_type pos(0); pos != std::string::npos; pos += newValue.length()) {
60 if ((pos = str.find(oldValue, pos)) != std::string::npos) str.replace(pos, oldValue.length(), newValue);
66[[nodiscard]]
constexpr std::string
67replaceAll(std::string
const& str, std::string_view oldValue, std::string_view newValue) {
68 std::string ret = str;
69 replaceAll(ret, oldValue, newValue);
74replaceContent(std::string& str, std::string_view before, std::string_view after, std::string_view relplaceWith) {
75 auto startOffset = str.find(before);
76 if (startOffset == std::string::npos)
return false;
77 startOffset += before.size();
78 auto endOffset = after.empty() ? std::string::npos : str.find(after, startOffset);
79 str.replace(startOffset, endOffset - startOffset, relplaceWith);
83constexpr inline uchar digitFromByte[] = {
84 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
85 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
86 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, 255, 10,
87 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
88 33, 34, 35, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
89 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 255, 255, 255, 255, 255, 255, 255, 255, 255,
90 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
91 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
92 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
93 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
94 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
95 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
97static_assert(
sizeof(digitFromByte) == 256);
99[[nodiscard]]
constexpr uchar digitFromChar(
char chr)
noexcept {
return digitFromByte[
static_cast<uchar
>(chr)]; }
101constexpr inline char charconvDigits[2][37] = {
102 "0123456789abcdefghijklmnopqrstuvwxyz",
103 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
106[[nodiscard]]
constexpr char charFromInt(
bool upper, uchar i) {
return charconvDigits[upper][i]; }
124 requires std::is_integral_v<T>
125[[nodiscard]]
constexpr std::string
126intToHexStr(T value,
bool upperCase =
true,
bool no0x =
true,
bool noLeadingZero =
true) {
128 if (value < 0) result +=
'-';
129 if (!no0x) result +=
"0x";
130 bool leadingZero =
true;
131 for (
int i =
sizeof(T) * 2; i > 0; --i) {
132 auto hex =
static_cast<uchar
>((value >> (i - 1) * 4) & 0xF);
133 if (noLeadingZero && leadingZero && hex == 0)
continue;
135 result += charFromInt(upperCase, hex);
140[[nodiscard]]
constexpr std::string strToHexStr(std::string_view value,
bool upperCase =
false,
bool addSpace =
false) {
142 hex.reserve(value.size() * (addSpace ? 3 : 2));
143 for (uchar x : value) {
144 hex += charFromInt(upperCase, x / 16);
145 hex += charFromInt(upperCase, x % 16);
146 if (addSpace) hex +=
' ';
148 if (addSpace && hex.ends_with(
' ')) hex.pop_back();
152LLNDAPI std::string removeEscapeCode(std::string_view str);
154LLNDAPI std::string replaceAnsiToMcCode(std::string_view str);
156LLNDAPI std::string replaceMcToAnsiCode(std::string_view str);
158LLNDAPI
bool isu8str(std::string_view str)
noexcept;
160LLNDAPI std::string tou8str(std::string_view str);
162LLNDAPI std::string toSnakeCase(std::string_view str);
164LLNDAPI std::string toLowerCase(std::string_view str);
176LLNDAPI std::wstring str2wstr(std::string_view str, uint codePage = CodePage::UTF8);
178LLNDAPI std::string wstr2str(std::wstring_view wstr, uint codePage = CodePage::UTF8);
181 str2str(std::string_view str, uint fromCodePage = CodePage::DefaultACP, uint toCodePage = CodePage::UTF8);
183[[nodiscard]]
inline std::string u8str2str(std::u8string str) {
184 std::string& tmp = *
reinterpret_cast<std::string*
>(&str);
185 return {std::move(tmp)};
188[[nodiscard]]
inline std::u8string str2u8str(std::string str) {
189 std::u8string& tmp = *
reinterpret_cast<std::u8string*
>(&str);
190 return {std::move(tmp)};
193[[nodiscard]]
inline std::string
const& u8str2strConst(std::u8string
const& str) {
194 return *
reinterpret_cast<std::string const*
>(&str);
197[[nodiscard]]
inline std::u8string
const& str2u8strConst(std::string
const& str) {
198 return *
reinterpret_cast<std::u8string const*
>(&str);
201[[nodiscard]]
inline std::string_view u8sv2sv(std::u8string_view str) {
202 return {
reinterpret_cast<char const*
>(str.data()), str.size()};
205[[nodiscard]]
inline std::u8string_view sv2u8sv(std::string_view str) {
206 return {
reinterpret_cast<char8_t const*
>(str.data()), str.size()};
209LLNDAPI Expected<bool> svtobool(std::string_view);
211template <
class T,
class... Args>
212[[nodiscard]] LL_CONSTEXPR23 Expected<T> svtonum(std::string_view str,
size_t* idx, Args&&... args) {
214 const auto ans = ::std::from_chars(&*str.begin(), &*str.end(), result, std::forward<Args>(args)...);
215 if (ans.ec != std::errc{}) {
216 return makeErrorCodeError(ans.ec);
219 *idx =
static_cast<size_t>(ans.ptr - &*str.begin());
223[[nodiscard]]
inline decltype(
auto) svtoc(std::string_view str,
size_t* idx =
nullptr,
int base = 10) {
224 return svtonum<schar>(str, idx, base);
226[[nodiscard]]
inline decltype(
auto) svtouc(std::string_view str,
size_t* idx =
nullptr,
int base = 10) {
227 return svtonum<uchar>(str, idx, base);
229[[nodiscard]]
inline decltype(
auto) svtos(std::string_view str,
size_t* idx =
nullptr,
int base = 10) {
230 return svtonum<short>(str, idx, base);
232[[nodiscard]]
inline decltype(
auto) svtous(std::string_view str,
size_t* idx =
nullptr,
int base = 10) {
233 return svtonum<ushort>(str, idx, base);
235[[nodiscard]]
inline decltype(
auto) svtoi(std::string_view str,
size_t* idx =
nullptr,
int base = 10) {
236 return svtonum<int>(str, idx, base);
238[[nodiscard]]
inline decltype(
auto) svtoui(std::string_view str,
size_t* idx =
nullptr,
int base = 10) {
239 return svtonum<uint>(str, idx, base);
241[[nodiscard]]
inline decltype(
auto) svtol(std::string_view str,
size_t* idx =
nullptr,
int base = 10) {
242 return svtonum<long>(str, idx, base);
244[[nodiscard]]
inline decltype(
auto) svtoul(std::string_view str,
size_t* idx =
nullptr,
int base = 10) {
245 return svtonum<ulong>(str, idx, base);
247[[nodiscard]]
inline decltype(
auto) svtoll(std::string_view str,
size_t* idx =
nullptr,
int base = 10) {
248 return svtonum<int64>(str, idx, base);
250[[nodiscard]]
inline decltype(
auto) svtoull(std::string_view str,
size_t* idx =
nullptr,
int base = 10) {
251 return svtonum<uint64>(str, idx, base);
253[[nodiscard]]
inline decltype(
auto)
254svtof(std::string_view str,
size_t* idx =
nullptr, std::chars_format format = std::chars_format::general) {
255 return svtonum<float>(str, idx, format);
257[[nodiscard]]
inline decltype(
auto)
258svtod(std::string_view str,
size_t* idx =
nullptr, std::chars_format format = std::chars_format::general) {
259 return svtonum<double>(str, idx, format);
261[[nodiscard]]
inline decltype(
auto)
262svtold(std::string_view str,
size_t* idx =
nullptr, std::chars_format format = std::chars_format::general) {
263 return svtonum<ldouble>(str, idx, format);