stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
// Copyright (c) 2009-2016 Vladimir Batov.
|
||||
// Use, modification and distribution are subject to the Boost Software License,
|
||||
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
|
||||
|
||||
#ifndef BOOST_CONVERT_CONVERTER_BASE_HPP
|
||||
#define BOOST_CONVERT_CONVERTER_BASE_HPP
|
||||
|
||||
#include <boost/convert/parameters.hpp>
|
||||
#include <boost/convert/detail/is_string.hpp>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
|
||||
namespace boost { namespace cnv
|
||||
{
|
||||
namespace ARG = boost::cnv::parameter;
|
||||
|
||||
template<typename> struct cnvbase;
|
||||
}}
|
||||
|
||||
#define BOOST_CNV_TO_STRING \
|
||||
template<typename string_type> \
|
||||
typename boost::enable_if<cnv::is_string<string_type>, void>::type \
|
||||
operator()
|
||||
|
||||
#define BOOST_CNV_STRING_TO \
|
||||
template<typename string_type> \
|
||||
typename boost::enable_if<cnv::is_string<string_type>, void>::type \
|
||||
operator()
|
||||
|
||||
#define BOOST_CNV_PARAM(param_name, param_type) \
|
||||
derived_type& operator()(boost::parameter::aux::tag<ARG::type::param_name, param_type>::type const& arg)
|
||||
|
||||
template<typename derived_type>
|
||||
struct boost::cnv::cnvbase
|
||||
{
|
||||
using this_type = cnvbase;
|
||||
using int_type = int;
|
||||
using uint_type = unsigned int;
|
||||
using lint_type = long int;
|
||||
using ulint_type = unsigned long int;
|
||||
using sint_type = short int;
|
||||
using usint_type = unsigned short int;
|
||||
using llint_type = long long int;
|
||||
using ullint_type = unsigned long long int;
|
||||
using flt_type = float;
|
||||
using dbl_type = double;
|
||||
using ldbl_type = long double;
|
||||
|
||||
// Integration of user-types via operator>>()
|
||||
template<typename type_in, typename type_out>
|
||||
void
|
||||
operator()(type_in const& in, boost::optional<type_out>& out) const
|
||||
{
|
||||
in >> out;
|
||||
}
|
||||
|
||||
// Basic type to string
|
||||
BOOST_CNV_TO_STRING ( int_type v, optional<string_type>& r) const { to_str_(v, r); }
|
||||
BOOST_CNV_TO_STRING ( uint_type v, optional<string_type>& r) const { to_str_(v, r); }
|
||||
BOOST_CNV_TO_STRING ( lint_type v, optional<string_type>& r) const { to_str_(v, r); }
|
||||
BOOST_CNV_TO_STRING ( llint_type v, optional<string_type>& r) const { to_str_(v, r); }
|
||||
BOOST_CNV_TO_STRING ( ulint_type v, optional<string_type>& r) const { to_str_(v, r); }
|
||||
BOOST_CNV_TO_STRING (ullint_type v, optional<string_type>& r) const { to_str_(v, r); }
|
||||
BOOST_CNV_TO_STRING ( sint_type v, optional<string_type>& r) const { to_str_(v, r); }
|
||||
BOOST_CNV_TO_STRING ( usint_type v, optional<string_type>& r) const { to_str_(v, r); }
|
||||
BOOST_CNV_TO_STRING ( flt_type v, optional<string_type>& r) const { to_str_(v, r); }
|
||||
BOOST_CNV_TO_STRING ( dbl_type v, optional<string_type>& r) const { to_str_(v, r); }
|
||||
BOOST_CNV_TO_STRING ( ldbl_type v, optional<string_type>& r) const { to_str_(v, r); }
|
||||
// String to basic type
|
||||
BOOST_CNV_STRING_TO (string_type const& s, optional< int_type>& r) const { str_to_(s, r); }
|
||||
BOOST_CNV_STRING_TO (string_type const& s, optional< uint_type>& r) const { str_to_(s, r); }
|
||||
BOOST_CNV_STRING_TO (string_type const& s, optional< lint_type>& r) const { str_to_(s, r); }
|
||||
BOOST_CNV_STRING_TO (string_type const& s, optional< llint_type>& r) const { str_to_(s, r); }
|
||||
BOOST_CNV_STRING_TO (string_type const& s, optional< ulint_type>& r) const { str_to_(s, r); }
|
||||
BOOST_CNV_STRING_TO (string_type const& s, optional<ullint_type>& r) const { str_to_(s, r); }
|
||||
BOOST_CNV_STRING_TO (string_type const& s, optional< sint_type>& r) const { str_to_(s, r); }
|
||||
BOOST_CNV_STRING_TO (string_type const& s, optional< usint_type>& r) const { str_to_(s, r); }
|
||||
BOOST_CNV_STRING_TO (string_type const& s, optional< flt_type>& r) const { str_to_(s, r); }
|
||||
BOOST_CNV_STRING_TO (string_type const& s, optional< dbl_type>& r) const { str_to_(s, r); }
|
||||
BOOST_CNV_STRING_TO (string_type const& s, optional< ldbl_type>& r) const { str_to_(s, r); }
|
||||
// Formatters
|
||||
// BOOST_CNV_PARAM (locale, std::locale const) { locale_ = arg[ARG:: locale]; return dncast(); }
|
||||
BOOST_CNV_PARAM (base, base::type const) { base_ = arg[ARG:: base]; return dncast(); }
|
||||
BOOST_CNV_PARAM (adjust, adjust::type const) { adjust_ = arg[ARG:: adjust]; return dncast(); }
|
||||
BOOST_CNV_PARAM (precision, int const) { precision_ = arg[ARG::precision]; return dncast(); }
|
||||
BOOST_CNV_PARAM (precision, int) { precision_ = arg[ARG::precision]; return dncast(); }
|
||||
BOOST_CNV_PARAM (uppercase, bool const) { uppercase_ = arg[ARG::uppercase]; return dncast(); }
|
||||
BOOST_CNV_PARAM (skipws, bool const) { skipws_ = arg[ARG:: skipws]; return dncast(); }
|
||||
BOOST_CNV_PARAM (width, int const) { width_ = arg[ARG:: width]; return dncast(); }
|
||||
BOOST_CNV_PARAM (fill, char const) { fill_ = arg[ARG:: fill]; return dncast(); }
|
||||
|
||||
protected:
|
||||
|
||||
cnvbase()
|
||||
:
|
||||
base_ (10),
|
||||
skipws_ (false),
|
||||
precision_ (0),
|
||||
uppercase_ (false),
|
||||
width_ (0),
|
||||
fill_ (' '),
|
||||
adjust_ (boost::cnv::adjust::right)
|
||||
{}
|
||||
|
||||
template<typename string_type, typename out_type>
|
||||
void
|
||||
str_to_(string_type const& str, optional<out_type>& result_out) const
|
||||
{
|
||||
using range_type = cnv::range<string_type const>;
|
||||
using char_type = typename range_type::value_type;
|
||||
|
||||
range_type range (str);
|
||||
auto is_space = [](char_type ch)
|
||||
{
|
||||
return std::isspace(static_cast<unsigned char>(ch));
|
||||
};
|
||||
if (skipws_)
|
||||
for (; !range.empty() && is_space(*range.begin()); ++range);
|
||||
|
||||
if (range.empty()) return;
|
||||
if (is_space(*range.begin())) return;
|
||||
|
||||
dncast().str_to(range, result_out);
|
||||
}
|
||||
template<typename in_type, typename string_type>
|
||||
void
|
||||
to_str_(in_type value_in, optional<string_type>& result_out) const
|
||||
{
|
||||
using range_type = cnv::range<string_type>;
|
||||
using char_type = typename range_type::value_type;
|
||||
|
||||
char_type buf[bufsize_];
|
||||
cnv::range<char_type*> range = dncast().to_str(value_in, buf);
|
||||
char_type* beg = range.begin();
|
||||
char_type* end = range.end();
|
||||
|
||||
if (beg < end)
|
||||
format_(buf, beg, end), result_out = string_type(beg, end);
|
||||
}
|
||||
|
||||
template<typename char_type>
|
||||
void
|
||||
format_(char_type* buf, char_type*& beg, char_type*& end) const
|
||||
{
|
||||
if (uppercase_)
|
||||
for (char_type* p = beg; p < end; ++p) *p = std::toupper(*p);
|
||||
|
||||
if (width_)
|
||||
{
|
||||
int num_fillers = (std::max)(0, int(width_ - (end - beg)));
|
||||
int num_left = adjust_ == boost::cnv::adjust::left ? 0
|
||||
: adjust_ == boost::cnv::adjust::right ? num_fillers
|
||||
: (num_fillers / 2);
|
||||
int num_right = num_fillers - num_left;
|
||||
int str_size = end - beg;
|
||||
bool move = (beg < buf + num_left) // No room for left fillers
|
||||
|| (buf + bufsize_ < end + num_right); // No room for right fillers
|
||||
if (move)
|
||||
{
|
||||
std::memmove(buf + num_left, beg, str_size * sizeof(char_type));
|
||||
beg = buf + num_left;
|
||||
end = beg + str_size;
|
||||
}
|
||||
for (int k = 0; k < num_left; *(--beg) = fill_, ++k);
|
||||
for (int k = 0; k < num_right; *(end++) = fill_, ++k);
|
||||
}
|
||||
}
|
||||
|
||||
derived_type const& dncast () const { return *static_cast<derived_type const*>(this); }
|
||||
derived_type& dncast () { return *static_cast<derived_type*>(this); }
|
||||
|
||||
// ULONG_MAX(8 bytes) = 18446744073709551615 (20(10) or 32(2) characters)
|
||||
// double (8 bytes) max is 316 chars
|
||||
static int const bufsize_ = 512;
|
||||
int base_;
|
||||
bool skipws_;
|
||||
int precision_;
|
||||
bool uppercase_;
|
||||
int width_;
|
||||
int fill_;
|
||||
adjust::type adjust_;
|
||||
// std::locale locale_;
|
||||
};
|
||||
|
||||
#undef BOOST_CNV_TO_STRING
|
||||
#undef BOOST_CNV_STRING_TO
|
||||
#undef BOOST_CNV_PARAM
|
||||
|
||||
#endif // BOOST_CONVERT_CONVERTER_BASE_HPP
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2009-2016 Vladimir Batov.
|
||||
// Use, modification and distribution are subject to the Boost Software License,
|
||||
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
|
||||
|
||||
#ifndef BOOST_PARAMETER_EXT_PRIVATE_HPP
|
||||
#define BOOST_PARAMETER_EXT_PRIVATE_HPP
|
||||
|
||||
#include <boost/parameter/keyword.hpp>
|
||||
|
||||
// A Boost.Parameter extension by Andrey Semashev.
|
||||
// This should really go to Boost.Parameter in the end.
|
||||
|
||||
namespace boost { namespace parameter {
|
||||
|
||||
// The metafunction, given the type of the arguments pack and the keyword tag,
|
||||
// returns the corresponding parameter type
|
||||
template< typename ArgsT, typename KeywordTagT >
|
||||
struct parameter_type
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template< typename ArgT, typename KeywordTagT >
|
||||
struct parameter_type<aux::tagged_argument<KeywordTagT, ArgT>, KeywordTagT>
|
||||
{
|
||||
typedef typename aux::tagged_argument< KeywordTagT, ArgT >::value_type type;
|
||||
};
|
||||
|
||||
template< typename KeywordTagT1, typename ArgT, typename KeywordTagT2 >
|
||||
struct parameter_type< aux::tagged_argument< KeywordTagT1, ArgT >, KeywordTagT2 >
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template< typename ArgT, typename TailT, typename KeywordTagT >
|
||||
struct parameter_type<
|
||||
aux::arg_list<
|
||||
aux::tagged_argument< KeywordTagT, ArgT >,
|
||||
TailT
|
||||
>,
|
||||
KeywordTagT
|
||||
>
|
||||
{
|
||||
typedef typename aux::tagged_argument< KeywordTagT, ArgT >::value_type type;
|
||||
};
|
||||
|
||||
template< typename KeywordTagT1, typename ArgT, typename TailT, typename KeywordTagT2 >
|
||||
struct parameter_type<
|
||||
aux::arg_list<
|
||||
aux::tagged_argument< KeywordTagT1, ArgT >,
|
||||
TailT
|
||||
>,
|
||||
KeywordTagT2
|
||||
> :
|
||||
public parameter_type< TailT, KeywordTagT2 >
|
||||
{
|
||||
};
|
||||
|
||||
}} // boost::parameter
|
||||
|
||||
#endif // BOOST_PARAMETER_EXT_PRIVATE_HPP
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2009-2016 Vladimir Batov.
|
||||
// Use, modification and distribution are subject to the Boost Software License,
|
||||
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
|
||||
|
||||
#ifndef BOOST_CONVERT_DETAIL_IS_CHAR_HPP
|
||||
#define BOOST_CONVERT_DETAIL_IS_CHAR_HPP
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
|
||||
namespace boost { namespace cnv
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename T> struct is_char : mpl::false_ {};
|
||||
template<> struct is_char<char> : mpl:: true_ {};
|
||||
template<> struct is_char<wchar_t> : mpl:: true_ {};
|
||||
}
|
||||
template <typename T> struct is_char : detail::is_char<typename remove_const<T>::type> {};
|
||||
}}
|
||||
|
||||
#endif // BOOST_CONVERT_DETAIL_IS_CHAR_HPP
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2009-2016 Vladimir Batov.
|
||||
// Use, modification and distribution are subject to the Boost Software License,
|
||||
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
|
||||
|
||||
#ifndef BOOST_CONVERT_FORWARD_HPP
|
||||
#define BOOST_CONVERT_FORWARD_HPP
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
//MSVC++ 7.0 _MSC_VER == 1300
|
||||
//MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio 2003)
|
||||
//MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
|
||||
//MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
|
||||
//MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
|
||||
//MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
|
||||
//MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
|
||||
//MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
|
||||
//MSVC++ 15.0 _MSC_VER == 1910 (Visual Studio 2017)
|
||||
|
||||
# pragma warning(disable: 4244)
|
||||
# pragma warning(disable: 4224)
|
||||
# pragma warning(disable: 4996)
|
||||
# pragma warning(disable: 4180) // qualifier applied to function type has no meaning
|
||||
# pragma warning(disable: 4100) // unreferenced formal parameter
|
||||
# pragma warning(disable: 4146) // unary minus operator applied to unsigned type
|
||||
|
||||
#if _MSC_VER < 1900 /* MSVC-14 defines real snprintf()... just about time! */
|
||||
# define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/version.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#undef BOOST_CONVERT_CXX11
|
||||
#else
|
||||
#define BOOST_CONVERT_CXX11
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_INTEL) && (BOOST_INTEL <= 1200) /* Intel 12.0 and lower have broken SFINAE */
|
||||
#error "Boost.Convert is not supported on this platform due to broken SFINAE."
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1800) /* MSVC-11 and lower have broken SFINAE */
|
||||
//# error "Boost.Convert is not supported on this platform due to broken SFINAE."
|
||||
# define BOOST_CONVERT_MSVC_SFINAE_BROKEN
|
||||
#endif
|
||||
|
||||
#endif // BOOST_CONVERT_FORWARD_HPP
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) 2009-2016 Vladimir Batov.
|
||||
// Use, modification and distribution are subject to the Boost Software License,
|
||||
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
|
||||
|
||||
#ifndef BOOST_CONVERT_HAS_MEMBER_HPP
|
||||
#define BOOST_CONVERT_HAS_MEMBER_HPP
|
||||
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/type_traits/detail/yes_no_type.hpp>
|
||||
|
||||
// This macro allows to check if a type has a member named "__member_name__"...
|
||||
// ... regardless of the signature. If takes advantage of the following behavior related to
|
||||
// function resolution. Say, both, foo and base, declare a method with the same name "func":
|
||||
//
|
||||
// struct foo { int func (int, int) { return 0; } };
|
||||
// struct base { void func () {} };
|
||||
// struct mixin : public foo, public base {};
|
||||
//
|
||||
// Now, if we inherit from both -- foo and base -- classes, then the following calls will fail
|
||||
// mixin_ptr(0)->func();
|
||||
// mixin_ptr(0)->func(5, 5);
|
||||
// with the error message (gcc): request for member func is ambiguous
|
||||
// regardless if we provide any arguments or not even though one might expect that
|
||||
// arg-based signature resolution might kick in. The only way to deploy those methods is:
|
||||
//
|
||||
// mixin_ptr(0)->foo::func();
|
||||
// mixin_ptr(0)->base::func(5, 5);
|
||||
//
|
||||
// C2. The actual signature of __member_name__ is not taken into account. If
|
||||
// __T__::__member_name__(any-signature) exists, then the introduced base::__member_name__
|
||||
// will cause mixin->__member_name__() call to fail to compile (due to ambiguity).
|
||||
// C3. &U::__member_name__ (a.k.a. &mixin::__member_name__)
|
||||
// has the type of func_type only if __T__::__member_name__ does not exist.
|
||||
// If __T__::member_name does exist, then mixin::__member_name__ is ambiguous
|
||||
// and "yes_type test (...)" kicks in instead.
|
||||
// C4. Need to find some unique/ugly name so that it does not clash if this macro is
|
||||
// used inside some other template class;
|
||||
|
||||
#define BOOST_DECLARE_HAS_MEMBER(__trait_name__, __member_name__) \
|
||||
\
|
||||
template <typename __boost_has_member_T__> /*C4*/ \
|
||||
class __trait_name__ \
|
||||
{ \
|
||||
typedef typename ::boost::remove_const<__boost_has_member_T__>::type check_type; \
|
||||
typedef ::boost::type_traits::yes_type yes_type; \
|
||||
typedef ::boost::type_traits:: no_type no_type; \
|
||||
\
|
||||
struct base { void __member_name__(/*C2*/) {}}; \
|
||||
struct mixin : public base, public check_type {}; \
|
||||
\
|
||||
template <void (base::*)()> struct aux {}; \
|
||||
\
|
||||
template <typename U> static no_type test(aux<&U::__member_name__>*); /*C3*/ \
|
||||
template <typename U> static yes_type test(...); \
|
||||
\
|
||||
public: \
|
||||
\
|
||||
BOOST_STATIC_CONSTANT(bool, value = (sizeof(yes_type) == sizeof(test<mixin>(0)))); \
|
||||
}
|
||||
|
||||
#endif // BOOST_CONVERT_HAS_MEMBER_HPP
|
||||
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) 2009-2016 Vladimir Batov.
|
||||
// Use, modification and distribution are subject to the Boost Software License,
|
||||
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
|
||||
|
||||
#ifndef BOOST_CONVERT_IS_CALLABLE_HPP
|
||||
#define BOOST_CONVERT_IS_CALLABLE_HPP
|
||||
|
||||
#include <boost/convert/detail/has_member.hpp>
|
||||
|
||||
namespace boost { namespace cnv { namespace detail
|
||||
{
|
||||
typedef ::boost::type_traits::yes_type yes_type;
|
||||
typedef ::boost::type_traits:: no_type no_type;
|
||||
|
||||
struct not_found {};
|
||||
struct void_return_substitute {};
|
||||
|
||||
// The overloaded comma operator only kicks in for U != void essentially short-circuiting
|
||||
// itself ineffective. Otherwise, when U=void, the standard op,() kicks in and returns
|
||||
// 'void_return_substitute'.
|
||||
template<typename U> U const& operator, (U const&, void_return_substitute);
|
||||
template<typename U> U& operator, (U&, void_return_substitute);
|
||||
|
||||
template <typename src, typename dst> struct match_const { typedef dst type; };
|
||||
template <typename src, typename dst> struct match_const<src const, dst> { typedef dst const type; };
|
||||
|
||||
template<typename T, typename return_type>
|
||||
struct redirect
|
||||
{
|
||||
static no_type test (...);
|
||||
static yes_type test (return_type);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct redirect<T, void>
|
||||
{
|
||||
static yes_type test (...);
|
||||
static no_type test (not_found);
|
||||
};
|
||||
}}}
|
||||
|
||||
// No-args case needs to be implemented differently and has not been implemented yet.
|
||||
// template <typename R>
|
||||
// struct check<true, R ()>
|
||||
|
||||
// C1. Need to find some unique/ugly names so that they do not clash if this macro is
|
||||
// used inside some other template class;
|
||||
// C2. Body of the function is not actually used anywhere.
|
||||
// However, Intel C++ compiler treats it as an error. So, we provide the body.
|
||||
|
||||
#define BOOST_DECLARE_IS_CALLABLE(__trait_name__, __member_name__) \
|
||||
\
|
||||
template <typename __boost_is_callable_T__, typename __boost_is_callable_signature__> \
|
||||
class __trait_name__ \
|
||||
{ \
|
||||
typedef __boost_is_callable_T__ class_type; /*C1*/ \
|
||||
typedef __boost_is_callable_signature__ signature; /*C1*/ \
|
||||
typedef boost::cnv::detail::not_found not_found; \
|
||||
\
|
||||
BOOST_DECLARE_HAS_MEMBER(has_member, __member_name__); \
|
||||
\
|
||||
struct mixin : public class_type \
|
||||
{ \
|
||||
using class_type::__member_name__; \
|
||||
not_found __member_name__(...) const { return not_found(); /*C2*/} \
|
||||
}; \
|
||||
\
|
||||
typedef typename boost::cnv::detail::match_const<class_type, mixin>::type* mixin_ptr; \
|
||||
\
|
||||
template <bool has, typename F> struct check { static bool const value = false; }; \
|
||||
\
|
||||
template <typename Arg1, typename R> \
|
||||
struct check<true, R (Arg1)> \
|
||||
{ \
|
||||
typedef typename boost::decay<Arg1>::type* a1; \
|
||||
\
|
||||
static bool const value = sizeof(boost::type_traits::yes_type) \
|
||||
== sizeof(boost::cnv::detail::redirect<class_type, R>::test( \
|
||||
(mixin_ptr(0)->__member_name__(*a1(0)), \
|
||||
boost::cnv::detail::void_return_substitute()))); \
|
||||
}; \
|
||||
template <typename Arg1, typename Arg2, typename R> \
|
||||
struct check<true, R (Arg1, Arg2)> \
|
||||
{ \
|
||||
typedef typename boost::decay<Arg1>::type* a1; \
|
||||
typedef typename boost::decay<Arg2>::type* a2; \
|
||||
\
|
||||
static bool const value = sizeof(boost::type_traits::yes_type) \
|
||||
== sizeof(boost::cnv::detail::redirect<class_type, R>::test( \
|
||||
(mixin_ptr(0)->__member_name__(*a1(0), *a2(0)), \
|
||||
boost::cnv::detail::void_return_substitute()))); \
|
||||
}; \
|
||||
\
|
||||
public: \
|
||||
\
|
||||
/* Check the existence of __member_name__ first, then the signature. */ \
|
||||
static bool const value = check<has_member<class_type>::value, signature>::value; \
|
||||
}
|
||||
|
||||
#endif // BOOST_CONVERT_IS_CALLABLE_HPP
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2009-2016 Vladimir Batov.
|
||||
// Use, modification and distribution are subject to the Boost Software License,
|
||||
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
|
||||
|
||||
#ifndef BOOST_CONVERT_IS_CONVERTER_HPP
|
||||
#define BOOST_CONVERT_IS_CONVERTER_HPP
|
||||
|
||||
#include <boost/convert/detail/forward.hpp>
|
||||
#include <boost/convert/detail/is_callable.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
namespace boost { namespace cnv
|
||||
{
|
||||
template<typename, typename, typename, typename =void>
|
||||
struct is_cnv { BOOST_STATIC_CONSTANT(bool, value = false); };
|
||||
|
||||
template<typename Class, typename TypeIn, typename TypeOut>
|
||||
struct is_cnv<Class, TypeIn, TypeOut, typename enable_if<is_class<Class>, void>::type>
|
||||
{
|
||||
typedef typename ::boost::unwrap_reference<Class>::type class_type;
|
||||
typedef void signature_type(TypeIn const&, optional<TypeOut>&);
|
||||
|
||||
BOOST_DECLARE_IS_CALLABLE(is_callable, operator());
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, value = (is_callable<class_type, signature_type>::value));
|
||||
};
|
||||
|
||||
template<typename Function, typename TypeIn, typename TypeOut>
|
||||
struct is_cnv<Function, TypeIn, TypeOut,
|
||||
typename enable_if_c<is_function<Function>::value && function_types::function_arity<Function>::value == 2,
|
||||
void>::type>
|
||||
{
|
||||
typedef TypeIn in_type;
|
||||
typedef optional<TypeOut>& out_type;
|
||||
typedef typename function_traits<Function>::arg1_type func_in_type;
|
||||
typedef typename function_traits<Function>::arg2_type func_out_type;
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, in_good = (is_convertible<in_type, func_in_type>::value));
|
||||
BOOST_STATIC_CONSTANT(bool, out_good = (is_same<out_type, func_out_type>::value));
|
||||
BOOST_STATIC_CONSTANT(bool, value = (in_good && out_good));
|
||||
};
|
||||
}}
|
||||
|
||||
#endif // BOOST_CONVERT_IS_CONVERTER_HPP
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) 2009-2016 Vladimir Batov.
|
||||
// Use, modification and distribution are subject to the Boost Software License,
|
||||
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
|
||||
|
||||
#ifndef BOOST_CONVERT_IS_FUNCTION_HPP
|
||||
#define BOOST_CONVERT_IS_FUNCTION_HPP
|
||||
|
||||
#include <boost/convert/detail/forward.hpp>
|
||||
#include <boost/convert/detail/has_member.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/function_types/is_function_pointer.hpp>
|
||||
#include <boost/function_types/function_arity.hpp>
|
||||
#include <boost/function_types/result_type.hpp>
|
||||
|
||||
namespace boost { namespace cnv
|
||||
{
|
||||
typedef ::boost::type_traits::yes_type yes_type;
|
||||
typedef ::boost::type_traits:: no_type no_type;
|
||||
|
||||
template <bool has_operator, typename Functor, typename TypeOut>
|
||||
struct check_functor { BOOST_STATIC_CONSTANT(bool, value = false); };
|
||||
|
||||
template<typename Func, typename TypeOut, class Enable =void>
|
||||
struct is_fun { BOOST_STATIC_CONSTANT(bool, value = false); };
|
||||
|
||||
template <typename Functor, typename TypeOut>
|
||||
struct check_functor<true, Functor, TypeOut>
|
||||
{
|
||||
static yes_type test (TypeOut const&);
|
||||
static no_type test (...);
|
||||
|
||||
static const bool value = sizeof(yes_type) == sizeof(test(((Functor*) 0)->operator()()));
|
||||
};
|
||||
|
||||
template<typename Functor, typename TypeOut>
|
||||
struct is_fun<Functor, TypeOut,
|
||||
typename enable_if_c<is_class<Functor>::value && !is_convertible<Functor, TypeOut>::value, void>::type>
|
||||
{
|
||||
BOOST_DECLARE_HAS_MEMBER(has_funop, operator());
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, value = (check_functor<has_funop<Functor>::value, Functor, TypeOut>::value));
|
||||
};
|
||||
|
||||
template<typename Function, typename TypeOut>
|
||||
struct is_fun<Function, TypeOut,
|
||||
typename enable_if_c<
|
||||
function_types::is_function_pointer<Function>::value &&
|
||||
function_types::function_arity<Function>::value == 0 &&
|
||||
!is_same<Function, TypeOut>::value,
|
||||
void>::type>
|
||||
{
|
||||
typedef TypeOut out_type;
|
||||
typedef typename function_types::result_type<Function>::type func_out_type;
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, value = (is_convertible<func_out_type, out_type>::value));
|
||||
};
|
||||
}}
|
||||
|
||||
#endif // BOOST_CONVERT_IS_FUNCTION_HPP
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2009-2016 Vladimir Batov.
|
||||
// Use, modification and distribution are subject to the Boost Software License,
|
||||
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
|
||||
|
||||
#ifndef BOOST_CONVERT_DETAIL_IS_STRING_HPP
|
||||
#define BOOST_CONVERT_DETAIL_IS_STRING_HPP
|
||||
|
||||
#include <boost/convert/detail/range.hpp>
|
||||
|
||||
namespace boost { namespace cnv
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename T, bool is_range_class> struct is_string : mpl::false_ {};
|
||||
|
||||
template<typename T> struct is_string<T*, false>
|
||||
{
|
||||
static bool const value = cnv::is_char<T>::value;
|
||||
};
|
||||
template <typename T, std::size_t N> struct is_string<T [N], false>
|
||||
{
|
||||
static bool const value = cnv::is_char<T>::value;
|
||||
};
|
||||
template<typename T> struct is_string<T, /*is_range_class=*/true>
|
||||
{
|
||||
static bool const value = cnv::is_char<typename T::value_type>::value;
|
||||
};
|
||||
}
|
||||
template<typename T> struct is_string : detail::is_string<
|
||||
typename remove_const<T>::type,
|
||||
boost::is_class<T>::value && boost::cnv::is_range<T>::value> {};
|
||||
}}
|
||||
|
||||
#endif // BOOST_CONVERT_DETAIL_IS_STRING_HPP
|
||||
@@ -0,0 +1,117 @@
|
||||
// Copyright (c) 2009-2016 Vladimir Batov.
|
||||
// Use, modification and distribution are subject to the Boost Software License,
|
||||
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
|
||||
|
||||
#ifndef BOOST_CONVERT_DETAIL_RANGE_HPP
|
||||
#define BOOST_CONVERT_DETAIL_RANGE_HPP
|
||||
|
||||
#include <boost/convert/detail/has_member.hpp>
|
||||
#include <boost/convert/detail/char.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/range/iterator.hpp>
|
||||
|
||||
namespace boost { namespace cnv
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename T, bool is_class> struct is_range : mpl::false_ {};
|
||||
|
||||
template<typename T> struct is_range<T, /*is_class=*/true>
|
||||
{
|
||||
BOOST_DECLARE_HAS_MEMBER(has_begin, begin);
|
||||
BOOST_DECLARE_HAS_MEMBER( has_end, end);
|
||||
|
||||
static bool const value = has_begin<T>::value && has_end<T>::value;
|
||||
};
|
||||
}
|
||||
template<typename T> struct is_range : detail::is_range<typename remove_const<T>::type, boost::is_class<T>::value> {};
|
||||
template<typename T, typename enable =void> struct range;
|
||||
template<typename T, typename enable =void> struct iterator;
|
||||
|
||||
template<typename T>
|
||||
struct iterator<T, typename enable_if<is_range<T> >::type>
|
||||
{
|
||||
typedef typename boost::range_iterator<T>::type type;
|
||||
typedef typename boost::range_iterator<T const>::type const_type;
|
||||
typedef typename boost::iterator_value<type>::type value_type;
|
||||
};
|
||||
template<typename T>
|
||||
struct iterator<T*, void>
|
||||
{
|
||||
typedef typename remove_const<T>::type value_type;
|
||||
typedef T* type;
|
||||
typedef value_type const* const_type;
|
||||
};
|
||||
template<typename T>
|
||||
struct range_base
|
||||
{
|
||||
typedef typename cnv::iterator<T>::value_type value_type;
|
||||
typedef typename cnv::iterator<T>::type iterator;
|
||||
typedef typename cnv::iterator<T>::const_type const_iterator;
|
||||
typedef const_iterator sentry_type;
|
||||
|
||||
iterator begin () { return begin_; }
|
||||
const_iterator begin () const { return begin_; }
|
||||
void operator++ () { ++begin_; }
|
||||
// void operator-- () { --end_; }
|
||||
|
||||
protected:
|
||||
|
||||
range_base (iterator b, iterator e) : begin_(b), end_(e) {}
|
||||
|
||||
iterator begin_;
|
||||
iterator mutable end_;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct range<T, typename enable_if<is_range<T> >::type> : public range_base<T>
|
||||
{
|
||||
typedef range this_type;
|
||||
typedef range_base<T> base_type;
|
||||
typedef typename base_type::iterator iterator;
|
||||
typedef typename base_type::const_iterator const_iterator;
|
||||
typedef const_iterator sentry_type;
|
||||
|
||||
range (T& r) : base_type(r.begin(), r.end()) {}
|
||||
|
||||
iterator end () { return base_type::end_; }
|
||||
const_iterator end () const { return base_type::end_; }
|
||||
sentry_type sentry () const { return base_type::end_; }
|
||||
bool empty () const { return base_type::begin_ == base_type::end_; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct range<T*, typename enable_if<cnv::is_char<T> >::type> : public range_base<T*>
|
||||
{
|
||||
typedef range this_type;
|
||||
typedef range_base<T*> base_type;
|
||||
typedef typename remove_const<T>::type value_type;
|
||||
typedef T* iterator;
|
||||
typedef value_type const* const_iterator;
|
||||
|
||||
struct sentry_type
|
||||
{
|
||||
friend bool operator!=(iterator it, sentry_type) { return !!*it; }
|
||||
};
|
||||
|
||||
range (iterator b, iterator e =0) : base_type(b, e) {}
|
||||
|
||||
iterator end () { return base_type::end_ ? base_type::end_ : (base_type::end_ = base_type::begin_ + size()); }
|
||||
const_iterator end () const { return base_type::end_ ? base_type::end_ : (base_type::end_ = base_type::begin_ + size()); }
|
||||
sentry_type sentry () const { return sentry_type(); }
|
||||
std::size_t size () const { return std::char_traits<value_type>::length(base_type::begin_); }
|
||||
bool empty () const { return !*base_type::begin_; }
|
||||
};
|
||||
template<typename T>
|
||||
struct range<T* const, void> : public range<T*>
|
||||
{
|
||||
range (T* b, T* e =0) : range<T*>(b, e) {}
|
||||
};
|
||||
template <typename T, std::size_t N>
|
||||
struct range<T [N], void> : public range<T*>
|
||||
{
|
||||
range (T* b, T* e =0) : range<T*>(b, e) {}
|
||||
};
|
||||
}}
|
||||
|
||||
#endif // BOOST_CONVERT_DETAIL_RANGE_HPP
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2009-2016 Vladimir Batov.
|
||||
// Use, modification and distribution are subject to the Boost Software License,
|
||||
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
|
||||
|
||||
#ifndef BOOST_CONVERT_LEXICAL_CAST_HPP
|
||||
#define BOOST_CONVERT_LEXICAL_CAST_HPP
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
namespace boost { namespace cnv
|
||||
{
|
||||
struct lexical_cast;
|
||||
}}
|
||||
|
||||
/// @brief boost::lexical_cast-based converter
|
||||
/// @details The purpose of the converter is to
|
||||
/// * Make use of the boost::lexical_cast functionality and performance that many people have become
|
||||
/// accustomed to and comfortable with;
|
||||
/// * Demonstrate how existing independent conversion/transformation-related facilities might be
|
||||
// incorporated in to the Boost.Convert framework.
|
||||
///
|
||||
/// The converter can easily replace boost::lexical_cast, adding flexibility and convenience.
|
||||
|
||||
struct boost::cnv::lexical_cast
|
||||
{
|
||||
template<typename TypeOut, typename TypeIn>
|
||||
void
|
||||
operator()(TypeIn const& value_in, boost::optional<TypeOut>& result_out) const
|
||||
{
|
||||
try
|
||||
{
|
||||
result_out = boost::lexical_cast<TypeOut>(value_in);
|
||||
}
|
||||
catch (boost::bad_lexical_cast const&)
|
||||
{
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BOOST_CONVERT_LEXICAL_CAST_HPP
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2009-2016 Vladimir Batov.
|
||||
// Use, modification and distribution are subject to the Boost Software License,
|
||||
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
|
||||
|
||||
#ifndef BOOST_CONVERT_PARAMETERS_HPP
|
||||
#define BOOST_CONVERT_PARAMETERS_HPP
|
||||
|
||||
#include <boost/convert/detail/boost_parameter_ext.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace cnv
|
||||
{
|
||||
struct adjust { enum type { left, right, center };};
|
||||
struct base { enum type { bin =2, dec =10, hex =16, oct =8 };};
|
||||
struct notation { enum type { fixed, scientific };};
|
||||
|
||||
namespace parameter
|
||||
{
|
||||
BOOST_PARAMETER_KEYWORD(type, adjust)
|
||||
BOOST_PARAMETER_KEYWORD(type, base)
|
||||
BOOST_PARAMETER_KEYWORD(type, fill)
|
||||
BOOST_PARAMETER_KEYWORD(type, locale)
|
||||
BOOST_PARAMETER_KEYWORD(type, notation)
|
||||
BOOST_PARAMETER_KEYWORD(type, precision)
|
||||
BOOST_PARAMETER_KEYWORD(type, skipws)
|
||||
BOOST_PARAMETER_KEYWORD(type, uppercase)
|
||||
BOOST_PARAMETER_KEYWORD(type, width)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BOOST_CONVERT_PARAMETERS_HPP
|
||||
@@ -0,0 +1,89 @@
|
||||
// Copyright (c) 2009-2016 Vladimir Batov.
|
||||
// Use, modification and distribution are subject to the Boost Software License,
|
||||
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
|
||||
|
||||
#ifndef BOOST_CONVERT_PRINTF_HPP
|
||||
#define BOOST_CONVERT_PRINTF_HPP
|
||||
|
||||
#include <boost/convert/base.hpp>
|
||||
#include <boost/make_default.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/find.hpp>
|
||||
#include <boost/range/as_literal.hpp>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
namespace boost { namespace cnv
|
||||
{
|
||||
struct printf;
|
||||
}}
|
||||
|
||||
struct boost::cnv::printf : public boost::cnv::cnvbase<boost::cnv::printf>
|
||||
{
|
||||
typedef boost::cnv::printf this_type;
|
||||
typedef boost::cnv::cnvbase<this_type> base_type;
|
||||
|
||||
using base_type::operator();
|
||||
|
||||
template<typename in_type>
|
||||
cnv::range<char*>
|
||||
to_str(in_type value_in, char* buf) const
|
||||
{
|
||||
char const* fmt = pformat(pos<in_type>());
|
||||
int const num_chars = snprintf(buf, bufsize_, fmt, precision_, value_in);
|
||||
bool const success = num_chars < bufsize_;
|
||||
|
||||
return cnv::range<char*>(buf, success ? (buf + num_chars) : buf);
|
||||
}
|
||||
template<typename string_type, typename out_type>
|
||||
void
|
||||
str_to(cnv::range<string_type> range, optional<out_type>& result_out) const
|
||||
{
|
||||
out_type result = boost::make_default<out_type>();
|
||||
int const num_read = sscanf(&*range.begin(), format(pos<out_type>()), &result);
|
||||
|
||||
if (num_read == 1)
|
||||
result_out = result;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template<typename Type> int pos() const
|
||||
{
|
||||
typedef boost::mpl::vector<double, float,
|
||||
int, unsigned int,
|
||||
short int, unsigned short int,
|
||||
long int, unsigned long int
|
||||
> managed_types;
|
||||
|
||||
typedef typename boost::mpl::find<managed_types, Type>::type type_iterator;
|
||||
typedef typename type_iterator::pos type_pos;
|
||||
|
||||
return type_pos::value;
|
||||
}
|
||||
|
||||
char const* pformat(int pos) const
|
||||
{
|
||||
static char const* d_format[] = { "%.*f", "%.*f", "%.*d", "%.*u", "%.*hd", "%.*hu", "%.*ld", "%.*lu" }; // Must match managed_types
|
||||
static char const* x_format[] = { "%.*f", "%.*f", "%.*x", "%.*x", "%.*hx", "%.*hx", "%.*lx", "%.*lx" }; // Must match managed_types
|
||||
static char const* o_format[] = { "%.*f", "%.*f", "%.*o", "%.*o", "%.*ho", "%.*ho", "%.*lo", "%.*lo" }; // Must match managed_types
|
||||
char const* format = base_ == 10 ? d_format[pos]
|
||||
: base_ == 16 ? x_format[pos]
|
||||
: base_ == 8 ? o_format[pos]
|
||||
: (BOOST_ASSERT(0), (char const*) 0);
|
||||
return format;
|
||||
}
|
||||
char const* format(int pos) const
|
||||
{
|
||||
static char const* d_format[] = { "%f", "%f", "%d", "%u", "%hd", "%hu", "%ld", "%lu" }; // Must match managed_types
|
||||
static char const* x_format[] = { "%f", "%f", "%x", "%x", "%hx", "%hx", "%lx", "%lx" }; // Must match managed_types
|
||||
static char const* o_format[] = { "%f", "%f", "%o", "%o", "%ho", "%ho", "%lo", "%lo" }; // Must match managed_types
|
||||
char const* format = base_ == 10 ? d_format[pos]
|
||||
: base_ == 16 ? x_format[pos]
|
||||
: base_ == 8 ? o_format[pos]
|
||||
: (BOOST_ASSERT(0), (char const*) 0);
|
||||
return format;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BOOST_CONVERT_PRINTF_HPP
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2009-2016 Vladimir Batov.
|
||||
// Use, modification and distribution are subject to the Boost Software License,
|
||||
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
|
||||
|
||||
#ifndef BOOST_CONVERT_SPIRIT_BASED_CONVERTER_HPP
|
||||
#define BOOST_CONVERT_SPIRIT_BASED_CONVERTER_HPP
|
||||
|
||||
#include <boost/convert/base.hpp>
|
||||
#include <boost/convert/detail/forward.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/karma.hpp>
|
||||
|
||||
namespace boost { namespace cnv
|
||||
{
|
||||
struct spirit;
|
||||
}}
|
||||
|
||||
struct boost::cnv::spirit : public boost::cnv::cnvbase<boost::cnv::spirit>
|
||||
{
|
||||
typedef boost::cnv::spirit this_type;
|
||||
typedef boost::cnv::cnvbase<this_type> base_type;
|
||||
|
||||
using base_type::operator();
|
||||
|
||||
template<typename string_type, typename out_type>
|
||||
void
|
||||
str_to(cnv::range<string_type> range, optional<out_type>& result_out) const
|
||||
{
|
||||
typedef typename cnv::range<string_type>::iterator iterator;
|
||||
typedef typename boost::spirit::traits::create_parser<out_type>::type parser;
|
||||
|
||||
iterator beg = range.begin();
|
||||
iterator end = range.end();
|
||||
out_type result;
|
||||
|
||||
if (boost::spirit::qi::parse(beg, end, parser(), result))
|
||||
if (beg == end) // ensure the whole string has been parsed
|
||||
result_out = result;
|
||||
}
|
||||
template<typename in_type, typename char_type>
|
||||
cnv::range<char_type*>
|
||||
to_str(in_type value_in, char_type* beg) const
|
||||
{
|
||||
typedef typename boost::spirit::traits::create_generator<in_type>::type generator;
|
||||
|
||||
char_type* end = beg;
|
||||
bool good = boost::spirit::karma::generate(end, generator(), value_in);
|
||||
|
||||
return cnv::range<char_type*>(beg, good ? end : beg);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BOOST_CONVERT_SPIRIT_BASED_CONVERTER_HPP
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
// Copyright (c) 2009-2016 Vladimir Batov.
|
||||
// Use, modification and distribution are subject to the Boost Software License,
|
||||
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
|
||||
|
||||
#ifndef BOOST_CONVERT_STRINGSTREAM_BASED_CONVERTER_HPP
|
||||
#define BOOST_CONVERT_STRINGSTREAM_BASED_CONVERTER_HPP
|
||||
|
||||
#include <boost/convert/parameters.hpp>
|
||||
#include <boost/convert/detail/is_string.hpp>
|
||||
#include <boost/make_default.hpp>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#define BOOST_CNV_STRING_ENABLE \
|
||||
template<typename string_type, typename type> \
|
||||
typename boost::enable_if<cnv::is_string<string_type>, void>::type \
|
||||
operator()
|
||||
|
||||
#define BOOST_CNV_PARAM(PARAM_NAME, PARAM_TYPE) \
|
||||
this_type& \
|
||||
operator()(boost::parameter::aux::tag<boost::cnv::parameter::type::PARAM_NAME, PARAM_TYPE>::type const& arg)
|
||||
|
||||
namespace boost { namespace cnv
|
||||
{
|
||||
template<class Char> struct basic_stream;
|
||||
|
||||
typedef boost::cnv::basic_stream<char> cstream;
|
||||
typedef boost::cnv::basic_stream<wchar_t> wstream;
|
||||
}}
|
||||
|
||||
template<class Char>
|
||||
struct boost::cnv::basic_stream : boost::noncopyable
|
||||
{
|
||||
// C01. In string-to-type conversions the "string" must be a CONTIGUOUS ARRAY of
|
||||
// characters because "ibuffer_type" uses/relies on that (it deals with char_type*).
|
||||
// C02. Use the provided "string_in" as the input (read-from) buffer and, consequently,
|
||||
// avoid the overhead associated with stream_.str(string_in) --
|
||||
// copying of the content into internal buffer.
|
||||
// C03. The "strbuf.gptr() != strbuf.egptr()" check replaces "istream.eof() != true"
|
||||
// which for some reason does not work when we try converting the "true" string
|
||||
// to "bool" with std::boolalpha set. Seems that istream state gets unsynced compared
|
||||
// to the actual underlying buffer.
|
||||
|
||||
typedef Char char_type;
|
||||
typedef boost::cnv::basic_stream<char_type> this_type;
|
||||
typedef std::basic_stringstream<char_type> stream_type;
|
||||
typedef std::basic_istream<char_type> istream_type;
|
||||
typedef std::basic_streambuf<char_type> buffer_type;
|
||||
typedef std::basic_string<char_type> stdstr_type;
|
||||
typedef std::ios_base& (*manipulator_type)(std::ios_base&);
|
||||
|
||||
struct ibuffer_type : public buffer_type
|
||||
{
|
||||
using buffer_type::eback;
|
||||
using buffer_type::gptr;
|
||||
using buffer_type::egptr;
|
||||
|
||||
ibuffer_type(char_type const* beg, std::size_t sz) //C01
|
||||
{
|
||||
char_type* b = const_cast<char_type*>(beg);
|
||||
|
||||
buffer_type::setg(b, b, b + sz);
|
||||
}
|
||||
};
|
||||
struct obuffer_type : public buffer_type
|
||||
{
|
||||
using buffer_type::pbase;
|
||||
using buffer_type::pptr;
|
||||
using buffer_type::epptr;
|
||||
};
|
||||
|
||||
basic_stream() : stream_(std::ios_base::in | std::ios_base::out) {}
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
basic_stream(this_type&& other) : stream_(std::move(other.stream_)) {}
|
||||
#endif
|
||||
|
||||
BOOST_CNV_STRING_ENABLE(type const& v, optional<string_type>& s) const { to_str(v, s); }
|
||||
BOOST_CNV_STRING_ENABLE(string_type const& s, optional<type>& r) const { str_to(cnv::range<string_type const>(s), r); }
|
||||
// Resolve ambiguity of string-to-string
|
||||
template<typename type> void operator()( char_type const* s, optional<type>& r) const { str_to(cnv::range< char_type const*>(s), r); }
|
||||
template<typename type> void operator()(stdstr_type const& s, optional<type>& r) const { str_to(cnv::range<stdstr_type const>(s), r); }
|
||||
|
||||
// Formatters
|
||||
template<typename manipulator>
|
||||
this_type& operator() (manipulator m) { return (stream_ << m, *this); }
|
||||
this_type& operator() (manipulator_type m) { return (m(stream_), *this); }
|
||||
this_type& operator() (std::locale const& l) { return (stream_.imbue(l), *this); }
|
||||
|
||||
BOOST_CNV_PARAM(locale, std::locale const) { return (stream_.imbue(arg[cnv::parameter::locale]), *this); }
|
||||
BOOST_CNV_PARAM(precision, int const) { return (stream_.precision(arg[cnv::parameter::precision]), *this); }
|
||||
BOOST_CNV_PARAM(precision, int) { return (stream_.precision(arg[cnv::parameter::precision]), *this); }
|
||||
BOOST_CNV_PARAM(width, int const) { return (stream_.width(arg[cnv::parameter::width]), *this); }
|
||||
BOOST_CNV_PARAM(fill, char const) { return (stream_.fill(arg[cnv::parameter::fill]), *this); }
|
||||
BOOST_CNV_PARAM(uppercase, bool const)
|
||||
{
|
||||
bool uppercase = arg[cnv::parameter::uppercase];
|
||||
uppercase ? (void) stream_.setf(std::ios::uppercase) : stream_.unsetf(std::ios::uppercase);
|
||||
return *this;
|
||||
}
|
||||
BOOST_CNV_PARAM(skipws, bool const)
|
||||
{
|
||||
bool skipws = arg[cnv::parameter::skipws];
|
||||
skipws ? (void) stream_.setf(std::ios::skipws) : stream_.unsetf(std::ios::skipws);
|
||||
return *this;
|
||||
}
|
||||
BOOST_CNV_PARAM(adjust, boost::cnv::adjust::type const)
|
||||
{
|
||||
cnv::adjust::type adjust = arg[cnv::parameter::adjust];
|
||||
|
||||
/**/ if (adjust == cnv::adjust:: left) stream_.setf(std::ios::adjustfield, std::ios:: left);
|
||||
else if (adjust == cnv::adjust::right) stream_.setf(std::ios::adjustfield, std::ios::right);
|
||||
else BOOST_ASSERT(!"Not implemented");
|
||||
|
||||
return *this;
|
||||
}
|
||||
BOOST_CNV_PARAM(base, boost::cnv::base::type const)
|
||||
{
|
||||
cnv::base::type base = arg[cnv::parameter::base];
|
||||
|
||||
/**/ if (base == cnv::base::dec) std::dec(stream_);
|
||||
else if (base == cnv::base::hex) std::hex(stream_);
|
||||
else if (base == cnv::base::oct) std::oct(stream_);
|
||||
else BOOST_ASSERT(!"Not implemented");
|
||||
|
||||
return *this;
|
||||
}
|
||||
BOOST_CNV_PARAM(notation, boost::cnv::notation::type const)
|
||||
{
|
||||
cnv::notation::type notation = arg[cnv::parameter::notation];
|
||||
|
||||
/**/ if (notation == cnv::notation:: fixed) std::fixed(stream_);
|
||||
else if (notation == cnv::notation::scientific) std::scientific(stream_);
|
||||
else BOOST_ASSERT(!"Not implemented");
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template<typename string_type, typename out_type> void str_to(cnv::range<string_type>, optional<out_type>&) const;
|
||||
template<typename string_type, typename in_type> void to_str(in_type const&, optional<string_type>&) const;
|
||||
|
||||
mutable stream_type stream_;
|
||||
};
|
||||
|
||||
template<typename char_type>
|
||||
template<typename string_type, typename in_type>
|
||||
inline
|
||||
void
|
||||
boost::cnv::basic_stream<char_type>::to_str(
|
||||
in_type const& value_in,
|
||||
boost::optional<string_type>& string_out) const
|
||||
{
|
||||
stream_.clear(); // Clear the flags
|
||||
stream_.str(stdstr_type()); // Clear/empty the content of the stream
|
||||
|
||||
if (!(stream_ << value_in).fail())
|
||||
{
|
||||
buffer_type* buf = stream_.rdbuf();
|
||||
obuffer_type* obuf = static_cast<obuffer_type*>(buf);
|
||||
char_type const* beg = obuf->pbase();
|
||||
char_type const* end = obuf->pptr();
|
||||
|
||||
string_out = string_type(beg, end); // Instead of stream_.str();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename char_type>
|
||||
template<typename string_type, typename out_type>
|
||||
inline
|
||||
void
|
||||
boost::cnv::basic_stream<char_type>::str_to(
|
||||
boost::cnv::range<string_type> string_in,
|
||||
boost::optional<out_type>& result_out) const
|
||||
{
|
||||
if (string_in.empty ()) return;
|
||||
|
||||
istream_type& istream = stream_;
|
||||
buffer_type* oldbuf = istream.rdbuf();
|
||||
char_type const* beg = &*string_in.begin();
|
||||
std::size_t sz = string_in.end() - string_in.begin();
|
||||
ibuffer_type newbuf (beg, sz); //C02
|
||||
|
||||
istream.rdbuf(&newbuf);
|
||||
istream.clear(); // Clear the flags
|
||||
|
||||
istream >> *(result_out = boost::make_default<out_type>());
|
||||
|
||||
if (istream.fail() || newbuf.gptr() != newbuf.egptr()/*C03*/)
|
||||
result_out = boost::none;
|
||||
|
||||
istream.rdbuf(oldbuf);
|
||||
}
|
||||
|
||||
#undef BOOST_CNV_STRING_ENABLE
|
||||
#undef BOOST_CNV_PARAM
|
||||
|
||||
#endif // BOOST_CONVERT_STRINGSTREAM_BASED_CONVERTER_HPP
|
||||
@@ -0,0 +1,219 @@
|
||||
// Copyright (c) 2009-2016 Vladimir Batov.
|
||||
// Use, modification and distribution are subject to the Boost Software License,
|
||||
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
|
||||
|
||||
#ifndef BOOST_CONVERT_STRTOL_CONVERTER_HPP
|
||||
#define BOOST_CONVERT_STRTOL_CONVERTER_HPP
|
||||
|
||||
#include <boost/convert/base.hpp>
|
||||
#include <boost/type_traits/make_unsigned.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <climits>
|
||||
|
||||
#if __GNUC__ == 4 && __GNUC_MINOR__ <= 2
|
||||
namespace std
|
||||
{
|
||||
using ::strtold; // Tests indicated that gcc-4.2.1 does not have 'std::strtold'
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace boost { namespace cnv
|
||||
{
|
||||
struct strtol;
|
||||
}}
|
||||
|
||||
/// @brief std::strtol-based extended converter
|
||||
/// @details The converter offers a fairly decent overall performance and moderate formatting facilities.
|
||||
|
||||
struct boost::cnv::strtol : public boost::cnv::cnvbase<boost::cnv::strtol>
|
||||
{
|
||||
typedef boost::cnv::strtol this_type;
|
||||
typedef boost::cnv::cnvbase<this_type> base_type;
|
||||
|
||||
using base_type::operator();
|
||||
|
||||
private:
|
||||
|
||||
friend struct boost::cnv::cnvbase<this_type>;
|
||||
|
||||
template<typename string_type> void str_to(cnv::range<string_type> v, optional< int_type>& r) const { str_to_i (v, r); }
|
||||
template<typename string_type> void str_to(cnv::range<string_type> v, optional< sint_type>& r) const { str_to_i (v, r); }
|
||||
template<typename string_type> void str_to(cnv::range<string_type> v, optional< lint_type>& r) const { str_to_i (v, r); }
|
||||
template<typename string_type> void str_to(cnv::range<string_type> v, optional< llint_type>& r) const { str_to_i (v, r); }
|
||||
template<typename string_type> void str_to(cnv::range<string_type> v, optional< uint_type>& r) const { str_to_i (v, r); }
|
||||
template<typename string_type> void str_to(cnv::range<string_type> v, optional< usint_type>& r) const { str_to_i (v, r); }
|
||||
template<typename string_type> void str_to(cnv::range<string_type> v, optional< ulint_type>& r) const { str_to_i (v, r); }
|
||||
template<typename string_type> void str_to(cnv::range<string_type> v, optional<ullint_type>& r) const { str_to_i (v, r); }
|
||||
template<typename string_type> void str_to(cnv::range<string_type> v, optional< flt_type>& r) const { str_to_d (v, r); }
|
||||
template<typename string_type> void str_to(cnv::range<string_type> v, optional< dbl_type>& r) const { str_to_d (v, r); }
|
||||
template<typename string_type> void str_to(cnv::range<string_type> v, optional< ldbl_type>& r) const { str_to_d (v, r); }
|
||||
|
||||
template <typename char_type> cnv::range<char_type*> to_str ( int_type v, char_type* buf) const { return i_to_str(v, buf); }
|
||||
template <typename char_type> cnv::range<char_type*> to_str ( uint_type v, char_type* buf) const { return i_to_str(v, buf); }
|
||||
template <typename char_type> cnv::range<char_type*> to_str ( lint_type v, char_type* buf) const { return i_to_str(v, buf); }
|
||||
template <typename char_type> cnv::range<char_type*> to_str ( ulint_type v, char_type* buf) const { return i_to_str(v, buf); }
|
||||
template <typename char_type> cnv::range<char_type*> to_str ( llint_type v, char_type* buf) const { return i_to_str(v, buf); }
|
||||
template <typename char_type> cnv::range<char_type*> to_str (ullint_type v, char_type* buf) const { return i_to_str(v, buf); }
|
||||
template <typename char_type> cnv::range<char_type*> to_str ( dbl_type v, char_type* buf) const;
|
||||
|
||||
template<typename char_type, typename in_type> cnv::range<char_type*> i_to_str (in_type, char_type*) const;
|
||||
template<typename string_type, typename out_type> void str_to_i (cnv::range<string_type>, optional<out_type>&) const;
|
||||
template<typename string_type, typename out_type> void str_to_d (cnv::range<string_type>, optional<out_type>&) const;
|
||||
|
||||
static double adjust_fraction (double, int);
|
||||
static int get_char (int v) { return (v < 10) ? (v += '0') : (v += 'A' - 10); }
|
||||
};
|
||||
|
||||
template<typename char_type, typename Type>
|
||||
boost::cnv::range<char_type*>
|
||||
boost::cnv::strtol::i_to_str(Type in_value, char_type* buf) const
|
||||
{
|
||||
// C1. Base=10 optimization improves performance 10%
|
||||
|
||||
typedef typename boost::make_unsigned<Type>::type unsigned_type;
|
||||
|
||||
char_type* beg = buf + bufsize_ / 2;
|
||||
char_type* end = beg;
|
||||
bool const is_negative = in_value < 0;
|
||||
unsigned_type value = static_cast<unsigned_type>(is_negative ? -in_value : in_value);
|
||||
|
||||
if (base_ == 10) for (; value; *(--beg) = int(value % 10) + '0', value /= 10); //C1
|
||||
else for (; value; *(--beg) = get_char(value % base_), value /= base_);
|
||||
|
||||
if (beg == end) *(--beg) = '0';
|
||||
if (is_negative) *(--beg) = '-';
|
||||
|
||||
return cnv::range<char_type*>(beg, end);
|
||||
}
|
||||
|
||||
inline
|
||||
double
|
||||
boost::cnv::strtol::adjust_fraction(double fraction, int precision)
|
||||
{
|
||||
// C1. Bring forward the fraction coming right after precision digits.
|
||||
// That is, say, fraction=0.234567, precision=2. Then brought forward=23.4567
|
||||
// C3. INT_MAX(4bytes)=2,147,483,647. So, 10^8 seems appropriate. If not, drop it down to 4.
|
||||
// C4. ::round() returns the integral value that is nearest to x,
|
||||
// with halfway cases rounded away from zero. Therefore,
|
||||
// round( 0.4) = 0
|
||||
// round( 0.5) = 1
|
||||
// round( 0.6) = 1
|
||||
// round(-0.4) = 0
|
||||
// round(-0.5) = -1
|
||||
// round(-0.6) = -1
|
||||
|
||||
int const tens[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000 };
|
||||
|
||||
for (int k = precision / 8; k; --k) fraction *= 100000000; //C3.
|
||||
|
||||
fraction *= tens[precision % 8]; //C1
|
||||
|
||||
// return ::rint(fraction); //C4
|
||||
return boost::math::round(fraction); //C4
|
||||
}
|
||||
|
||||
template <typename char_type>
|
||||
inline
|
||||
boost::cnv::range<char_type*>
|
||||
boost::cnv::strtol::to_str(double value, char_type* buf) const
|
||||
{
|
||||
char_type* beg = buf + bufsize_ / 2;
|
||||
char_type* end = beg;
|
||||
char_type* ipos = end - 1;
|
||||
bool const is_negative = (value < 0) ? (value = -value, true) : false;
|
||||
double ipart = std::floor(value);
|
||||
double fpart = adjust_fraction(value - ipart, precision_);
|
||||
int precision = precision_;
|
||||
int const base = 10;
|
||||
|
||||
for (; 1 <= ipart; ipart /= base)
|
||||
*(--beg) = get_char(int(ipart - std::floor(ipart / base) * base));
|
||||
|
||||
if (beg == end) *(--beg) = '0';
|
||||
if (precision) *(end++) = '.';
|
||||
|
||||
for (char_type* fpos = end += precision; precision; --precision, fpart /= base)
|
||||
*(--fpos) = get_char(int(fpart - std::floor(fpart / base) * base));
|
||||
|
||||
if (1 <= fpart)
|
||||
{
|
||||
for (; beg <= ipos; --ipos)
|
||||
if (*ipos == '9') *ipos = '0';
|
||||
else { ++*ipos; break; }
|
||||
|
||||
if (ipos < beg)
|
||||
*(beg = ipos) = '1';
|
||||
}
|
||||
if (is_negative) *(--beg) = '-';
|
||||
|
||||
return cnv::range<char_type*>(beg, end);
|
||||
}
|
||||
|
||||
template<typename string_type, typename out_type>
|
||||
void
|
||||
boost::cnv::strtol::str_to_i(cnv::range<string_type> range, boost::optional<out_type>& result_out) const
|
||||
{
|
||||
typedef typename boost::make_unsigned<out_type>::type unsigned_type;
|
||||
typedef cnv::range<string_type> range_type;
|
||||
typedef typename range_type::iterator iterator;
|
||||
|
||||
iterator s = range.begin();
|
||||
unsigned int ch = *s;
|
||||
bool const is_negative = ch == '-' ? (ch = *++s, true) : ch == '+' ? (ch = *++s, false) : false;
|
||||
bool const is_unsigned = boost::is_same<out_type, unsigned_type>::value;
|
||||
unsigned int base = 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)() + (is_negative ? 1 : 0);
|
||||
unsigned_type const cutoff = max / base;
|
||||
unsigned int const cutlim = max % base;
|
||||
unsigned_type result = 0;
|
||||
|
||||
for (; s != range.sentry(); ++s)
|
||||
{
|
||||
ch = *s;
|
||||
|
||||
/**/ if (std::isdigit(ch)) ch -= '0';
|
||||
else if (std::isalpha(ch)) ch -= (std::isupper(ch) ? 'A' : 'a') - 10;
|
||||
else return;
|
||||
|
||||
if (base <= ch || cutoff < result || (result == cutoff && cutlim < ch))
|
||||
return;
|
||||
|
||||
result *= base;
|
||||
result += ch;
|
||||
}
|
||||
result_out = is_negative ? -out_type(result) : out_type(result);
|
||||
}
|
||||
|
||||
template<typename string_type, typename out_type>
|
||||
void
|
||||
boost::cnv::strtol::str_to_d(cnv::range<string_type> range, optional<out_type>& result_out) const
|
||||
{
|
||||
// C2. Simply check if the end-of-string was reached -- *cnv_end == 0
|
||||
// instead of traversing once with strlen() to find the end iterator
|
||||
// and then comparing to it as in
|
||||
// char const* end = str + strlen(str); // Unnecessary traversal!
|
||||
// bool const good = ... && cnv_end == end;
|
||||
|
||||
typedef cnv::range<string_type> range_type;
|
||||
typedef typename range_type::value_type ch_type;
|
||||
|
||||
ch_type const* str = &*range.begin(); // Currently only works with 'char'
|
||||
char* cnv_end = 0;
|
||||
ldbl_type result = strtold(str, &cnv_end);
|
||||
bool good = result != -HUGE_VALL && result != HUGE_VALL && *cnv_end == 0/*C2*/;
|
||||
out_type max = (std::numeric_limits<out_type>::max)();
|
||||
|
||||
if (good && -max <= result && result <= max)
|
||||
result_out = out_type(result);
|
||||
}
|
||||
|
||||
#endif // BOOST_CONVERT_STRTOL_CONVERTER_HPP
|
||||
Reference in New Issue
Block a user