30 template <
typename T,
template <
typename...>
class U>
34 template <
template <
typename...>
class T,
typename... Args>
44 template <
typename T,
size_t N>
70 template <
typename T, T>
74 template <
typename T, T t>
79 static inline std::vector<std::string_view> split(
80 const std::string_view& s,
81 const std::string_view& separator =
" ",
82 size_t max_split = SIZE_MAX)
84 std::vector<std::string_view> result;
86 auto separator_end = 0;
87 auto next_separator_start = s.find(separator);
88 while (next_separator_start != std::string_view::npos &&
89 result.size() < max_split)
92 s.substr(separator_end, next_separator_start - separator_end));
94 separator_end = next_separator_start + separator.size();
95 next_separator_start = s.find(separator, separator_end);
98 result.push_back(s.substr(separator_end));
106 static inline std::tuple<std::string_view, std::string_view> split_1(
107 const std::string_view& s,
const std::string_view& separator)
109 const auto v = split(s, separator, 1);
113 return std::make_tuple(v[0],
"");
116 return std::make_tuple(v[0], v[1]);
125 static inline std::vector<std::string_view> rsplit(
126 const std::string_view& s,
127 const std::string_view& separator =
" ",
128 size_t max_split = SIZE_MAX)
130 std::vector<std::string_view> result;
132 auto prev_separator_start = s.size();
133 auto next_separator_start = s.rfind(separator);
134 while (next_separator_start != std::string_view::npos &&
135 result.size() < max_split)
137 auto separator_end = next_separator_start + separator.size();
140 s.substr(separator_end, prev_separator_start - separator_end));
142 prev_separator_start = next_separator_start;
144 if (next_separator_start == 0)
148 next_separator_start = s.rfind(separator, prev_separator_start - 1);
151 result.push_back(s.substr(0, prev_separator_start));
160 static inline std::tuple<std::string_view, std::string_view> rsplit_1(
161 const std::string_view& s,
const std::string_view& separator)
163 const auto v = rsplit(s, separator, 1);
167 return std::make_tuple(
"", v[0]);
170 return std::make_tuple(v[1], v[0]);
175 static inline void to_upper(std::string& s)
177 std::transform(s.begin(), s.end(), s.begin(), [](
unsigned char c) {
178 return std::toupper(c);
181 static inline void to_lower(std::string& s)
183 std::transform(s.begin(), s.end(), s.begin(), [](
unsigned char c) {
184 return std::tolower(c);
188 static inline std::string_view trim(
189 std::string_view s, std::string_view trim_chars =
" \t\r\n")
191 const auto start = std::min(s.find_first_not_of(trim_chars), s.size());
192 const auto end = std::min(s.find_last_not_of(trim_chars) + 1, s.size());
193 return s.substr(start, end - start);
197 template <
size_t I = 0,
typename F,
typename... Ts>
198 static void tuple_for_each(
const std::tuple<Ts...>& t,
const F& f)
200 if constexpr (I <
sizeof...(Ts))
203 tuple_for_each<I + 1>(t, f);
207 static void close_fd(
int* fd)
209 if (fd !=
nullptr && *fd >= 0)
219 return {fd, close_fd};
229 using rep = duration::rep;
241 return std::time_t(t.time_since_epoch().count());