CCF
Loading...
Searching...
No Matches
nonstd.h
Go to the documentation of this file.
1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the Apache 2.0 License.
3#pragma once
4
5#include <array>
6#include <cctype>
7#include <regex>
8#include <string>
9#include <string_view>
10#include <type_traits>
11#include <unistd.h>
12#include <vector>
13
14#define FMT_HEADER_ONLY
15#include <fmt/format.h>
16
23namespace ccf::nonstd
24{
28 template <typename T, template <typename...> class U>
29 struct is_specialization : std::false_type
30 {};
31
32 template <template <typename...> class T, typename... Args>
33 struct is_specialization<T<Args...>, T> : std::true_type
34 {};
35
38 template <typename T>
39 struct is_std_array : std::false_type
40 {};
41
42 template <typename T, size_t N>
43 struct is_std_array<std::array<T, N>> : public std::true_type
44 {};
45
48 template <typename T>
49 struct is_std_vector : std::false_type
50 {};
51
52 template <typename T>
53 struct is_std_vector<std::vector<T>> : public std::true_type
54 {};
55
61 template <typename T>
62 struct dependent_false : public std::false_type
63 {};
64
65 template <typename T>
66 static constexpr bool dependent_false_v = dependent_false<T>::value;
67
68 template <typename T, T>
69 struct value_dependent_false : public std::false_type
70 {};
71
72 template <typename T, T t>
73 static constexpr bool value_dependent_false_v = dependent_false<T>::value;
74
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)
81 {
82 std::vector<std::string_view> result;
83
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)
88 {
89 result.push_back(
90 s.substr(separator_end, next_separator_start - separator_end));
91
92 separator_end = next_separator_start + separator.size();
93 next_separator_start = s.find(separator, separator_end);
94 }
95
96 result.push_back(s.substr(separator_end));
97
98 return result;
99 }
100
101 /* split_1 wraps split and allows writing things like:
102 * auto [host, port] = ccf::nonstd::split_1("1.2.3.4:8000", ":")
103 */
104 static inline std::tuple<std::string_view, std::string_view> split_1(
105 const std::string_view& s, const std::string_view& separator)
106 {
107 const auto v = split(s, separator, 1);
108 if (v.size() == 1)
109 {
110 // If separator is not present, return {s, ""};
111 return std::make_tuple(v[0], "");
112 }
113
114 return std::make_tuple(v[0], v[1]);
115 }
116
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)
127 {
128 std::vector<std::string_view> result;
129
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)
134 {
135 auto separator_end = next_separator_start + separator.size();
136
137 result.push_back(
138 s.substr(separator_end, prev_separator_start - separator_end));
139
140 prev_separator_start = next_separator_start;
141
142 if (next_separator_start == 0)
143 {
144 break;
145 }
146 else
147 {
148 next_separator_start = s.rfind(separator, prev_separator_start - 1);
149 }
150 }
151
152 result.push_back(s.substr(0, prev_separator_start));
153
154 return result;
155 }
156
157 /* rsplit_1 wraps rsplit _and reverses the result order_ and allows writing
158 * things like:
159 * auto [host, port] = ccf::nonstd::rsplit_1("[1:2:3:4]:8000", ":")
160 */
161 static inline std::tuple<std::string_view, std::string_view> rsplit_1(
162 const std::string_view& s, const std::string_view& separator)
163 {
164 const auto v = rsplit(s, separator, 1);
165 if (v.size() == 1)
166 {
167 // If separator is not present, return {"", s};
168 return std::make_tuple("", v[0]);
169 }
170
171 return std::make_tuple(v[1], v[0]);
172 }
173
176 static inline void to_upper(std::string& s)
177 {
178 std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) {
179 return std::toupper(c);
180 });
181 }
182 static inline void to_lower(std::string& s)
183 {
184 std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) {
185 return std::tolower(c);
186 });
187 }
188
189 static inline std::string_view trim(
190 std::string_view s, std::string_view trim_chars = " \t\r\n")
191 {
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);
195 }
196
198 template <size_t I = 0, typename F, typename... Ts>
199 static void tuple_for_each(const std::tuple<Ts...>& t, const F& f)
200 {
201 if constexpr (I < sizeof...(Ts))
202 {
203 f(std::get<I>(t));
204 tuple_for_each<I + 1>(t, f);
205 }
206 }
207
208 static void close_fd(int* fd)
209 {
210 if (fd != nullptr && *fd >= 0)
211 {
212 close(*fd);
213 *fd = -1;
214 }
215 }
216 using CloseFdGuard = std::unique_ptr<int, decltype(&close_fd)>;
217 static inline CloseFdGuard make_close_fd_guard(int* fd)
218 {
219 return CloseFdGuard(fd, close_fd);
220 }
221}
Definition nonstd.h:24
std::unique_ptr< int, decltype(&close_fd)> CloseFdGuard
Definition nonstd.h:216
STL namespace.
Definition nonstd.h:63
Definition nonstd.h:30
Definition nonstd.h:40
Definition nonstd.h:50