libfly  6.2.2
C++20 utility library for Linux, macOS, and Windows
format_parameters.hpp
1 #pragma once
2 
3 #include "fly/concepts/concepts.hpp"
4 #include "fly/types/string/concepts.hpp"
5 #include "fly/types/string/detail/classifier.hpp"
6 #include "fly/types/string/detail/format_parse_context.hpp"
7 #include "fly/types/string/detail/format_specifier.hpp"
8 #include "fly/types/string/formatters.hpp"
9 
10 #include <array>
11 #include <cstdint>
12 #include <string_view>
13 #include <type_traits>
14 
15 namespace fly::detail {
16 
20 struct MonoState
21 {
22 };
23 
27 template <typename FormatContext>
29 {
30  const void *m_value;
31 
32  void (*m_format)(
33  const void *value,
35  FormatContext &context,
37 };
38 
43 template <typename FormatContext>
45 {
46  const void *m_value;
47  std::size_t m_size;
48 
49  void (*m_format)(
50  const void *value,
51  std::size_t size,
52  FormatContext &context,
54 };
55 
59 template <typename FormatContext>
61 {
62  union
63  {
64  const void *m_pointer;
65  std::int64_t m_signed_int;
66  std::uint64_t m_unsigned_int;
67  float m_float;
68  double m_double;
69  long double m_long_double;
70  bool m_bool;
71  };
72 
73  void (*m_format)(
74  StandardValue value,
75  FormatContext &context,
77 };
78 
90 template <typename FormatContext, typename T>
91 void format_user_defined_value(
92  const void *value,
94  FormatContext &context,
96 
108 template <typename FormatContext, typename T>
109 void format_string_value(
110  const void *value,
111  std::size_t size,
112  FormatContext &context,
114 
125 template <typename FormatContext, typename T>
126 void format_standard_value(
128  FormatContext &context,
130 
137 template <typename FormatContext>
139 {
140  using char_type = typename FormatContext::char_type;
141 
142 public:
146  constexpr BasicFormatParameter() noexcept;
147 
155  template <fly::FormattableUserDefined T>
156  explicit constexpr BasicFormatParameter(const T &value) noexcept;
157 
166  template <fly::FormattableString T>
167  explicit constexpr BasicFormatParameter(const T &value) noexcept;
168 
176  template <fly::FormattablePointer T>
177  explicit constexpr BasicFormatParameter(T value) noexcept;
178 
186  template <fly::FormattableIntegral T>
187  explicit constexpr BasicFormatParameter(T value) noexcept;
188 
196  template <fly::FormattableFloatingPoint T>
197  explicit constexpr BasicFormatParameter(T value) noexcept;
198 
206  template <fly::FormattableBoolean T>
207  explicit constexpr BasicFormatParameter(T value) noexcept;
208 
216  constexpr void format(
218  FormatContext &context,
219  BasicFormatSpecifier<char_type> &&specifier) const;
220 
228  template <typename Visitor>
229  constexpr auto visit(Visitor &&visitor) const;
230 
234  explicit operator bool() const noexcept;
235 
236 private:
237  enum class Type : std::uint8_t
238  {
239  Invalid,
240  UserDefined,
241  String,
242  Pointer,
243  SignedInt,
244  UnsignedInt,
245  Float,
246  Double,
247  LongDouble,
248  Bool,
249  };
250 
251  union Value
252  {
253  MonoState m_monostate;
254  UserDefinedValue<FormatContext> m_user_defined;
256  StandardValue<FormatContext> m_standard;
257  };
258 
259  Type m_type;
260  Value m_value;
261 };
262 
269 template <typename FormatContext, typename... ParameterTypes>
271 {
273 
274 public:
280  constexpr BasicFormatParameters(ParameterTypes &&...parameters) noexcept;
281 
282 private:
283  friend FormatContext;
284 
285  const std::array<FormatParameter, sizeof...(ParameterTypes)> m_parameters;
286 };
287 
296 template <typename FormatContext, fly::Formattable<FormatContext>... ParameterTypes>
297 constexpr auto make_format_parameters(ParameterTypes &&...parameters)
298 {
299  return BasicFormatParameters<FormatContext, ParameterTypes...> {
300  std::forward<ParameterTypes>(parameters)...};
301 }
302 
303 //==================================================================================================
304 template <typename FormatContext, typename T>
305 inline void format_user_defined_value(
306  const void *value,
307  BasicFormatParseContext<typename FormatContext::char_type> &parse_context,
308  FormatContext &context,
309  BasicFormatSpecifier<typename FormatContext::char_type> &&specifier)
310 {
311  using Formatter = typename FormatContext::template formatter_type<T>;
312  Formatter formatter;
313 
314  if constexpr (fly::FormattableWithParsing<decltype(parse_context), Formatter>)
315  {
316  bool formatter_requires_parsing = true;
317 
318  if constexpr (fly::DerivedFrom<Formatter, decltype(specifier)>)
319  {
320  formatter_requires_parsing = !specifier.m_was_parsed_as_standard_formatter;
321  specifier.copy_formatting_options_into(formatter);
322  }
323 
324  if (formatter_requires_parsing)
325  {
326  parse_context.lexer().set_position(specifier.m_parse_index);
327  formatter.parse(parse_context);
328  }
329  }
330 
331  formatter.format(*static_cast<const T *>(value), context);
332 }
333 
334 //==================================================================================================
335 template <typename FormatContext, typename T>
336 inline void format_string_value(
337  const void *value,
338  std::size_t size,
339  FormatContext &context,
340  BasicFormatSpecifier<typename FormatContext::char_type> &&specifier)
341 {
342  using view_type = std::basic_string_view<T>;
343 
344  typename FormatContext::template formatter_type<view_type> formatter(std::move(specifier));
345 
346  view_type view(static_cast<const T *>(value), size);
347  formatter.format(view, context);
348 }
349 
350 //==================================================================================================
351 template <typename FormatContext, typename T>
352 inline void format_standard_value(
353  StandardValue<FormatContext> value,
354  FormatContext &context,
355  BasicFormatSpecifier<typename FormatContext::char_type> &&specifier)
356 {
357  typename FormatContext::template formatter_type<T> formatter(std::move(specifier));
358 
359  if constexpr (fly::FormattablePointer<T>)
360  {
361  if constexpr (std::is_null_pointer_v<T>)
362  {
363  formatter.format(nullptr, context);
364  }
365  else if constexpr (std::is_const_v<T>)
366  {
367  formatter.format(static_cast<T>(value.m_pointer), context);
368  }
369  else
370  {
371  formatter.format(static_cast<T>(const_cast<void *>(value.m_pointer)), context);
372  }
373  }
374  else if constexpr (fly::SameAs<T, float>)
375  {
376  formatter.format(value.m_float, context);
377  }
378  else if constexpr (fly::SameAs<T, double>)
379  {
380  formatter.format(value.m_double, context);
381  }
382  else if constexpr (fly::SameAs<T, long double>)
383  {
384  formatter.format(value.m_long_double, context);
385  }
386  else if constexpr (fly::SameAs<T, bool>)
387  {
388  formatter.format(value.m_bool, context);
389  }
390  else if constexpr (std::is_signed_v<T>)
391  {
392  formatter.format(static_cast<T>(value.m_signed_int), context);
393  }
394  else
395  {
396  formatter.format(static_cast<T>(value.m_unsigned_int), context);
397  }
398 }
399 
400 //==================================================================================================
401 template <typename FormatContext>
403  m_type(Type::Invalid),
404  m_value {.m_monostate {}}
405 {
406 }
407 
408 //==================================================================================================
409 template <typename FormatContext>
410 template <fly::FormattableUserDefined T>
412  m_type(Type::UserDefined),
413  m_value {.m_user_defined {&value, format_user_defined_value<FormatContext, T>}}
414 {
415 }
416 
417 //==================================================================================================
418 template <typename FormatContext>
419 template <fly::FormattableString T>
420 constexpr BasicFormatParameter<FormatContext>::BasicFormatParameter(const T &value) noexcept :
421  m_type(Type::String)
422 {
423  using U = std::remove_cvref_t<T>;
424 
425  using standard_character_type = fly::StandardCharacterType<T>;
426  using standard_view_type = std::basic_string_view<standard_character_type>;
427 
428  standard_view_type view;
429 
430  if constexpr (std::is_array_v<U> || std::is_pointer_v<U>)
431  {
432  view = standard_view_type(value, BasicClassifier<standard_character_type>::size(value));
433  }
434  else
435  {
436  view = standard_view_type(value);
437  }
438 
439  m_value.m_string = {
440  static_cast<const void *>(view.data()),
441  view.size(),
442  format_string_value<FormatContext, standard_character_type>};
443 }
444 
445 //==================================================================================================
446 template <typename FormatContext>
447 template <fly::FormattablePointer T>
449  m_type(Type::Pointer),
450  m_value {.m_standard {.m_pointer = value, .m_format {format_standard_value<FormatContext, T>}}}
451 {
452 }
453 
454 //==================================================================================================
455 template <typename FormatContext>
456 template <fly::FormattableIntegral T>
458 {
459  m_value.m_standard.m_format = format_standard_value<FormatContext, T>;
460 
461  if constexpr (std::is_signed_v<T>)
462  {
463  m_type = Type::SignedInt;
464  m_value.m_standard.m_signed_int = value;
465  }
466  else
467  {
468  m_type = Type::UnsignedInt;
469  m_value.m_standard.m_unsigned_int = value;
470  }
471 }
472 
473 //==================================================================================================
474 template <typename FormatContext>
475 template <fly::FormattableFloatingPoint T>
477 {
478  m_value.m_standard.m_format = format_standard_value<FormatContext, T>;
479 
480  if constexpr (std::is_same_v<T, float>)
481  {
482  m_type = Type::Float;
483  m_value.m_standard.m_float = value;
484  }
485  else if constexpr (std::is_same_v<T, double>)
486  {
487  m_type = Type::Double;
488  m_value.m_standard.m_double = value;
489  }
490  else if constexpr (std::is_same_v<T, long double>)
491  {
492  m_type = Type::LongDouble;
493  m_value.m_standard.m_long_double = value;
494  }
495 }
496 
497 //==================================================================================================
498 template <typename FormatContext>
499 template <fly::FormattableBoolean T>
501  m_type(Type::Bool),
502  m_value {.m_standard {.m_bool = value, .m_format {format_standard_value<FormatContext, T>}}}
503 {
504 }
505 
506 //==================================================================================================
507 template <typename FormatContext>
510  FormatContext &context,
511  BasicFormatSpecifier<char_type> &&specifier) const
512 {
513  switch (m_type)
514  {
515  case Type::UserDefined:
516  m_value.m_user_defined.m_format(
517  m_value.m_user_defined.m_value,
518  parse_context,
519  context,
520  std::move(specifier));
521  break;
522  case Type::String:
523  m_value.m_string.m_format(
524  m_value.m_string.m_value,
525  m_value.m_string.m_size,
526  context,
527  std::move(specifier));
528  break;
529  case Type::Pointer:
530  case Type::SignedInt:
531  case Type::UnsignedInt:
532  case Type::Float:
533  case Type::Double:
534  case Type::LongDouble:
535  case Type::Bool:
536  m_value.m_standard.m_format(m_value.m_standard, context, std::move(specifier));
537  break;
538  default:
539  break;
540  }
541 }
542 
543 //==================================================================================================
544 template <typename FormatContext>
545 template <typename Visitor>
546 constexpr auto BasicFormatParameter<FormatContext>::visit(Visitor &&visitor) const
547 {
548  switch (m_type)
549  {
550  case Type::UserDefined:
551  return visitor(m_value.m_user_defined);
552  case Type::String:
553  return visitor(m_value.m_string);
554  case Type::Pointer:
555  return visitor(m_value.m_standard.m_pointer);
556  case Type::SignedInt:
557  return visitor(m_value.m_standard.m_signed_int);
558  case Type::UnsignedInt:
559  return visitor(m_value.m_standard.m_unsigned_int);
560  case Type::Float:
561  return visitor(m_value.m_standard.m_float);
562  case Type::Double:
563  return visitor(m_value.m_standard.m_double);
564  case Type::LongDouble:
565  return visitor(m_value.m_standard.m_long_double);
566  case Type::Bool:
567  return visitor(m_value.m_standard.m_bool);
568  default:
569  return visitor(m_value.m_monostate);
570  }
571 }
572 
573 //==================================================================================================
574 template <typename FormatContext>
576 {
577  return m_type != Type::Invalid;
578 }
579 
580 //==================================================================================================
581 template <typename FormatContext, typename... ParameterTypes>
583  ParameterTypes &&...parameters) noexcept :
584  m_parameters {FormatParameter {std::forward<ParameterTypes>(parameters)}...}
585 {
586 }
587 
588 } // namespace fly::detail
Definition: string.hpp:51
static constexpr size_type size(T &&value)
Definition: format_parameters.hpp:139
constexpr BasicFormatParameter(T value) noexcept
constexpr auto visit(Visitor &&visitor) const
Definition: format_parameters.hpp:546
constexpr BasicFormatParameter() noexcept
Definition: format_parameters.hpp:402
constexpr void format(BasicFormatParseContext< typename FormatContext::char_type > &parse_context, FormatContext &context, BasicFormatSpecifier< char_type > &&specifier) const
Definition: format_parameters.hpp:508
constexpr BasicFormatParameter(const T &value) noexcept
Definition: format_parameters.hpp:271
constexpr BasicFormatParameters(ParameterTypes &&...parameters) noexcept
Definition: format_parameters.hpp:582
Definition: format_parse_context.hpp:22
Definition: format_specifier.hpp:116
Definition: format_parameters.hpp:21
Definition: format_parameters.hpp:61
Definition: format_parameters.hpp:45
Definition: format_parameters.hpp:29