File indexing completed on 2025-01-30 09:35:11
0001
0002
0003
0004
0005 #ifndef BOOST_CONVERT_PRINTF_HPP
0006 #define BOOST_CONVERT_PRINTF_HPP
0007
0008 #include <boost/convert/base.hpp>
0009 #include <boost/make_default.hpp>
0010 #include <boost/mpl/vector.hpp>
0011 #include <boost/mpl/find.hpp>
0012 #include <string>
0013 #include <cstdio>
0014
0015 namespace boost { namespace cnv { struct printf; }}
0016
0017 struct boost::cnv::printf : boost::cnv::cnvbase<boost::cnv::printf>
0018 {
0019 using this_type = boost::cnv::printf;
0020 using base_type = boost::cnv::cnvbase<this_type>;
0021
0022 using base_type::operator();
0023
0024 template<typename in_type>
0025 cnv::range<char*>
0026 to_str(in_type value_in, char* buf) const
0027 {
0028 char_cptr fmt = printf_format(pos<in_type>());
0029 int num_chars = snprintf(buf, bufsize_, fmt, precision_, value_in);
0030 bool success = num_chars < bufsize_;
0031
0032 return cnv::range<char*>(buf, success ? (buf + num_chars) : buf);
0033 }
0034 template<typename string_type, typename out_type>
0035 void
0036 str_to(cnv::range<string_type> range, optional<out_type>& result_out) const
0037 {
0038 out_type result = boost::make_default<out_type>();
0039 char_cptr fmt = sscanf_format(pos<out_type>());
0040 int num_read = sscanf(&*range.begin(), fmt, &result);
0041
0042 if (num_read == 1)
0043 result_out = result;
0044 }
0045
0046 private:
0047
0048 template<typename Type> int pos() const
0049 {
0050
0051
0052 using types = boost::mpl::vector<
0053 double, float, int, unsigned int, short int,
0054 unsigned short int, long int, unsigned long int>;
0055 using found = typename boost::mpl::find<types, Type>::type;
0056 using pos = typename found::pos;
0057
0058 return pos::value;
0059 }
0060 char_cptr printf_format(int type_pos) const
0061 {
0062 char_cptr BOOST_CONSTEXPR_OR_CONST d_fmt[3][8] =
0063 {
0064 { "%.*f", "%.*f", "%.*d", "%.*u", "%.*hd", "%.*hu", "%.*ld", "%.*lu" },
0065 { "%.*e", "%.*e", "%.*d", "%.*u", "%.*hd", "%.*hu", "%.*ld", "%.*lu" },
0066 { "%.*a", "%.*a", "%.*d", "%.*u", "%.*hd", "%.*hu", "%.*ld", "%.*lu" }
0067 };
0068 char_cptr BOOST_CONSTEXPR_OR_CONST x_fmt[3][8] =
0069 {
0070 { "%.*f", "%.*f", "%.*x", "%.*x", "%.*hx", "%.*hx", "%.*lx", "%.*lx" },
0071 { "%.*e", "%.*e", "%.*x", "%.*x", "%.*hx", "%.*hx", "%.*lx", "%.*lx" },
0072 { "%.*a", "%.*a", "%.*x", "%.*x", "%.*hx", "%.*hx", "%.*lx", "%.*lx" }
0073 };
0074 char_cptr BOOST_CONSTEXPR_OR_CONST o_fmt[3][8] =
0075 {
0076 { "%.*f", "%.*f", "%.*o", "%.*o", "%.*ho", "%.*ho", "%.*lo", "%.*lo" },
0077 { "%.*e", "%.*e", "%.*o", "%.*o", "%.*ho", "%.*ho", "%.*lo", "%.*lo" },
0078 { "%.*a", "%.*a", "%.*o", "%.*o", "%.*ho", "%.*ho", "%.*lo", "%.*lo" }
0079 };
0080 return base_ == base::dec ? d_fmt[int(notation_)][type_pos]
0081 : base_ == base::hex ? x_fmt[int(notation_)][type_pos]
0082 : base_ == base::oct ? o_fmt[int(notation_)][type_pos]
0083 : (BOOST_ASSERT(0), nullptr);
0084 }
0085 char_cptr sscanf_format(int type_pos) const
0086 {
0087 char_cptr BOOST_CONSTEXPR_OR_CONST d_fmt[3][8] =
0088 {
0089 { "%lf", "%f", "%d", "%u", "%hd", "%hu", "%ld", "%lu" },
0090 { "%le", "%e", "%d", "%u", "%hd", "%hu", "%ld", "%lu" },
0091 { "%la", "%a", "%d", "%u", "%hd", "%hu", "%ld", "%lu" }
0092 };
0093 char_cptr BOOST_CONSTEXPR_OR_CONST x_fmt[3][8] =
0094 {
0095 { "%lf", "%f", "%x", "%x", "%hx", "%hx", "%lx", "%lx" },
0096 { "%le", "%e", "%x", "%x", "%hx", "%hx", "%lx", "%lx" },
0097 { "%la", "%a", "%x", "%x", "%hx", "%hx", "%lx", "%lx" }
0098 };
0099 char_cptr BOOST_CONSTEXPR_OR_CONST o_fmt[3][8] =
0100 {
0101 { "%lf", "%f", "%o", "%o", "%ho", "%ho", "%lo", "%lo" },
0102 { "%le", "%e", "%o", "%o", "%ho", "%ho", "%lo", "%lo" },
0103 { "%la", "%a", "%o", "%o", "%ho", "%ho", "%lo", "%lo" }
0104 };
0105 return base_ == base::dec ? d_fmt[int(notation_)][type_pos]
0106 : base_ == base::hex ? x_fmt[int(notation_)][type_pos]
0107 : base_ == base::oct ? o_fmt[int(notation_)][type_pos]
0108 : (BOOST_ASSERT(0), nullptr);
0109 }
0110 };
0111
0112 #endif