GEOS
Format.hpp
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2024 TotalEnergies
7  * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
8  * Copyright (c) 2023-2024 Chevron
9  * Copyright (c) 2019- GEOS/GEOSX Contributors
10  * All rights reserved
11  *
12  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
13  * ------------------------------------------------------------------------------------------------------------
14  */
15 
16 #ifndef GEOS_COMMON_FORMAT_HPP_
17 #define GEOS_COMMON_FORMAT_HPP_
18 
19 #include <type_traits>
20 #include <optional>
21 #include <sstream>
22 #include <string>
23 
24 #define GEOS_USE_FMT
25 
26 #ifdef GEOS_USE_FMT
27 #ifndef FMT_HEADER_ONLY
28 #define FMT_HEADER_ONLY
29 #endif
30 // Differentiate between standalone fmt path and umpire's fmt path
31 #include "../include/fmt/core.h"
32 #include "../include/fmt/chrono.h"
33 #include "../include/fmt/ranges.h"
34 #include "../include/fmt/xchar.h"
35 #define GEOS_FMT_NS fmt
36 #endif
37 
38 #ifdef GEOS_USE_FMT
44 template< typename T >
45 struct fmt::formatter< T, std::enable_if_t< std::is_enum< T >::value > >
46 {
53  template< typename ParseContext >
54  constexpr auto parse( ParseContext & ctx )
55  {
56  return ctx.end();
57  }
58 
66  template< typename FormatContext >
67  auto format( const T & value, FormatContext & ctx ) const
68  {
69  return fmt::format_to( ctx.out(), "{}", static_cast< std::underlying_type_t< T > >( value ) );
70  }
71 };
72 #endif
73 
78 #define GEOS_FMT( msg, ... ) GEOS_FMT_NS::format( msg, __VA_ARGS__ )
79 
84 #define GEOS_FMT_RUNTIME( msg, ... ) GEOS_FMT_NS::format( GEOS_FMT_NS::runtime( msg ), __VA_ARGS__ )
85 
93 #define GEOS_FMT_TO( iter, size, msg, ... ) *GEOS_FMT_NS::format_to_n( iter, size - 1, msg, __VA_ARGS__ ).out = '\0'
94 
99 
104 template< typename T >
105 struct GEOS_FMT_NS::formatter< std::optional< T > > : GEOS_FMT_NS::formatter< T >
106 {
113  auto format( std::optional< T > const & opt, format_context & ctx ) const
114  {
115  if( opt )
116  {
117  return GEOS_FMT_NS::formatter< T >::format( *opt, ctx );
118  }
119  return GEOS_FMT_NS::format_to( ctx.out(), "" );
120  }
121 };
122 
124 
125 // The following workaround is needed to fix compilation with NVCC on some PowerPC machines.
126 // The issue causes the following assertion error message:
127 // "Cannot format an argument. To make type T formattable provide a formatter<T> specialization"
128 // The standard definition of the has_const_formatter check of fmt fails due to a compiler bug, see the issue below:
129 // https://github.com/fmtlib/fmt/issues/2746
130 // The workaround was originally implemented in fmt:
131 // https://github.com/fmtlib/fmt/commit/70de324aa801eaf52e94c402d526a3849797c620
132 // but later removed:
133 // https://github.com/fmtlib/fmt/commit/466e0650ec2d153d255a40ec230eb77d7f1c3334
134 // This workaround bypasse the check for a const formatter whenever the foramt context GEOS_FMT_NS::format_context is used
135 #ifdef GEOS_USE_FMT_CONST_FORMATTER_WORKAROUND
136 template< >
137 constexpr auto GEOS_FMT_NS::detail::has_const_formatter_impl< GEOS_FMT_NS::format_context >( ... ) -> bool
138 {
139  return true;
140 }
141 #endif // End of the workaround for fmt compilation issues
142 
146 template< class T >
147 static constexpr bool has_formatter_v = fmt::is_formattable< fmt::remove_cvref_t< T > >::value;
148 
149 namespace geos::format
150 {
151 
152 template< class T >
153 inline std::string toStringForFmt( T const & v )
154 {
155  if constexpr ( std::is_convertible_v< T, std::string > )
156  {
157  return std::string( v );
158  }
159  else if constexpr ( std::is_convertible_v< T, std::string_view > )
160  {
161  return std::string( std::string_view( v ) );
162  }
163  else
164  {
165  std::ostringstream os;
166  os << v; // requires operator<<(ostream&, T)
167  return os.str();
168  }
169 }
170 
171 } // namespace geos::format
172 
173 #endif //GEOS_COMMON_FORMAT_HPP_
std::string string
String type.
Definition: DataTypes.hpp:90
std::string_view string_view
String type.
Definition: DataTypes.hpp:93
auto format(std::optional< T > const &opt, format_context &ctx) const
Format the std::optional<T> to a string.
Definition: Format.hpp:113
auto format(const T &value, FormatContext &ctx) const
Formatter for the fmtlib formatting library.
Definition: Format.hpp:67
constexpr auto parse(ParseContext &ctx)
Parser for the fmtlib formatting library.
Definition: Format.hpp:54