diff options
Diffstat (limited to 'boost/convert')
-rw-r--r-- | boost/convert/base.hpp | 56 | ||||
-rw-r--r-- | boost/convert/detail/char.hpp | 28 | ||||
-rw-r--r-- | boost/convert/detail/config.hpp (renamed from boost/convert/detail/forward.hpp) | 45 | ||||
-rw-r--r-- | boost/convert/detail/has_member.hpp | 3 | ||||
-rw-r--r-- | boost/convert/detail/is_converter.hpp | 2 | ||||
-rw-r--r-- | boost/convert/detail/is_fun.hpp | 2 | ||||
-rw-r--r-- | boost/convert/detail/is_string.hpp | 4 | ||||
-rw-r--r-- | boost/convert/detail/range.hpp | 29 | ||||
-rw-r--r-- | boost/convert/spirit.hpp | 2 | ||||
-rw-r--r-- | boost/convert/strtol.hpp | 32 |
10 files changed, 108 insertions, 95 deletions
diff --git a/boost/convert/base.hpp b/boost/convert/base.hpp index 27931194cc..678d99cfc6 100644 --- a/boost/convert/base.hpp +++ b/boost/convert/base.hpp @@ -7,7 +7,6 @@ #include <boost/convert/parameters.hpp> #include <boost/convert/detail/is_string.hpp> -#include <cctype> #include <cstring> namespace boost { namespace cnv @@ -106,19 +105,13 @@ struct boost::cnv::cnvbase 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; + cnv::range<string_type const> range (str); - 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); + for (; !range.empty() && cnv::is_space(*range.begin()); ++range); - if (range.empty()) return; - if (is_space(*range.begin())) return; + if (range.empty()) return; + if (cnv::is_space(*range.begin())) return; dncast().str_to(range, result_out); } @@ -126,35 +119,31 @@ struct boost::cnv::cnvbase 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; + using char_type = typename cnv::range<string_type>::value_type; + using range_type = cnv::range<char_type*>; + using buf_type = char_type[bufsize_]; - 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(); + buf_type buf; + range_type range = dncast().to_str(value_in, buf); + char_type* beg = range.begin(); + char_type* end = range.end(); + int str_size = end - beg; - if (beg < end) - format_(buf, beg, end), result_out = string_type(beg, end); - } + if (str_size <= 0) + return; - 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); + for (char_type* p = beg; p < end; ++p) *p = cnv::to_upper(*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 + int num_fill = (std::max)(0, int(width_ - (end - beg))); + int num_left = adjust_ == cnv::adjust::left ? 0 + : adjust_ == cnv::adjust::right ? num_fill + : (num_fill / 2); + int num_right = num_fill - num_left; + 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)); @@ -164,6 +153,7 @@ struct boost::cnv::cnvbase for (int k = 0; k < num_left; *(--beg) = fill_, ++k); for (int k = 0; k < num_right; *(end++) = fill_, ++k); } + result_out = string_type(beg, end); } derived_type const& dncast () const { return *static_cast<derived_type const*>(this); } diff --git a/boost/convert/detail/char.hpp b/boost/convert/detail/char.hpp index 1d375bad51..a829dc8806 100644 --- a/boost/convert/detail/char.hpp +++ b/boost/convert/detail/char.hpp @@ -5,18 +5,34 @@ #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> +#include <boost/convert/detail/config.hpp> +#include <type_traits> +#include <cctype> +#include <cwctype> namespace boost { namespace cnv { + using char_type = char; + using uchar_type = unsigned char; + using wchar_type = wchar_t; + 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> struct is_char : std::false_type {}; + template<> struct is_char< char_type> : std:: true_type {}; + template<> struct is_char<wchar_type> : std:: true_type {}; } - template <typename T> struct is_char : detail::is_char<typename remove_const<T>::type> {}; + template <typename T> struct is_char : detail::is_char<typename boost::remove_const<T>::type> {}; + + template<typename char_type> inline bool is_space(char_type); + template<typename char_type> inline char_type to_upper(char_type); + + template<> inline bool is_space ( char_type c) { return bool(std::isspace(static_cast<uchar_type>(c))); } + template<> inline bool is_space (uchar_type c) { return bool(std::isspace(c)); } + template<> inline bool is_space (wchar_type c) { return bool(std::iswspace(c)); } + template<> inline char_type to_upper ( char_type c) { return std::toupper(static_cast<uchar_type>(c)); } + template<> inline uchar_type to_upper (uchar_type c) { return std::toupper(c); } + template<> inline wchar_type to_upper (wchar_type c) { return std::towupper(c); } }} #endif // BOOST_CONVERT_DETAIL_IS_CHAR_HPP diff --git a/boost/convert/detail/forward.hpp b/boost/convert/detail/config.hpp index 7ea7960490..6c74cd308a 100644 --- a/boost/convert/detail/forward.hpp +++ b/boost/convert/detail/config.hpp @@ -5,7 +5,33 @@ #ifndef BOOST_CONVERT_FORWARD_HPP #define BOOST_CONVERT_FORWARD_HPP +#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 + +// Intel 12.0 and lower have broken SFINAE +#if defined(BOOST_INTEL) && (BOOST_INTEL <= 1200) +# define BOOST_CONVERT_IS_NOT_SUPPORTED +#endif + +// No C++11 support +#if defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION <= 40600) +# define BOOST_CONVERT_IS_NOT_SUPPORTED +#endif + +// MSVC-11 and lower have broken SFINAE +#if defined(BOOST_MSVC) && (BOOST_MSVC < 1800) +# define BOOST_CONVERT_IS_NOT_SUPPORTED +#endif + #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) @@ -29,23 +55,4 @@ #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 diff --git a/boost/convert/detail/has_member.hpp b/boost/convert/detail/has_member.hpp index 68e53807a9..2cd617f7b0 100644 --- a/boost/convert/detail/has_member.hpp +++ b/boost/convert/detail/has_member.hpp @@ -5,7 +5,6 @@ #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__"... @@ -41,7 +40,7 @@ template <typename __boost_has_member_T__> /*C4*/ \ class __trait_name__ \ { \ - typedef typename ::boost::remove_const<__boost_has_member_T__>::type check_type; \ + 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; \ \ diff --git a/boost/convert/detail/is_converter.hpp b/boost/convert/detail/is_converter.hpp index 7633b6daba..6964655409 100644 --- a/boost/convert/detail/is_converter.hpp +++ b/boost/convert/detail/is_converter.hpp @@ -5,7 +5,7 @@ #ifndef BOOST_CONVERT_IS_CONVERTER_HPP #define BOOST_CONVERT_IS_CONVERTER_HPP -#include <boost/convert/detail/forward.hpp> +#include <boost/convert/detail/config.hpp> #include <boost/convert/detail/is_callable.hpp> #include <boost/utility/enable_if.hpp> #include <boost/type_traits.hpp> diff --git a/boost/convert/detail/is_fun.hpp b/boost/convert/detail/is_fun.hpp index 9fa4d96f9b..72a768188a 100644 --- a/boost/convert/detail/is_fun.hpp +++ b/boost/convert/detail/is_fun.hpp @@ -5,7 +5,7 @@ #ifndef BOOST_CONVERT_IS_FUNCTION_HPP #define BOOST_CONVERT_IS_FUNCTION_HPP -#include <boost/convert/detail/forward.hpp> +#include <boost/convert/detail/config.hpp> #include <boost/convert/detail/has_member.hpp> #include <boost/utility/enable_if.hpp> #include <boost/type_traits.hpp> diff --git a/boost/convert/detail/is_string.hpp b/boost/convert/detail/is_string.hpp index ea6ca82e90..75d565e3e7 100644 --- a/boost/convert/detail/is_string.hpp +++ b/boost/convert/detail/is_string.hpp @@ -11,7 +11,7 @@ namespace boost { namespace cnv { namespace detail { - template<typename T, bool is_range_class> struct is_string : mpl::false_ {}; + template<typename T, bool is_range_class> struct is_string : std::false_type {}; template<typename T> struct is_string<T*, false> { @@ -27,7 +27,7 @@ namespace boost { namespace cnv }; } template<typename T> struct is_string : detail::is_string< - typename remove_const<T>::type, + typename boost::remove_const<T>::type, boost::is_class<T>::value && boost::cnv::is_range<T>::value> {}; }} diff --git a/boost/convert/detail/range.hpp b/boost/convert/detail/range.hpp index 345321039e..82d105f949 100644 --- a/boost/convert/detail/range.hpp +++ b/boost/convert/detail/range.hpp @@ -14,7 +14,7 @@ namespace boost { namespace cnv { namespace detail { - template<typename T, bool is_class> struct is_range : mpl::false_ {}; + template<typename T, bool is_class> struct is_range : std::false_type {}; template<typename T> struct is_range<T, /*is_class=*/true> { @@ -24,7 +24,7 @@ namespace boost { namespace cnv 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> struct is_range : detail::is_range<typename boost::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; @@ -38,9 +38,9 @@ namespace boost { namespace cnv template<typename T> struct iterator<T*, void> { - typedef typename remove_const<T>::type value_type; - typedef T* type; - typedef value_type const* const_type; + typedef typename boost::remove_const<T>::type value_type; + typedef T* type; + typedef value_type const* const_type; }; template<typename T> struct range_base @@ -74,20 +74,21 @@ namespace boost { namespace cnv 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_; } + iterator end () { return base_type::end_; } + const_iterator end () const { return base_type::end_; } + sentry_type sentry () const { return base_type::end_; } + std::size_t size () const { return base_type::end_ - base_type::begin_; } + 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; + using this_type = range; + using base_type = range_base<T*>; + using value_type = typename boost::remove_const<T>::type; + using iterator = T*; + using const_iterator = value_type const*; struct sentry_type { diff --git a/boost/convert/spirit.hpp b/boost/convert/spirit.hpp index 22a88b9b3f..b33a793f38 100644 --- a/boost/convert/spirit.hpp +++ b/boost/convert/spirit.hpp @@ -6,7 +6,7 @@ #define BOOST_CONVERT_SPIRIT_BASED_CONVERTER_HPP #include <boost/convert/base.hpp> -#include <boost/convert/detail/forward.hpp> +#include <boost/convert/detail/config.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/karma.hpp> diff --git a/boost/convert/strtol.hpp b/boost/convert/strtol.hpp index de5aa29a8a..4dd26eef7f 100644 --- a/boost/convert/strtol.hpp +++ b/boost/convert/strtol.hpp @@ -76,16 +76,16 @@ boost::cnv::strtol::i_to_str(Type in_value, char_type* buf) const 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); + char_type* beg = buf + bufsize_ / 2; + char_type* end = beg; + bool const is_neg = std::is_signed<Type>::value && in_value < 0; + unsigned_type value = static_cast<unsigned_type>(is_neg ? -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) = '-'; + if (beg == end) *(--beg) = '0'; + if (is_neg) *(--beg) = '-'; return cnv::range<char_type*>(beg, end); } @@ -197,20 +197,20 @@ 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; + // C1. Because of strtold() currently only works with 'char' + // C2. strtold() does not work with ranges. + // Consequently, we have to copy the supplied range into a string for strtold(). + // C3. Check if the end-of-string was reached -- *cnv_end == 0. 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)(); + size_t const sz = 128; + ch_type str[sz] = {0}; std::strncpy(str, &*range.begin(), std::min(sz - 1, range.size())); + char* cnv_end = 0; + ldbl_type result = strtold(str, &cnv_end); + bool good = result != -HUGE_VALL && result != HUGE_VALL && *cnv_end == 0; //C3 + out_type max = (std::numeric_limits<out_type>::max)(); if (good && -max <= result && result <= max) result_out = out_type(result); |