mirror of
https://github.com/boostorg/convert.git
synced 2026-01-19 04:02:18 +00:00
14APR-09:44 issue #54: added support for notation::hex
This commit is contained in:
@@ -89,7 +89,8 @@ struct boost::cnv::cnvbase
|
||||
BOOST_CNV_STRING_TO (string_type const& s, optional< ldbl_type>& r) const { str_to_(s, r); }
|
||||
|
||||
template<typename argument_pack>
|
||||
derived_type& operator()(argument_pack const& arg)
|
||||
typename std::enable_if<boost::parameter::is_argument_pack<argument_pack>::value, derived_type&>::type
|
||||
operator()(argument_pack const& arg)
|
||||
{
|
||||
BOOST_CNV_PARAM_TRY(base);
|
||||
BOOST_CNV_PARAM_TRY(adjust);
|
||||
@@ -98,6 +99,7 @@ struct boost::cnv::cnvbase
|
||||
BOOST_CNV_PARAM_TRY(skipws);
|
||||
BOOST_CNV_PARAM_TRY(width);
|
||||
BOOST_CNV_PARAM_TRY(fill);
|
||||
BOOST_CNV_PARAM_TRY(notation);
|
||||
// BOOST_CNV_PARAM_TRY(locale);
|
||||
|
||||
return this->dncast();
|
||||
@@ -105,16 +107,7 @@ struct boost::cnv::cnvbase
|
||||
|
||||
protected:
|
||||
|
||||
cnvbase()
|
||||
:
|
||||
skipws_ (false),
|
||||
precision_ (0),
|
||||
uppercase_ (false),
|
||||
width_ (0),
|
||||
fill_ (' '),
|
||||
base_ (boost::cnv::base::dec),
|
||||
adjust_ (boost::cnv::adjust::right)
|
||||
{}
|
||||
cnvbase() = default;
|
||||
|
||||
template<typename string_type, typename out_type>
|
||||
void
|
||||
@@ -185,20 +178,22 @@ struct boost::cnv::cnvbase
|
||||
BOOST_CNV_PARAM_SET(skipws) { skipws_ = arg[cnv::parameter:: skipws]; }
|
||||
BOOST_CNV_PARAM_SET(width) { width_ = arg[cnv::parameter:: width]; }
|
||||
BOOST_CNV_PARAM_SET(fill) { fill_ = arg[cnv::parameter:: fill]; }
|
||||
BOOST_CNV_PARAM_SET(notation) { notation_ = arg[cnv::parameter:: notation]; }
|
||||
// BOOST_CNV_PARAM_SET(locale) { locale_ = arg[cnv::parameter:: locale]; }
|
||||
|
||||
// ULONG_MAX(8 bytes) = 18446744073709551615 (20(10) or 32(2) characters)
|
||||
// double (8 bytes) max is 316 chars
|
||||
static int BOOST_CONSTEXPR_OR_CONST bufsize_ = 512;
|
||||
static int inline BOOST_CONSTEXPR_OR_CONST bufsize_ = 512;
|
||||
|
||||
bool skipws_;
|
||||
int precision_;
|
||||
bool uppercase_;
|
||||
int width_;
|
||||
int fill_;
|
||||
cnv::base base_;
|
||||
cnv::adjust adjust_;
|
||||
// std::locale locale_;
|
||||
bool skipws_ = false;
|
||||
int precision_ = 0;
|
||||
bool uppercase_ = false;
|
||||
int width_ = 0;
|
||||
int fill_ = ' ';
|
||||
cnv::base base_ = boost::cnv::base::dec;
|
||||
cnv::adjust adjust_ = boost::cnv::adjust::right;
|
||||
cnv::notation notation_ = boost::cnv::notation::fixed;
|
||||
// std::locale locale_;
|
||||
};
|
||||
|
||||
#undef BOOST_CNV_TO_STRING
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace boost { namespace cnv
|
||||
using char_type = char;
|
||||
using uchar_type = unsigned char;
|
||||
using wchar_type = wchar_t;
|
||||
using char_cptr = char const*;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace boost { namespace cnv
|
||||
{
|
||||
enum class adjust { left, right, center };
|
||||
enum class base { bin =2, oct =8, dec =10, hex =16 };
|
||||
enum class notation { fixed, scientific };
|
||||
enum class notation { fixed, scientific, hex };
|
||||
|
||||
namespace parameter
|
||||
{
|
||||
|
||||
@@ -21,6 +21,7 @@ struct boost::cnv::printf : boost::cnv::cnvbase<boost::cnv::printf>
|
||||
{
|
||||
using this_type = boost::cnv::printf;
|
||||
using base_type = boost::cnv::cnvbase<this_type>;
|
||||
using fmt_type = char_cptr const*;
|
||||
|
||||
using base_type::operator();
|
||||
|
||||
@@ -58,27 +59,65 @@ struct boost::cnv::printf : boost::cnv::cnvbase<boost::cnv::printf>
|
||||
|
||||
return type_pos::value;
|
||||
}
|
||||
char const* printf_format(int pos) const
|
||||
char_cptr fmt(
|
||||
int pos,
|
||||
fmt_type fxd_d_fmt, fmt_type fxd_x_fmt, fmt_type fxd_o_fmt,
|
||||
fmt_type sci_d_fmt, fmt_type sci_x_fmt, fmt_type sci_o_fmt,
|
||||
fmt_type hex_d_fmt, fmt_type hex_x_fmt, fmt_type hex_o_fmt) const
|
||||
{
|
||||
static char const* d_fmt[] = { "%.*f", "%.*f", "%.*d", "%.*u", "%.*hd", "%.*hu", "%.*ld", "%.*lu" }; // Must match managed_types
|
||||
static char const* x_fmt[] = { "%.*f", "%.*f", "%.*x", "%.*x", "%.*hx", "%.*hx", "%.*lx", "%.*lx" }; // Must match managed_types
|
||||
static char const* o_fmt[] = { "%.*f", "%.*f", "%.*o", "%.*o", "%.*ho", "%.*ho", "%.*lo", "%.*lo" }; // Must match managed_types
|
||||
char const* fmt = base_ == boost::cnv::base::dec ? d_fmt[pos]
|
||||
: base_ == boost::cnv::base::hex ? x_fmt[pos]
|
||||
: base_ == boost::cnv::base::oct ? o_fmt[pos]
|
||||
: (BOOST_ASSERT(0), nullptr);
|
||||
return fmt;
|
||||
if (notation_ == notation::fixed)
|
||||
return base_ == base::dec ? fxd_d_fmt[pos]
|
||||
: base_ == base::hex ? fxd_x_fmt[pos]
|
||||
: base_ == base::oct ? fxd_o_fmt[pos]
|
||||
: (BOOST_ASSERT(0), nullptr);
|
||||
|
||||
if (notation_ == notation::scientific)
|
||||
return base_ == base::dec ? sci_d_fmt[pos]
|
||||
: base_ == base::hex ? sci_x_fmt[pos]
|
||||
: base_ == base::oct ? sci_o_fmt[pos]
|
||||
: (BOOST_ASSERT(0), nullptr);
|
||||
|
||||
if (notation_ == notation::hex)
|
||||
return base_ == base::dec ? hex_d_fmt[pos]
|
||||
: base_ == base::hex ? hex_x_fmt[pos]
|
||||
: base_ == base::oct ? hex_o_fmt[pos]
|
||||
: (BOOST_ASSERT(0), nullptr);
|
||||
|
||||
return (BOOST_ASSERT(0), nullptr);
|
||||
}
|
||||
char const* sscanf_format(int pos) const
|
||||
char_cptr printf_format(int pos) const
|
||||
{
|
||||
static char const* d_fmt[] = { "%lf", "%f", "%d", "%u", "%hd", "%hu", "%ld", "%lu" }; // Must match managed_types
|
||||
static char const* x_fmt[] = { "%lf", "%f", "%x", "%x", "%hx", "%hx", "%lx", "%lx" }; // Must match managed_types
|
||||
static char const* o_fmt[] = { "%lf", "%f", "%o", "%o", "%ho", "%ho", "%lo", "%lo" }; // Must match managed_types
|
||||
char const* fmt = base_ == boost::cnv::base::dec ? d_fmt[pos]
|
||||
: base_ == boost::cnv::base::hex ? x_fmt[pos]
|
||||
: base_ == boost::cnv::base::oct ? o_fmt[pos]
|
||||
: (BOOST_ASSERT(0), nullptr);
|
||||
return fmt;
|
||||
char_cptr constexpr fxd_d_fmt[] = { "%.*f", "%.*f", "%.*d", "%.*u", "%.*hd", "%.*hu", "%.*ld", "%.*lu" }; // Must match managed_types
|
||||
char_cptr constexpr fxd_x_fmt[] = { "%.*f", "%.*f", "%.*x", "%.*x", "%.*hx", "%.*hx", "%.*lx", "%.*lx" }; // Must match managed_types
|
||||
char_cptr constexpr fxd_o_fmt[] = { "%.*f", "%.*f", "%.*o", "%.*o", "%.*ho", "%.*ho", "%.*lo", "%.*lo" }; // Must match managed_types
|
||||
char_cptr constexpr sci_d_fmt[] = { "%.*e", "%.*e", "%.*d", "%.*u", "%.*hd", "%.*hu", "%.*ld", "%.*lu" }; // Must match managed_types
|
||||
char_cptr constexpr sci_x_fmt[] = { "%.*e", "%.*e", "%.*x", "%.*x", "%.*hx", "%.*hx", "%.*lx", "%.*lx" }; // Must match managed_types
|
||||
char_cptr constexpr sci_o_fmt[] = { "%.*e", "%.*e", "%.*o", "%.*o", "%.*ho", "%.*ho", "%.*lo", "%.*lo" }; // Must match managed_types
|
||||
char_cptr constexpr hex_d_fmt[] = { "%.*a", "%.*a", "%.*d", "%.*u", "%.*hd", "%.*hu", "%.*ld", "%.*lu" }; // Must match managed_types
|
||||
char_cptr constexpr hex_x_fmt[] = { "%.*a", "%.*a", "%.*x", "%.*x", "%.*hx", "%.*hx", "%.*lx", "%.*lx" }; // Must match managed_types
|
||||
char_cptr constexpr hex_o_fmt[] = { "%.*a", "%.*a", "%.*o", "%.*o", "%.*ho", "%.*ho", "%.*lo", "%.*lo" }; // Must match managed_types
|
||||
|
||||
return fmt(pos,
|
||||
fxd_d_fmt, fxd_x_fmt, fxd_o_fmt,
|
||||
sci_d_fmt, sci_x_fmt, sci_o_fmt,
|
||||
hex_d_fmt, hex_x_fmt, hex_o_fmt);
|
||||
}
|
||||
char_cptr sscanf_format(int pos) const
|
||||
{
|
||||
char_cptr constexpr fxd_d_fmt[] = { "%lf", "%f", "%d", "%u", "%hd", "%hu", "%ld", "%lu" }; // Must match managed_types
|
||||
char_cptr constexpr fxd_x_fmt[] = { "%lf", "%f", "%x", "%x", "%hx", "%hx", "%lx", "%lx" }; // Must match managed_types
|
||||
char_cptr constexpr fxd_o_fmt[] = { "%lf", "%f", "%o", "%o", "%ho", "%ho", "%lo", "%lo" }; // Must match managed_types
|
||||
char_cptr constexpr sci_d_fmt[] = { "%le", "%e", "%d", "%u", "%hd", "%hu", "%ld", "%lu" }; // Must match managed_types
|
||||
char_cptr constexpr sci_x_fmt[] = { "%le", "%e", "%x", "%x", "%hx", "%hx", "%lx", "%lx" }; // Must match managed_types
|
||||
char_cptr constexpr sci_o_fmt[] = { "%le", "%e", "%o", "%o", "%ho", "%ho", "%lo", "%lo" }; // Must match managed_types
|
||||
char_cptr constexpr hex_d_fmt[] = { "%la", "%a", "%d", "%u", "%hd", "%hu", "%ld", "%lu" }; // Must match managed_types
|
||||
char_cptr constexpr hex_x_fmt[] = { "%la", "%a", "%x", "%x", "%hx", "%hx", "%lx", "%lx" }; // Must match managed_types
|
||||
char_cptr constexpr hex_o_fmt[] = { "%la", "%a", "%o", "%o", "%ho", "%ho", "%lo", "%lo" }; // Must match managed_types
|
||||
|
||||
return fmt(pos,
|
||||
fxd_d_fmt, fxd_x_fmt, fxd_o_fmt,
|
||||
sci_d_fmt, sci_x_fmt, sci_o_fmt,
|
||||
hex_d_fmt, hex_x_fmt, hex_o_fmt);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ struct boost::cnv::spirit : public boost::cnv::cnvbase<boost::cnv::spirit>
|
||||
|
||||
char_type* end = beg;
|
||||
bool good = boost::spirit::karma::generate(end, generator(), value_in);
|
||||
|
||||
|
||||
return cnv::range<char_type*>(beg, good ? end : beg);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -156,8 +156,9 @@ struct boost::cnv::basic_stream
|
||||
{
|
||||
cnv::notation notation = arg[cnv::parameter::notation];
|
||||
|
||||
/**/ if (notation == cnv::notation:: fixed) std::fixed(stream_);
|
||||
/**/ if (notation == cnv::notation:: fixed) std::fixed(stream_);
|
||||
else if (notation == cnv::notation::scientific) std::scientific(stream_);
|
||||
else if (notation == cnv::notation:: hex) std::hexfloat(stream_);
|
||||
else BOOST_ASSERT(!"Not implemented");
|
||||
}
|
||||
|
||||
|
||||
@@ -153,21 +153,21 @@ boost::cnv::strtol::str_to_i(cnv::range<string_type> range, boost::optional<out_
|
||||
using range_type = cnv::range<string_type>;
|
||||
using iterator = typename range_type::iterator;
|
||||
|
||||
iterator s = range.begin();
|
||||
uint_type ch = *s;
|
||||
bool const is_negative = ch == '-' ? (ch = *++s, true) : ch == '+' ? (ch = *++s, false) : false;
|
||||
bool const is_unsigned = std::is_same<out_type, unsigned_type>::value;
|
||||
uint_type base = uint_type(base_);
|
||||
iterator s = range.begin();
|
||||
uint_type ch = *s;
|
||||
bool is_negative = ch == '-' ? (ch = *++s, true) : ch == '+' ? (ch = *++s, false) : false;
|
||||
bool is_unsigned = std::is_same<out_type, unsigned_type>::value;
|
||||
uint_type base = uint_type(base_);
|
||||
|
||||
/**/ if (is_negative && is_unsigned) return;
|
||||
else if ((base == 0 || base == 16) && ch == '0' && (*++s == 'x' || *s == 'X')) ++s, base = 16;
|
||||
else if (base == 0) base = ch == '0' ? (++s, 8) : 10;
|
||||
|
||||
unsigned_type const max = (std::numeric_limits<out_type>::max)();
|
||||
unsigned_type const umax = max + (is_negative ? 1 : 0);
|
||||
unsigned_type const cutoff = umax / base;
|
||||
uint_type const cutlim = umax % base;
|
||||
unsigned_type result = 0;
|
||||
unsigned_type max = (std::numeric_limits<out_type>::max)();
|
||||
unsigned_type umax = max + (is_negative ? 1 : 0);
|
||||
unsigned_type cutoff = umax / base;
|
||||
uint_type cutlim = umax % base;
|
||||
unsigned_type result = 0;
|
||||
|
||||
for (; s != range.sentry(); ++s)
|
||||
{
|
||||
|
||||
@@ -29,8 +29,6 @@ exe convert_test_performance_spirit : performance_spirit.cpp ;
|
||||
run callable.cpp : : : : convert_test_callable ;
|
||||
run fallbacks.cpp : : : : convert_test_fallbacks ;
|
||||
run spirit_converter.cpp : : : : convert_test_spirit_converter ;
|
||||
run stream_converter.cpp : : : : convert_test_stream_converter ;
|
||||
run printf_converter.cpp : : : : convert_test_printf_converter ;
|
||||
run strtol_converter.cpp : : : : convert_test_strtol_converter ;
|
||||
run lcast_converter.cpp : : : : convert_test_lcast_converter ;
|
||||
run encryption.cpp : : : : convert_test_encryption ;
|
||||
@@ -38,4 +36,8 @@ run user_type.cpp : : : : convert_test_user_type ;
|
||||
run str_to_int.cpp : : : : convert_test_str_to_int ;
|
||||
run sfinae.cpp : : : : convert_test_sfinae ;
|
||||
run has_member.cpp : : : : convert_test_has_member ;
|
||||
run printf_converter.cpp :
|
||||
/boost/test/included_unit_test_framework : : : convert_test_printf_converter ;
|
||||
run stream_converter.cpp :
|
||||
/boost/test/included_unit_test_framework : : : convert_test_stream_converter ;
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ int main(int, char const* []) { return 0; }
|
||||
#include <boost/convert/lexical_cast.hpp>
|
||||
|
||||
#include <libs/spirit/workbench/measure.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
|
||||
@@ -11,12 +11,33 @@ int main(int, char const* []) { return 0; }
|
||||
|
||||
#include <boost/convert.hpp>
|
||||
#include <boost/convert/printf.hpp>
|
||||
#include <boost/test/tools/floating_point_comparison.hpp>
|
||||
|
||||
using std::string;
|
||||
using boost::convert;
|
||||
|
||||
namespace cnv = boost::cnv;
|
||||
namespace arg = boost::cnv::parameter;
|
||||
|
||||
static
|
||||
void
|
||||
test_notation()
|
||||
{
|
||||
//[charconv_notation
|
||||
boost::cnv::printf cnv;
|
||||
|
||||
BOOST_TEST( "-3.14159" == convert<string>(-3.14159, cnv(arg::notation = cnv::notation::fixed)(arg::precision = 5)).value());
|
||||
BOOST_TEST( "-3.142e+00" == convert<string>(-3.14159, cnv(arg::notation = cnv::notation::scientific)(arg::precision = 3)).value());
|
||||
BOOST_TEST("-0x1.9220p+1" == convert<string>(-3.14159, cnv(arg::notation = cnv::notation::hex)(arg::precision = 4)).value());
|
||||
|
||||
const auto close = boost::math::fpc::close_at_tolerance<double>(1);
|
||||
|
||||
BOOST_TEST_WITH(-3.14159, convert<double>("-3.14159", cnv(arg::notation = cnv::notation::fixed)).value(), close);
|
||||
BOOST_TEST_WITH(-3.14159, convert<double>("-3.142e+00", cnv(arg::notation = cnv::notation::scientific)).value(), close);
|
||||
BOOST_TEST_WITH(-3.14159, convert<double>("-0x1.9220p+1", cnv(arg::notation = cnv::notation::hex)).value(), close);
|
||||
//]
|
||||
}
|
||||
|
||||
int
|
||||
main(int, char const* [])
|
||||
{
|
||||
@@ -43,6 +64,8 @@ main(int, char const* [])
|
||||
BOOST_TEST(s01 == "12.345600");
|
||||
BOOST_TEST(s02 == "12.346");
|
||||
|
||||
test_notation();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ int main(int, char const* []) { return 0; }
|
||||
|
||||
#include <boost/convert.hpp>
|
||||
#include <boost/convert/stream.hpp>
|
||||
#include <boost/test/tools/floating_point_comparison.hpp>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <stdlib.h>
|
||||
@@ -348,6 +349,28 @@ test_user_str()
|
||||
//]
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
test_notation()
|
||||
{
|
||||
//[charconv_notation
|
||||
boost::cnv::cstream cnv;
|
||||
|
||||
BOOST_TEST( "-3.14159" == convert<string>(-3.14159, cnv(arg::notation = cnv::notation::fixed)(arg::precision = 5)).value());
|
||||
BOOST_TEST("-3.142e+00" == convert<string>(-3.14159, cnv(arg::notation = cnv::notation::scientific)(arg::precision = 3)).value());
|
||||
|
||||
// precision doesn't affect hexfloat
|
||||
BOOST_TEST("-0x1.921f9f01b866ep+1" == convert<string>(-3.14159, cnv(arg::notation = cnv::notation::hex)).value());
|
||||
|
||||
const auto close = boost::math::fpc::close_at_tolerance<double>(1);
|
||||
|
||||
BOOST_TEST_WITH(-3.14159, convert<double>("-3.14159", cnv(arg::notation = cnv::notation::fixed)).value(), close);
|
||||
BOOST_TEST_WITH(-3.14159, convert<double>("-3.142e+00", cnv(arg::notation = cnv::notation::scientific)).value(), close);
|
||||
// not supported due to https://gcc.gnu.org/bugzilla//show_bug.cgi?id=81122
|
||||
// BOOST_TEST_WITH(-3.14159, convert<double>("-0x1.921f9f01b866ep+1", cnv(arg::notation = cnv::notation::hex)).value(), close);
|
||||
//]
|
||||
}
|
||||
|
||||
int
|
||||
main(int, char const* [])
|
||||
{
|
||||
@@ -365,6 +388,7 @@ main(int, char const* [])
|
||||
test_locale();
|
||||
test_dbl_to_str();
|
||||
test_user_str();
|
||||
test_notation();
|
||||
}
|
||||
catch(boost::bad_optional_access const&)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user