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 <chrono>
8#include <ctime>
9#include <regex>
10#include <string>
11#include <string_view>
12#include <type_traits>
13#include <unistd.h>
14#include <vector>
15
16#define FMT_HEADER_ONLY
17#include <fmt/format.h>
18
25namespace ccf::nonstd
26{
30 template <typename T, template <typename...> class U>
31 struct is_specialization : std::false_type
32 {};
33
34 template <template <typename...> class T, typename... Args>
35 struct is_specialization<T<Args...>, T> : std::true_type
36 {};
37
40 template <typename T>
41 struct is_std_array : std::false_type
42 {};
43
44 template <typename T, size_t N>
45 struct is_std_array<std::array<T, N>> : public std::true_type
46 {};
47
50 template <typename T>
51 struct is_std_vector : std::false_type
52 {};
53
54 template <typename T>
55 struct is_std_vector<std::vector<T>> : public std::true_type
56 {};
57
63 template <typename T>
64 struct dependent_false : public std::false_type
65 {};
66
67 template <typename T>
68 static constexpr bool dependent_false_v = dependent_false<T>::value;
69
70 template <typename T, T>
71 struct value_dependent_false : public std::false_type
72 {};
73
74 template <typename T, T t>
75 static constexpr bool value_dependent_false_v = dependent_false<T>::value;
76
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)
83 {
84 std::vector<std::string_view> result;
85
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)
90 {
91 result.push_back(
92 s.substr(separator_end, next_separator_start - separator_end));
93
94 separator_end = next_separator_start + separator.size();
95 next_separator_start = s.find(separator, separator_end);
96 }
97
98 result.push_back(s.substr(separator_end));
99
100 return result;
101 }
102
103 /* split_1 wraps split and allows writing things like:
104 * auto [host, port] = ccf::nonstd::split_1("1.2.3.4:8000", ":")
105 */
106 static inline std::tuple<std::string_view, std::string_view> split_1(
107 const std::string_view& s, const std::string_view& separator)
108 {
109 const auto v = split(s, separator, 1);
110 if (v.size() == 1)
111 {
112 // If separator is not present, return {s, ""};
113 return std::make_tuple(v[0], "");
114 }
115
116 return std::make_tuple(v[0], v[1]);
117 }
118
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)
129 {
130 std::vector<std::string_view> result;
131
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)
136 {
137 auto separator_end = next_separator_start + separator.size();
138
139 result.push_back(
140 s.substr(separator_end, prev_separator_start - separator_end));
141
142 prev_separator_start = next_separator_start;
143
144 if (next_separator_start == 0)
145 {
146 break;
147 }
148 next_separator_start = s.rfind(separator, prev_separator_start - 1);
149 }
150
151 result.push_back(s.substr(0, prev_separator_start));
152
153 return result;
154 }
155
156 /* rsplit_1 wraps rsplit _and reverses the result order_ and allows writing
157 * things like:
158 * auto [host, port] = ccf::nonstd::rsplit_1("[1:2:3:4]:8000", ":")
159 */
160 static inline std::tuple<std::string_view, std::string_view> rsplit_1(
161 const std::string_view& s, const std::string_view& separator)
162 {
163 const auto v = rsplit(s, separator, 1);
164 if (v.size() == 1)
165 {
166 // If separator is not present, return {"", s};
167 return std::make_tuple("", v[0]);
168 }
169
170 return std::make_tuple(v[1], v[0]);
171 }
172
175 static inline void to_upper(std::string& s)
176 {
177 std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) {
178 return std::toupper(c);
179 });
180 }
181 static inline void to_lower(std::string& s)
182 {
183 std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) {
184 return std::tolower(c);
185 });
186 }
187
188 static inline std::string_view trim(
189 std::string_view s, std::string_view trim_chars = " \t\r\n")
190 {
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);
194 }
195
197 template <size_t I = 0, typename F, typename... Ts>
198 static void tuple_for_each(const std::tuple<Ts...>& t, const F& f)
199 {
200 if constexpr (I < sizeof...(Ts))
201 {
202 f(std::get<I>(t));
203 tuple_for_each<I + 1>(t, f);
204 }
205 }
206
207 static void close_fd(int* fd)
208 {
209 if (fd != nullptr && *fd >= 0)
210 {
211 close(*fd);
212 *fd = -1;
213 }
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 {fd, close_fd};
220 }
221
222 // A custom clock type for handling certificate validity periods, which are
223 // defined in terms of seconds since the epoch. This avoids issues with
224 // system_clock::time_point being unable to represent times after 2262-04-11
225 // 23:47:17 UTC (due to tracking nanosecond precision).
227 {
228 using duration = std::chrono::seconds;
229 using rep = duration::rep;
230 using period = duration::period;
231 using time_point = std::chrono::time_point<SystemClock>;
232 static constexpr bool is_steady = false;
233
234 static time_point now() noexcept
235 {
236 return time_point(duration(std::time(nullptr)));
237 }
238
239 static std::time_t to_time_t(const time_point& t) noexcept
240 {
241 return std::time_t(t.time_since_epoch().count());
242 }
243
244 static time_point from_time_t(std::time_t t) noexcept
245 {
246 return time_point(duration(t));
247 }
248 };
249}
Definition nonstd.h:26
std::unique_ptr< int, decltype(&close_fd)> CloseFdGuard
Definition nonstd.h:216
STL namespace.
Definition nonstd.h:227
std::chrono::seconds duration
Definition nonstd.h:228
std::chrono::time_point< SystemClock > time_point
Definition nonstd.h:231
duration::rep rep
Definition nonstd.h:229
static time_point now() noexcept
Definition nonstd.h:234
static constexpr bool is_steady
Definition nonstd.h:232
static time_point from_time_t(std::time_t t) noexcept
Definition nonstd.h:244
duration::period period
Definition nonstd.h:230
static std::time_t to_time_t(const time_point &t) noexcept
Definition nonstd.h:239
Definition nonstd.h:65
Definition nonstd.h:32
Definition nonstd.h:42
Definition nonstd.h:52