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 <vector>
12
13#define FMT_HEADER_ONLY
14#include <fmt/format.h>
15
22namespace ccf::nonstd
23{
27 template <typename T, template <typename...> class U>
28 struct is_specialization : std::false_type
29 {};
30
31 template <template <typename...> class T, typename... Args>
32 struct is_specialization<T<Args...>, T> : std::true_type
33 {};
34
37 template <typename T>
38 struct is_std_array : std::false_type
39 {};
40
41 template <typename T, size_t N>
42 struct is_std_array<std::array<T, N>> : public std::true_type
43 {};
44
47 template <typename T>
48 struct is_std_vector : std::false_type
49 {};
50
51 template <typename T>
52 struct is_std_vector<std::vector<T>> : public std::true_type
53 {};
54
60 template <typename T>
61 struct dependent_false : public std::false_type
62 {};
63
64 template <typename T>
65 static constexpr bool dependent_false_v = dependent_false<T>::value;
66
67 template <typename T, T>
68 struct value_dependent_false : public std::false_type
69 {};
70
71 template <typename T, T t>
72 static constexpr bool value_dependent_false_v = dependent_false<T>::value;
73
76 static inline std::vector<std::string_view> split(
77 const std::string_view& s,
78 const std::string_view& separator = " ",
79 size_t max_split = SIZE_MAX)
80 {
81 std::vector<std::string_view> result;
82
83 auto separator_end = 0;
84 auto next_separator_start = s.find(separator);
85 while (next_separator_start != std::string_view::npos &&
86 result.size() < max_split)
87 {
88 result.push_back(
89 s.substr(separator_end, next_separator_start - separator_end));
90
91 separator_end = next_separator_start + separator.size();
92 next_separator_start = s.find(separator, separator_end);
93 }
94
95 result.push_back(s.substr(separator_end));
96
97 return result;
98 }
99
100 /* split_1 wraps split and allows writing things like:
101 * auto [host, port] = ccf::nonstd::split_1("1.2.3.4:8000", ":")
102 */
103 static inline std::tuple<std::string_view, std::string_view> split_1(
104 const std::string_view& s, const std::string_view& separator)
105 {
106 const auto v = split(s, separator, 1);
107 if (v.size() == 1)
108 {
109 // If separator is not present, return {s, ""};
110 return std::make_tuple(v[0], "");
111 }
112
113 return std::make_tuple(v[0], v[1]);
114 }
115
122 static inline std::vector<std::string_view> rsplit(
123 const std::string_view& s,
124 const std::string_view& separator = " ",
125 size_t max_split = SIZE_MAX)
126 {
127 std::vector<std::string_view> result;
128
129 auto prev_separator_start = s.size();
130 auto next_separator_start = s.rfind(separator);
131 while (next_separator_start != std::string_view::npos &&
132 result.size() < max_split)
133 {
134 auto separator_end = next_separator_start + separator.size();
135
136 result.push_back(
137 s.substr(separator_end, prev_separator_start - separator_end));
138
139 prev_separator_start = next_separator_start;
140
141 if (next_separator_start == 0)
142 {
143 break;
144 }
145 else
146 {
147 next_separator_start = s.rfind(separator, prev_separator_start - 1);
148 }
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
189 template <size_t I = 0, typename F, typename... Ts>
190 static void tuple_for_each(const std::tuple<Ts...>& t, const F& f)
191 {
192 if constexpr (I < sizeof...(Ts))
193 {
194 f(std::get<I>(t));
195 tuple_for_each<I + 1>(t, f);
196 }
197 }
198}
Definition nonstd.h:23
STL namespace.
Definition nonstd.h:62
Definition nonstd.h:29
Definition nonstd.h:39
Definition nonstd.h:49