28 template <
typename T,
template <
typename...>
class U>
32 template <
template <
typename...>
class T,
typename... Args>
42 template <
typename T,
size_t N>
68 template <
typename T, T>
72 template <
typename T, T t>
77 static inline std::vector<std::string_view> split(
78 const std::string_view& s,
79 const std::string_view& separator =
" ",
80 size_t max_split = SIZE_MAX)
82 std::vector<std::string_view> result;
84 auto separator_end = 0;
85 auto next_separator_start = s.find(separator);
86 while (next_separator_start != std::string_view::npos &&
87 result.size() < max_split)
90 s.substr(separator_end, next_separator_start - separator_end));
92 separator_end = next_separator_start + separator.size();
93 next_separator_start = s.find(separator, separator_end);
96 result.push_back(s.substr(separator_end));
104 static inline std::tuple<std::string_view, std::string_view> split_1(
105 const std::string_view& s,
const std::string_view& separator)
107 const auto v = split(s, separator, 1);
111 return std::make_tuple(v[0],
"");
114 return std::make_tuple(v[0], v[1]);
123 static inline std::vector<std::string_view> rsplit(
124 const std::string_view& s,
125 const std::string_view& separator =
" ",
126 size_t max_split = SIZE_MAX)
128 std::vector<std::string_view> result;
130 auto prev_separator_start = s.size();
131 auto next_separator_start = s.rfind(separator);
132 while (next_separator_start != std::string_view::npos &&
133 result.size() < max_split)
135 auto separator_end = next_separator_start + separator.size();
138 s.substr(separator_end, prev_separator_start - separator_end));
140 prev_separator_start = next_separator_start;
142 if (next_separator_start == 0)
148 next_separator_start = s.rfind(separator, prev_separator_start - 1);
152 result.push_back(s.substr(0, prev_separator_start));
161 static inline std::tuple<std::string_view, std::string_view> rsplit_1(
162 const std::string_view& s,
const std::string_view& separator)
164 const auto v = rsplit(s, separator, 1);
168 return std::make_tuple(
"", v[0]);
171 return std::make_tuple(v[1], v[0]);
176 static inline void to_upper(std::string& s)
178 std::transform(s.begin(), s.end(), s.begin(), [](
unsigned char c) {
179 return std::toupper(c);
182 static inline void to_lower(std::string& s)
184 std::transform(s.begin(), s.end(), s.begin(), [](
unsigned char c) {
185 return std::tolower(c);
189 static inline std::string_view trim(
190 std::string_view s, std::string_view trim_chars =
" \t\r\n")
192 const auto start = std::min(s.find_first_not_of(trim_chars), s.size());
193 const auto end = std::min(s.find_last_not_of(trim_chars) + 1, s.size());
194 return s.substr(start, end - start);
198 template <
size_t I = 0,
typename F,
typename... Ts>
199 static void tuple_for_each(
const std::tuple<Ts...>& t,
const F& f)
201 if constexpr (I <
sizeof...(Ts))
204 tuple_for_each<I + 1>(t, f);
208 static void close_fd(
int* fd)
210 if (fd !=
nullptr && *fd >= 0)