Scippy

SoPlex

Sequential object-oriented simPlex

ranges.h
Go to the documentation of this file.
1 // Formatting library for C++ - experimental range support
2 //
3 // Copyright (c) 2012 - present, Victor Zverovich
4 // All rights reserved.
5 //
6 // For the license information refer to format.h.
7 //
8 // Copyright (c) 2018 - present, Remotion (Igor Schulz)
9 // All Rights Reserved
10 // {fmt} support for ranges, containers and types tuple interface.
11 
12 #ifndef FMT_RANGES_H_
13 #define FMT_RANGES_H_
14 
15 #include <type_traits>
16 #include "format.h"
17 
18 // output only up to N items from the range.
19 #ifndef FMT_RANGE_OUTPUT_LENGTH_LIMIT
20 # define FMT_RANGE_OUTPUT_LENGTH_LIMIT 256
21 #endif
22 
24 
25 template <typename Char> struct formatting_base {
26  template <typename ParseContext>
27  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
28  return ctx.begin();
29  }
30 };
31 
32 template <typename Char, typename Enable = void>
34  static FMT_CONSTEXPR_DECL const std::size_t range_length_limit =
35  FMT_RANGE_OUTPUT_LENGTH_LIMIT; // output only up to N items from the
36  // range.
37  Char prefix;
38  Char delimiter;
39  Char postfix;
40  formatting_range() : prefix('{'), delimiter(','), postfix('}') {}
41  static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
42  static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
43 };
44 
45 template <typename Char, typename Enable = void>
47  Char prefix;
48  Char delimiter;
49  Char postfix;
50  formatting_tuple() : prefix('('), delimiter(','), postfix(')') {}
51  static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
52  static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
53 };
54 
55 namespace internal {
56 
57 template <typename RangeT, typename OutputIterator>
58 OutputIterator copy(const RangeT& range, OutputIterator out) {
59  for (auto it = range.begin(), end = range.end(); it != end; ++it)
60  *out++ = *it;
61  return out;
62 }
63 
64 template <typename OutputIterator>
65 OutputIterator copy(const char* str, OutputIterator out) {
66  while (*str) *out++ = *str++;
67  return out;
68 }
69 
70 template <typename OutputIterator>
71 OutputIterator copy(char ch, OutputIterator out) {
72  *out++ = ch;
73  return out;
74 }
75 
76 /// Return true value if T has std::string interface, like std::string_view.
77 template <typename T> class is_like_std_string {
78  template <typename U>
79  static auto check(U* p)
80  -> decltype((void)p->find('a'), p->length(), (void)p->data(), int());
81  template <typename> static void check(...);
82 
83  public:
84  static FMT_CONSTEXPR_DECL const bool value =
85  is_string<T>::value || !std::is_void<decltype(check<T>(nullptr))>::value;
86 };
87 
88 template <typename Char>
89 struct is_like_std_string<fmt::basic_string_view<Char>> : std::true_type {};
90 
91 template <typename... Ts> struct conditional_helper {};
92 
93 template <typename T, typename _ = void> struct is_range_ : std::false_type {};
94 
95 #if !FMT_MSC_VER || FMT_MSC_VER > 1800
96 template <typename T>
97 struct is_range_<
98  T, conditional_t<false,
99  conditional_helper<decltype(std::declval<T>().begin()),
100  decltype(std::declval<T>().end())>,
101  void>> : std::true_type {};
102 #endif
103 
104 /// tuple_size and tuple_element check.
105 template <typename T> class is_tuple_like_ {
106  template <typename U>
107  static auto check(U* p)
108  -> decltype(std::tuple_size<U>::value,
109  (void)std::declval<typename std::tuple_element<0, U>::type>(),
110  int());
111  template <typename> static void check(...);
112 
113  public:
114  static FMT_CONSTEXPR_DECL const bool value =
115  !std::is_void<decltype(check<T>(nullptr))>::value;
116 };
117 
118 // Check for integer_sequence
119 #if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
120 template <typename T, T... N>
121 using integer_sequence = std::integer_sequence<T, N...>;
122 template <std::size_t... N> using index_sequence = std::index_sequence<N...>;
123 template <std::size_t N>
124 using make_index_sequence = std::make_index_sequence<N>;
125 #else
126 template <typename T, T... N> struct integer_sequence {
127  using value_type = T;
128 
129  static FMT_CONSTEXPR std::size_t size() { return sizeof...(N); }
130 };
131 
132 template <std::size_t... N>
133 using index_sequence = integer_sequence<std::size_t, N...>;
134 
135 template <typename T, std::size_t N, T... Ns>
136 struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
137 template <typename T, T... Ns>
138 struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
139 
140 template <std::size_t N>
142 #endif
143 
144 template <class Tuple, class F, size_t... Is>
145 void for_each(index_sequence<Is...>, Tuple&& tup, F&& f) FMT_NOEXCEPT {
146  using std::get;
147  // using free function get<I>(T) now.
148  const int _[] = {0, ((void)f(get<Is>(tup)), 0)...};
149  (void)_; // blocks warnings
150 }
151 
152 template <class T>
154  T const&) {
155  return {};
156 }
157 
158 template <class Tuple, class F> void for_each(Tuple&& tup, F&& f) {
159  const auto indexes = get_indexes(tup);
160  for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
161 }
162 
163 template <typename Arg, FMT_ENABLE_IF(!is_like_std_string<
164  typename std::decay<Arg>::type>::value)>
165 FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) {
166  return add_space ? " {}" : "{}";
167 }
168 
169 template <typename Arg, FMT_ENABLE_IF(is_like_std_string<
170  typename std::decay<Arg>::type>::value)>
171 FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) {
172  return add_space ? " \"{}\"" : "\"{}\"";
173 }
174 
175 FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char*) {
176  return add_space ? " \"{}\"" : "\"{}\"";
177 }
178 FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t*) {
179  return add_space ? L" \"{}\"" : L"\"{}\"";
180 }
181 
182 FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char) {
183  return add_space ? " '{}'" : "'{}'";
184 }
185 FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t) {
186  return add_space ? L" '{}'" : L"'{}'";
187 }
188 
189 } // namespace internal
190 
191 template <typename T> struct is_tuple_like {
192  static FMT_CONSTEXPR_DECL const bool value =
194 };
195 
196 template <typename TupleT, typename Char>
197 struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> {
198  private:
199  // C++11 generic lambda for format()
200  template <typename FormatContext> struct format_each {
201  template <typename T> void operator()(const T& v) {
202  if (i > 0) {
203  if (formatting.add_prepostfix_space) {
204  *out++ = ' ';
205  }
206  out = internal::copy(formatting.delimiter, out);
207  }
208  out = format_to(out,
210  (formatting.add_delimiter_spaces && i > 0), v),
211  v);
212  ++i;
213  }
214 
216  std::size_t& i;
217  typename std::add_lvalue_reference<decltype(
218  std::declval<FormatContext>().out())>::type out;
219  };
220 
221  public:
223 
224  template <typename ParseContext>
225  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
226  return formatting.parse(ctx);
227  }
228 
229  template <typename FormatContext = format_context>
230  auto format(const TupleT& values, FormatContext& ctx) -> decltype(ctx.out()) {
231  auto out = ctx.out();
232  std::size_t i = 0;
233  internal::copy(formatting.prefix, out);
234 
235  internal::for_each(values, format_each<FormatContext>{formatting, i, out});
236  if (formatting.add_prepostfix_space) {
237  *out++ = ' ';
238  }
239  internal::copy(formatting.postfix, out);
240 
241  return ctx.out();
242  }
243 };
244 
245 template <typename T, typename Char> struct is_range {
246  static FMT_CONSTEXPR_DECL const bool value =
249  !std::is_convertible<T, std::basic_string<Char>>::value &&
250  !std::is_constructible<internal::std_string_view<Char>, T>::value;
251 };
252 
253 template <typename RangeT, typename Char>
254 struct formatter<RangeT, Char,
255  enable_if_t<fmt::is_range<RangeT, Char>::value>> {
257 
258  template <typename ParseContext>
259  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
260  return formatting.parse(ctx);
261  }
262 
263  template <typename FormatContext>
264  typename FormatContext::iterator format(const RangeT& values,
265  FormatContext& ctx) {
266  auto out = internal::copy(formatting.prefix, ctx.out());
267  std::size_t i = 0;
268  for (auto it = values.begin(), end = values.end(); it != end; ++it) {
269  if (i > 0) {
270  if (formatting.add_prepostfix_space) *out++ = ' ';
271  out = internal::copy(formatting.delimiter, out);
272  }
273  out = format_to(out,
275  (formatting.add_delimiter_spaces && i > 0), *it),
276  *it);
277  if (++i > formatting.range_length_limit) {
278  out = format_to(out, " ... <other elements>");
279  break;
280  }
281  }
282  if (formatting.add_prepostfix_space) *out++ = ' ';
283  return internal::copy(formatting.postfix, out);
284  }
285 };
286 
287 template <typename Char, typename... T> struct tuple_arg_join : internal::view {
288  const std::tuple<T...>& tuple;
290 
291  tuple_arg_join(const std::tuple<T...>& t, basic_string_view<Char> s)
292  : tuple{t}, sep{s} {}
293 };
294 
295 template <typename Char, typename... T>
296 struct formatter<tuple_arg_join<Char, T...>, Char> {
297  template <typename ParseContext>
298  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
299  return ctx.begin();
300  }
301 
302  template <typename FormatContext>
303  typename FormatContext::iterator format(
304  const tuple_arg_join<Char, T...>& value, FormatContext& ctx) {
305  return format(value, ctx, internal::make_index_sequence<sizeof...(T)>{});
306  }
307 
308  private:
309  template <typename FormatContext, size_t... N>
310  typename FormatContext::iterator format(
311  const tuple_arg_join<Char, T...>& value, FormatContext& ctx,
313  return format_args(value, ctx, std::get<N>(value.tuple)...);
314  }
315 
316  template <typename FormatContext>
317  typename FormatContext::iterator format_args(
318  const tuple_arg_join<Char, T...>&, FormatContext& ctx) {
319  // NOTE: for compilers that support C++17, this empty function instantiation
320  // can be replaced with a constexpr branch in the variadic overload.
321  return ctx.out();
322  }
323 
324  template <typename FormatContext, typename Arg, typename... Args>
325  typename FormatContext::iterator format_args(
326  const tuple_arg_join<Char, T...>& value, FormatContext& ctx,
327  const Arg& arg, const Args&... args) {
328  using base = formatter<typename std::decay<Arg>::type, Char>;
329  auto out = ctx.out();
330  out = base{}.format(arg, ctx);
331  if (sizeof...(Args) > 0) {
332  out = std::copy(value.sep.begin(), value.sep.end(), out);
333  ctx.advance_to(out);
334  return format_args(value, ctx, args...);
335  }
336  return out;
337  }
338 };
339 
340 /**
341  \rst
342  Returns an object that formats `tuple` with elements separated by `sep`.
343 
344  **Example**::
345 
346  std::tuple<int, char> t = {1, 'a'};
347  fmt::print("{}", fmt::join(t, ", "));
348  // Output: "1, a"
349  \endrst
350  */
351 template <typename... T>
352 FMT_CONSTEXPR tuple_arg_join<char, T...> join(const std::tuple<T...>& tuple,
353  string_view sep) {
354  return {tuple, sep};
355 }
356 
357 template <typename... T>
358 FMT_CONSTEXPR tuple_arg_join<wchar_t, T...> join(const std::tuple<T...>& tuple,
359  wstring_view sep) {
360  return {tuple, sep};
361 }
362 
364 
365 #endif // FMT_RANGES_H_
formatting_tuple()
Definition: ranges.h:50
#define FMT_BEGIN_NAMESPACE
Definition: core.h:163
static FMT_CONSTEXPR std::size_t size()
Definition: ranges.h:129
formatting_range()
Definition: ranges.h:40
std::basic_string< Char > format(const text_style &ts, const S &format_str, const Args &... args)
Definition: color.h:562
Char postfix
Definition: ranges.h:49
FMT_CONSTEXPR tuple_arg_join< char, T... > join(const std::tuple< T... > &tuple, string_view sep)
Definition: ranges.h:352
FormatContext::iterator format(const RangeT &values, FormatContext &ctx)
Definition: ranges.h:264
Char delimiter
Definition: ranges.h:38
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin())
Definition: ranges.h:298
auto format(const TupleT &values, FormatContext &ctx) -> decltype(ctx.out())
Definition: ranges.h:230
#define FMT_RANGE_OUTPUT_LENGTH_LIMIT
Definition: ranges.h:20
FormatContext::iterator format_args(const tuple_arg_join< Char, T... > &value, FormatContext &ctx, const Arg &arg, const Args &... args)
Definition: ranges.h:325
#define FMT_CONSTEXPR_DECL
Definition: core.h:76
Char postfix
Definition: ranges.h:39
static FMT_CONSTEXPR_DECL const bool add_prepostfix_space
Definition: ranges.h:42
FMT_CONSTEXPR const wchar_t * format_str_quoted(bool add_space, const wchar_t)
Definition: ranges.h:185
basic_string_view< Char > sep
Definition: ranges.h:289
OutputIt format_to(OutputIt out, const CompiledFormat &cf, const Args &... args)
Definition: compile.h:559
static FMT_CONSTEXPR_DECL const std::size_t range_length_limit
Definition: ranges.h:34
#define FMT_END_NAMESPACE
Definition: core.h:158
tuple_size and tuple_element check.
Definition: ranges.h:105
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin())
Definition: ranges.h:225
void for_each(Tuple &&tup, F &&f)
Definition: ranges.h:158
typename std::enable_if< B, T >::type enable_if_t
Definition: core.h:204
FMT_CONSTEXPR make_index_sequence< std::tuple_size< T >::value > get_indexes(T const &)
Definition: ranges.h:153
static FMT_CONSTEXPR_DECL const bool add_prepostfix_space
Definition: ranges.h:52
FMT_CONSTEXPR const char * format_str_quoted(bool add_space, const Arg &)
Definition: ranges.h:165
std::add_lvalue_reference< decltype(std::declval< FormatContext >).out())>::type out
Definition: ranges.h:218
OutputIterator copy(const RangeT &range, OutputIterator out)
Definition: ranges.h:58
FormatContext::iterator format(const tuple_arg_join< Char, T... > &value, FormatContext &ctx, internal::index_sequence< N... >)
Definition: ranges.h:310
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin())
Definition: ranges.h:27
Char delimiter
Definition: ranges.h:48
#define FMT_ENABLE_IF(...)
Definition: core.h:220
typename std::conditional< B, T, F >::type conditional_t
Definition: core.h:206
void for_each(index_sequence< Is... >, Tuple &&tup, F &&f) FMT_NOEXCEPT
Definition: ranges.h:145
integer_sequence< std::size_t, N... > index_sequence
Definition: ranges.h:133
Return true value if T has std::string interface, like std::string_view.
Definition: ranges.h:77
tuple_arg_join(const std::tuple< T... > &t, basic_string_view< Char > s)
Definition: ranges.h:291
type
Definition: core.h:687
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin())
Definition: ranges.h:259
OutputIterator copy(char ch, OutputIterator out)
Definition: ranges.h:71
FormatContext::iterator format(const tuple_arg_join< Char, T... > &value, FormatContext &ctx)
Definition: ranges.h:303
#define FMT_NOEXCEPT
Definition: core.h:114
static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces
Definition: ranges.h:41
FormatContext::iterator format_args(const tuple_arg_join< Char, T... > &, FormatContext &ctx)
Definition: ranges.h:317
const std::tuple< T... > & tuple
Definition: ranges.h:288
#define FMT_CONSTEXPR
Definition: core.h:75
internal::named_arg< T, Char > arg(const S &name, const T &arg)
Definition: core.h:1422