]>
Commit | Line | Data |
---|---|---|
20effc67 | 1 | // Copyright (c) 2009-2020 Vladimir Batov. |
7c673cae FG |
2 | // Use, modification and distribution are subject to the Boost Software License, |
3 | // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. | |
4 | ||
5 | #ifndef BOOST_CONVERT_PRINTF_HPP | |
6 | #define BOOST_CONVERT_PRINTF_HPP | |
7 | ||
8 | #include <boost/convert/base.hpp> | |
9 | #include <boost/make_default.hpp> | |
10 | #include <boost/mpl/vector.hpp> | |
11 | #include <boost/mpl/find.hpp> | |
7c673cae FG |
12 | #include <string> |
13 | #include <cstdio> | |
14 | ||
15 | namespace boost { namespace cnv | |
16 | { | |
17 | struct printf; | |
18 | }} | |
19 | ||
92f5a8d4 | 20 | struct boost::cnv::printf : boost::cnv::cnvbase<boost::cnv::printf> |
7c673cae | 21 | { |
92f5a8d4 TL |
22 | using this_type = boost::cnv::printf; |
23 | using base_type = boost::cnv::cnvbase<this_type>; | |
7c673cae FG |
24 | |
25 | using base_type::operator(); | |
26 | ||
27 | template<typename in_type> | |
28 | cnv::range<char*> | |
29 | to_str(in_type value_in, char* buf) const | |
30 | { | |
31 | char const* fmt = pformat(pos<in_type>()); | |
32 | int const num_chars = snprintf(buf, bufsize_, fmt, precision_, value_in); | |
33 | bool const success = num_chars < bufsize_; | |
34 | ||
35 | return cnv::range<char*>(buf, success ? (buf + num_chars) : buf); | |
36 | } | |
37 | template<typename string_type, typename out_type> | |
38 | void | |
39 | str_to(cnv::range<string_type> range, optional<out_type>& result_out) const | |
40 | { | |
41 | out_type result = boost::make_default<out_type>(); | |
42 | int const num_read = sscanf(&*range.begin(), format(pos<out_type>()), &result); | |
43 | ||
44 | if (num_read == 1) | |
45 | result_out = result; | |
46 | } | |
47 | ||
48 | private: | |
49 | ||
50 | template<typename Type> int pos() const | |
51 | { | |
92f5a8d4 TL |
52 | using managed_types = boost::mpl::vector<double, float, |
53 | int, unsigned int, | |
54 | short int, unsigned short int, | |
55 | long int, unsigned long int>; | |
56 | using type_iterator = typename boost::mpl::find<managed_types, Type>::type; | |
57 | using type_pos = typename type_iterator::pos; | |
7c673cae FG |
58 | |
59 | return type_pos::value; | |
60 | } | |
61 | ||
62 | char const* pformat(int pos) const | |
63 | { | |
92f5a8d4 TL |
64 | static char const* d_fmt[] = { "%.*f", "%.*f", "%.*d", "%.*u", "%.*hd", "%.*hu", "%.*ld", "%.*lu" }; // Must match managed_types |
65 | static char const* x_fmt[] = { "%.*f", "%.*f", "%.*x", "%.*x", "%.*hx", "%.*hx", "%.*lx", "%.*lx" }; // Must match managed_types | |
66 | static char const* o_fmt[] = { "%.*f", "%.*f", "%.*o", "%.*o", "%.*ho", "%.*ho", "%.*lo", "%.*lo" }; // Must match managed_types | |
67 | char const* fmt = base_ == boost::cnv::base::dec ? d_fmt[pos] | |
68 | : base_ == boost::cnv::base::hex ? x_fmt[pos] | |
69 | : base_ == boost::cnv::base::oct ? o_fmt[pos] | |
70 | : (BOOST_ASSERT(0), nullptr); | |
71 | return fmt; | |
7c673cae FG |
72 | } |
73 | char const* format(int pos) const | |
74 | { | |
92f5a8d4 TL |
75 | static char const* d_fmt[] = { "%f", "%f", "%d", "%u", "%hd", "%hu", "%ld", "%lu" }; // Must match managed_types |
76 | static char const* x_fmt[] = { "%f", "%f", "%x", "%x", "%hx", "%hx", "%lx", "%lx" }; // Must match managed_types | |
77 | static char const* o_fmt[] = { "%f", "%f", "%o", "%o", "%ho", "%ho", "%lo", "%lo" }; // Must match managed_types | |
78 | char const* fmt = base_ == boost::cnv::base::dec ? d_fmt[pos] | |
79 | : base_ == boost::cnv::base::hex ? x_fmt[pos] | |
80 | : base_ == boost::cnv::base::oct ? o_fmt[pos] | |
81 | : (BOOST_ASSERT(0), nullptr); | |
82 | return fmt; | |
7c673cae FG |
83 | } |
84 | }; | |
85 | ||
86 | #endif // BOOST_CONVERT_PRINTF_HPP |