Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-09 08:28:01

0001 //
0002 // Copyright (c) 2019-2024 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 
0008 #ifndef BOOST_MYSQL_DETAIL_FORMAT_SQL_HPP
0009 #define BOOST_MYSQL_DETAIL_FORMAT_SQL_HPP
0010 
0011 #include <boost/mysql/field_view.hpp>
0012 #include <boost/mysql/string_view.hpp>
0013 
0014 #include <boost/mysql/detail/writable_field_traits.hpp>
0015 
0016 #include <iterator>
0017 #include <type_traits>
0018 #include <utility>
0019 
0020 #ifdef BOOST_MYSQL_HAS_CONCEPTS
0021 #include <concepts>
0022 #endif
0023 
0024 namespace boost {
0025 namespace mysql {
0026 
0027 // Forward decls
0028 template <class T>
0029 struct formatter;
0030 
0031 class format_context_base;
0032 class formattable_ref;
0033 
0034 namespace detail {
0035 
0036 class format_state;
0037 
0038 struct formatter_is_unspecialized
0039 {
0040 };
0041 
0042 template <class T>
0043 constexpr bool has_specialized_formatter()
0044 {
0045     return !std::is_base_of<formatter_is_unspecialized, formatter<typename std::decay<T>::type>>::value;
0046 }
0047 
0048 template <class T>
0049 struct is_writable_field_ref : is_writable_field<typename std::decay<T>::type>
0050 {
0051 };
0052 
0053 template <class T>
0054 struct is_formattable_ref : std::is_same<typename std::decay<T>::type, formattable_ref>
0055 {
0056 };
0057 
0058 // Is T suitable for being the element type of a formattable range?
0059 template <class T>
0060 constexpr bool is_formattable_range_elm_type()
0061 {
0062     return is_writable_field_ref<T>::value || has_specialized_formatter<T>() || is_formattable_ref<T>::value;
0063 }
0064 
0065 template <class T, class = void>
0066 struct is_formattable_range : std::false_type
0067 {
0068 };
0069 
0070 // Note: T might be a reference.
0071 // Using T& + reference collapsing gets the right semantics for non-const ranges
0072 template <class T>
0073 struct is_formattable_range<
0074     T,
0075     typename std::enable_if<
0076         // std::begin and std::end can be called on it, and we can compare values
0077         std::is_convertible<decltype(std::begin(std::declval<T&>()) != std::end(std::declval<T&>())), bool>::
0078             value &&
0079 
0080         // value_type is either a writable field or a type with a specialized formatter.
0081         // We don't support sequences of sequences out of the box (no known use case)
0082         is_formattable_range_elm_type<decltype(*std::begin(std::declval<T&>()))>()
0083 
0084         // end of conditions
0085         >::type> : std::true_type
0086 {
0087 };
0088 
0089 template <class T>
0090 constexpr bool is_formattable_type()
0091 {
0092     return is_formattable_range_elm_type<T>() || is_formattable_range<T>::value;
0093 }
0094 
0095 #ifdef BOOST_MYSQL_HAS_CONCEPTS
0096 
0097 // If you're getting an error referencing this concept,
0098 // it means that you are attempting to format a type that doesn't support it.
0099 template <class T>
0100 concept formattable =
0101     // This covers basic types and optionals
0102     is_writable_field_ref<T>::value ||
0103     // This covers custom types that specialized boost::mysql::formatter
0104     has_specialized_formatter<T>() ||
0105     // This covers ranges of formattable types
0106     is_formattable_range<T>::value ||
0107     // This covers passing formattable_ref as a format argument
0108     is_formattable_ref<T>::value;
0109 
0110 template <class FormatFn, class Range>
0111 concept format_fn_for_range = requires(const FormatFn& format_fn, Range&& range, format_context_base& ctx) {
0112     { std::begin(range) != std::end(range) } -> std::convertible_to<bool>;
0113     format_fn(*std::begin(range), ctx);
0114     std::end(range);
0115 };
0116 
0117 #define BOOST_MYSQL_FORMATTABLE ::boost::mysql::detail::formattable
0118 
0119 #else
0120 
0121 #define BOOST_MYSQL_FORMATTABLE class
0122 
0123 #endif
0124 
0125 // A type-erased argument passed to format. Built-in types are passed
0126 // directly in the struct (as a field_view), instead of by pointer,
0127 // to reduce the number of do_format instantiations
0128 struct formattable_ref_impl
0129 {
0130     enum class type_t
0131     {
0132         field,
0133         field_with_specs,
0134         fn_and_ptr
0135     };
0136 
0137     struct fn_and_ptr
0138     {
0139         const void* obj;
0140         bool (*format_fn)(const void*, const char*, const char*, format_context_base&);
0141     };
0142 
0143     union data_t
0144     {
0145         field_view fv;
0146         fn_and_ptr custom;
0147 
0148         data_t(field_view fv) noexcept : fv(fv) {}
0149         data_t(fn_and_ptr v) noexcept : custom(v) {}
0150     };
0151 
0152     type_t type;
0153     data_t data;
0154 };
0155 
0156 // Create a type-erased formattable_ref_impl from a formattable value
0157 template <class T>
0158 formattable_ref_impl make_formattable_ref(T&& v);
0159 
0160 }  // namespace detail
0161 }  // namespace mysql
0162 }  // namespace boost
0163 
0164 #endif