File indexing completed on 2025-04-09 08:28:01
0001
0002
0003
0004
0005
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
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
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
0071
0072 template <class T>
0073 struct is_formattable_range<
0074 T,
0075 typename std::enable_if<
0076
0077 std::is_convertible<decltype(std::begin(std::declval<T&>()) != std::end(std::declval<T&>())), bool>::
0078 value &&
0079
0080
0081
0082 is_formattable_range_elm_type<decltype(*std::begin(std::declval<T&>()))>()
0083
0084
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
0098
0099 template <class T>
0100 concept formattable =
0101
0102 is_writable_field_ref<T>::value ||
0103
0104 has_specialized_formatter<T>() ||
0105
0106 is_formattable_range<T>::value ||
0107
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
0126
0127
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
0157 template <class T>
0158 formattable_ref_impl make_formattable_ref(T&& v);
0159
0160 }
0161 }
0162 }
0163
0164 #endif