rocprofiler-sdk/cxx/details/join.hpp Source File

rocprofiler-sdk/cxx/details/join.hpp Source File#

Rocprofiler SDK Developer API: rocprofiler-sdk/cxx/details/join.hpp Source File
Rocprofiler SDK Developer API 0.5.0
ROCm Profiling API and tools
join.hpp
Go to the documentation of this file.
1// MIT License
2//
3// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23#pragma once
24
26
27#include <array>
28#include <cstring>
29#include <initializer_list>
30#include <ios>
31#include <sstream>
32#include <string>
33#include <string_view>
34#include <tuple>
35#include <type_traits>
36
37namespace rocprofiler
38{
39namespace sdk
40{
41namespace join
42{
43template <typename... ArgsT>
44inline void
45consume_args(ArgsT&&...)
46{}
47
48enum
49{
51 QuoteStrings = 0x1
52};
53
54template <size_t Idx>
56{
57 static constexpr auto index() { return Idx; }
58 std::string_view delimiter = {};
59 std::string_view prefix = {};
60 std::string_view suffix = {};
61};
62
66
68{
69 using format_flags_t = std::ios_base::fmtflags;
71
72 config() = default;
73 ~config() = default;
74 config(const config&) = default;
76
79
80 // converting constructor
81 config(std::string_view _delim)
83 {}
84
85 // converting constructor
86 config(const char* const _delim)
88 {}
89
93
97
101
106
111
116
117 format_flags_t flags = std::ios_base::boolalpha;
118 array_config array = {", ", "[", "]"};
119 pair_config pair = {", ", "{", "}"};
120};
121
122namespace impl
123{
124template <int TraitT, typename ArgT>
125inline decltype(auto)
126join_arg(config _cfg, ArgT&& _v)
127{
128 using arg_type = mpl::basic_identity_t<ArgT>;
129
130 constexpr bool _is_string_type = mpl::is_string_type<arg_type>::value;
131 constexpr bool _is_iterable = mpl::is_iterable<arg_type>(0);
132 constexpr bool _has_traits_type = mpl::has_traits<arg_type>(0);
133 constexpr bool _has_key_type = mpl::has_key_type<arg_type>(0);
134 constexpr bool _has_value_type = mpl::has_value_type<arg_type>(0);
135 constexpr bool _has_mapped_type = mpl::has_mapped_type<arg_type>(0);
136
137 if constexpr(_is_string_type)
138 {
139 if constexpr(TraitT == QuoteStrings)
140 {
141 return std::string{"\""} + std::string{std::forward<ArgT>(_v)} + std::string{"\""};
142 }
143 else
144 {
145 return std::forward<ArgT>(_v);
146 }
147 }
148 else if constexpr(_is_iterable && !_has_traits_type &&
149 (_has_value_type || (_has_key_type && _has_mapped_type)))
150 {
151 if constexpr(_has_key_type && _has_mapped_type)
152 {
153 std::stringstream _ss{};
154 _ss.setf(_cfg.flags);
155 for(auto&& itr : std::forward<ArgT>(_v))
156 _ss << _cfg.array.delimiter << _cfg.pair.prefix << join_arg<TraitT>(_cfg, itr.first)
157 << _cfg.pair.delimiter << join_arg<TraitT>(_cfg, itr.second)
158 << _cfg.pair.suffix;
159 auto _ret = _ss.str();
160 auto&& _len = _cfg.array.delimiter.length();
161 return (_ret.length() > _len) ? (std::string{_cfg.array.prefix} + _ret.substr(_len) +
162 std::string{_cfg.array.suffix})
163 : std::string{};
164 }
165 else if constexpr(_has_value_type)
166 {
167 std::stringstream _ss{};
168 _ss.setf(_cfg.flags);
169 for(auto&& itr : std::forward<ArgT>(_v))
170 _ss << _cfg.array.delimiter << join_arg<TraitT>(_cfg, itr);
171 auto _ret = _ss.str();
172 auto&& _len = _cfg.array.delimiter.length();
173 return (_ret.length() > _len) ? (std::string{_cfg.array.prefix} + _ret.substr(_len) +
174 std::string{_cfg.array.suffix})
175 : std::string{};
176 }
177 }
178 else if constexpr(mpl::supports_ostream<ArgT>(0))
179 {
180 return std::forward<ArgT>(_v);
181 }
182 else
183 {
184 static_assert(_is_iterable, "Type is not iterable");
185 static_assert(!_has_traits_type, "Type has a traits type");
186 if constexpr(!_has_value_type)
187 {
188 static_assert(_has_key_type && _has_mapped_type,
189 "Type must have a key_type and mapped_type if there is no value_type");
190 }
191 else
192 {
193 static_assert(_has_value_type,
194 "Type must have a value_type if there is no key_type and mapped_type");
195 }
196 static_assert(std::is_empty<ArgT>::value,
197 "Error! argument type cannot be written to output stream");
198 }
199 // suppress any unused but set variable warnings
200 consume_args(_is_string_type,
201 _is_iterable,
202 _has_traits_type,
203 _has_key_type,
204 _has_value_type,
205 _has_mapped_type);
206}
207} // namespace impl
208
209template <int TraitT = NoQuoteStrings, typename... Args>
210auto
211join(config _cfg, Args&&... _args)
212{
213 static_assert(std::is_trivially_copyable<config>::value,
214 "Error! config is not trivially copyable");
215
216 std::stringstream _ss{};
217 _ss.setf(_cfg.flags);
218 ((_ss << ((mpl::is_empty(_args)) ? std::string_view{} : std::string_view{_cfg.delimiter})
219 << impl::join_arg<TraitT>(_cfg, _args)),
220 ...);
221 auto _ret = _ss.str();
222 auto&& _len = _cfg.delimiter.length();
223 auto _cmp =
224 strncmp(std::string_view{_ret}.data(), std::string_view{_cfg.delimiter}.data(), _len) == 0;
225 return (_ret.length() > _len) ? (std::string{_cfg.prefix} +
226 ((_cmp) ? _ret.substr(_len) : _ret) + std::string{_cfg.suffix})
227 : std::string{};
228}
229
230template <int TraitT = NoQuoteStrings, typename... Args>
231auto
232join(std::array<std::string_view, 3>&& _delims, Args&&... _args)
233{
234 auto _cfg = config{};
235 _cfg.delimiter = _delims.at(0);
236 _cfg.prefix = _delims.at(1);
237 _cfg.suffix = _delims.at(2);
238 return join(_cfg, std::forward<Args>(_args)...);
239}
240
241template <int TraitT = NoQuoteStrings,
242 typename DelimT,
243 typename... Args,
244 std::enable_if_t<!mpl::is_basic_same<config, DelimT>::value, int> = 0>
245auto
246join(DelimT&& _delim, Args&&... _args)
247{
248 using delim_type = mpl::basic_identity_t<DelimT>;
249
250 if constexpr(std::is_constructible<config, delim_type>::value)
251 {
252 auto _cfg = config{std::forward<DelimT>(_delim)};
253 return join<TraitT>(_cfg, std::forward<Args>(_args)...);
254 }
255 else if constexpr(std::is_same<delim_type, char>::value)
256 {
257 auto _cfg = config{};
258 const char _delim_c[2] = {_delim, '\0'};
259 _cfg.delimiter = _delim_c;
260 return join<TraitT>(_cfg, std::forward<Args>(_args)...);
261 }
262 else
263 {
264 auto _cfg = config{};
265 _cfg.delimiter = std::string_view{_delim};
266 return join<TraitT>(_cfg, std::forward<Args>(_args)...);
267 }
268}
269
270template <typename ArgT>
271auto
272quoted(ArgT&& _arg)
273{
274 auto _cfg = config{};
275 _cfg.prefix = "\"";
276 _cfg.suffix = "\"";
277 return join(_cfg, std::forward<ArgT>(_arg));
278}
279} // namespace join
280} // namespace sdk
281} // namespace rocprofiler
decltype(auto) join_arg(config _cfg, ArgT &&_v)
Definition join.hpp:126
triplet_config< 0 > generic_config
Definition join.hpp:63
auto quoted(ArgT &&_arg)
Definition join.hpp:272
auto join(config _cfg, Args &&... _args)
Definition join.hpp:211
void consume_args(ArgsT &&...)
Definition join.hpp:45
bool is_empty(ArgT &&_v)
Definition mpl.hpp:188
STL namespace.
std::ios_base::fmtflags format_flags_t
Definition join.hpp:69
config(array_config _cfg)
Definition join.hpp:94
config(generic_config _generic, array_config _array)
Definition join.hpp:102
config(generic_config _generic, pair_config _pair)
Definition join.hpp:107
config(const char *const _delim)
Definition join.hpp:86
config(pair_config _cfg)
Definition join.hpp:98
config(generic_config _cfg)
Definition join.hpp:90
config(array_config _array, pair_config _pair)
Definition join.hpp:112
config(const config &)=default
config(config &&) noexcept=default
static constexpr auto index()
Definition join.hpp:57