File indexing completed on 2025-12-16 09:58:24
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MYSQL_IMPL_FORMAT_SQL_HPP
0009 #define BOOST_MYSQL_IMPL_FORMAT_SQL_HPP
0010
0011 #pragma once
0012
0013 #include <boost/mysql/format_sql.hpp>
0014
0015 #include <boost/mysql/detail/format_sql.hpp>
0016
0017 #include <type_traits>
0018
0019 namespace boost {
0020 namespace mysql {
0021 namespace detail {
0022
0023 BOOST_MYSQL_DECL
0024 std::pair<bool, string_view> parse_range_specifiers(const char* spec_begin, const char* spec_end);
0025
0026
0027 template <class T>
0028 bool do_format_custom_formatter(
0029 const void* obj,
0030 const char* spec_begin,
0031 const char* spec_end,
0032 format_context_base& ctx
0033 )
0034 {
0035
0036 using U = typename std::remove_const<T>::type;
0037
0038 formatter<U> fmt;
0039
0040
0041 const char* it = fmt.parse(spec_begin, spec_end);
0042 if (it != spec_end)
0043 {
0044 return false;
0045 }
0046
0047
0048 auto& value = *const_cast<T*>(static_cast<const T*>(obj));
0049
0050
0051 fmt.format(value, ctx);
0052
0053
0054 return true;
0055 }
0056
0057
0058 template <class T>
0059 bool do_format_range(const void* obj, const char* spec_begin, const char* spec_end, format_context_base& ctx)
0060 {
0061
0062 auto res = detail::parse_range_specifiers(spec_begin, spec_end);
0063 if (!res.first)
0064 return false;
0065 auto spec = runtime(res.second);
0066
0067
0068 auto& value = *const_cast<T*>(static_cast<const T*>(obj));
0069
0070
0071 bool is_first = true;
0072 for (auto it = std::begin(value); it != std::end(value); ++it)
0073 {
0074 if (!is_first)
0075 ctx.append_raw(", ");
0076 is_first = false;
0077 ctx.append_value(*it, spec);
0078 }
0079 return true;
0080 }
0081
0082
0083 inline formattable_ref_impl make_formattable_ref_custom(
0084 formattable_ref v,
0085 std::true_type
0086 )
0087 {
0088 return access::get_impl(v);
0089 }
0090
0091
0092 template <class T>
0093 formattable_ref_impl make_formattable_ref_custom(
0094 T&& v,
0095 std::false_type
0096 )
0097 {
0098
0099
0100 static_assert(
0101 has_specialized_formatter<T>(),
0102 "T is not formattable. Please use a formattable type or specialize formatter<T> to make it "
0103 "formattable"
0104 );
0105
0106
0107
0108 return {
0109 formattable_ref_impl::type_t::fn_and_ptr,
0110 formattable_ref_impl::
0111 fn_and_ptr{&v, &do_format_custom_formatter<typename std::remove_reference<T>::type>}
0112 };
0113 }
0114
0115
0116 template <class T>
0117 formattable_ref_impl make_formattable_ref_range(
0118 T&& v,
0119 std::true_type
0120 )
0121 {
0122
0123
0124 return {
0125 formattable_ref_impl::type_t::fn_and_ptr,
0126 formattable_ref_impl::fn_and_ptr{&v, &do_format_range<typename std::remove_reference<T>::type>}
0127 };
0128 }
0129
0130 template <class T>
0131 formattable_ref_impl make_formattable_ref_range(
0132 T&& v,
0133 std::false_type
0134 )
0135 {
0136 return make_formattable_ref_custom(std::forward<T>(v), is_formattable_ref<T>());
0137 }
0138
0139
0140 template <class T>
0141 formattable_ref_impl make_formattable_ref_writable(
0142 const T& v,
0143 std::true_type
0144 )
0145 {
0146
0147 return {
0148 std::is_convertible<T, string_view>::value ? formattable_ref_impl::type_t::field_with_specs
0149 : formattable_ref_impl::type_t::field,
0150 to_field(v)
0151 };
0152 }
0153
0154 template <class T>
0155 formattable_ref_impl make_formattable_ref_writable(
0156 T&& v,
0157 std::false_type
0158 )
0159 {
0160 return make_formattable_ref_range(std::forward<T>(v), is_formattable_range<T>());
0161 }
0162
0163 }
0164 }
0165 }
0166
0167 template <class T>
0168 boost::mysql::detail::formattable_ref_impl boost::mysql::detail::make_formattable_ref(T&& v)
0169 {
0170
0171
0172
0173
0174 return make_formattable_ref_writable(std::forward<T>(v), is_writable_field_ref<T>());
0175 }
0176
0177 template <BOOST_MYSQL_FORMATTABLE... Formattable>
0178 std::string boost::mysql::format_sql(
0179 format_options opts,
0180 constant_string_view format_str,
0181 Formattable&&... args
0182 )
0183 {
0184 std::initializer_list<format_arg> args_il{
0185 {string_view(), std::forward<Formattable>(args)}
0186 ...
0187 };
0188 return format_sql(opts, format_str, args_il);
0189 }
0190
0191 #endif