From 78ea5912efc6e3dbe96ce17e30d6411ea6cc346a Mon Sep 17 00:00:00 2001 From: Vladimir Batov Date: Tue, 24 Jun 2014 12:22:05 +1000 Subject: [PATCH] added coerce --- doc/Jamfile.v2 | 2 +- include/boost/convert/detail/base.hpp | 2 +- .../boost/convert/detail/string_sfinae.hpp | 6 +- include/boost/convert/spirit.hpp | 59 ++++++++++++++----- test/{int_to_str.cpp => int_to_str.hpp} | 47 +++++---------- test/main.cpp | 17 ++++-- test/spirit.cpp | 29 +++++++++ test/stream.cpp | 47 +++++++++++++++ test/test.hpp | 1 + 9 files changed, 153 insertions(+), 57 deletions(-) rename test/{int_to_str.cpp => int_to_str.hpp} (52%) diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 9a4bb34..a36b9ea 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -56,7 +56,7 @@ boostbook standalone : convert : - boost.root="../../../.." + boost.root="$(BOOST_ROOT)" chunk.section.depth=8 toc.section.depth=8 # How far down sections get TOCs. toc.max.depth=4 # Max depth in each TOC. diff --git a/include/boost/convert/detail/base.hpp b/include/boost/convert/detail/base.hpp index f67a382..76cff3f 100644 --- a/include/boost/convert/detail/base.hpp +++ b/include/boost/convert/detail/base.hpp @@ -50,7 +50,7 @@ struct boost::cnv::detail::cnvbase protected: - derived const& dncast() const { return static_cast(*this); } + derived const& dncast() const { return *static_cast(this); } int mutable base_; int mutable precision_; diff --git a/include/boost/convert/detail/string_sfinae.hpp b/include/boost/convert/detail/string_sfinae.hpp index 4c526d7..808f210 100644 --- a/include/boost/convert/detail/string_sfinae.hpp +++ b/include/boost/convert/detail/string_sfinae.hpp @@ -117,7 +117,7 @@ struct string_range >::t typedef char_type const* iterator; static iterator begin (String const& s) { return &*s.begin(); } -// static iterator end (String const& s) { return s.end(); } + static iterator end (String const& s) { return &*s.end(); } static std::streamsize size (String const& s) { return std::streamsize(s.size()); } }; diff --git a/include/boost/convert/spirit.hpp b/include/boost/convert/spirit.hpp index 41d9910..fa3dfa9 100644 --- a/include/boost/convert/spirit.hpp +++ b/include/boost/convert/spirit.hpp @@ -5,35 +5,62 @@ #ifndef BOOST_CONVERT_SPIRIT_BASED_CONVERTER_HPP #define BOOST_CONVERT_SPIRIT_BASED_CONVERTER_HPP -#include -#include -#include +#include +#include +#include namespace boost { namespace cnv { struct spirit; }} -struct boost::cnv::spirit +struct boost::cnv::spirit : public boost::cnv::detail::cnvbase { - template - void parse_(Iterator beg, Iterator end, boost::optional& result_out) const + typedef boost::cnv::spirit this_type; + typedef boost::cnv::detail::cnvbase base_type; + + using base_type::operator(); + + template + void + operator()(TypeIn const& value_in, boost::optional& result_out) const { - int result; + try + { + /**/ if (base_ == 10) result_out = coerce::as(value_in); + else if (base_ == 8) result_out = coerce::as(value_in, coerce::tag::oct()); + else if (base_ == 16) result_out = coerce::as(value_in, coerce::tag::hex()); + } + catch(boost::coerce::bad_cast const&) + { + } + } +}; + +#ifdef asdasdasdasdasdasd + +#include +#include +#include +#include +#include + + template + typename boost::enable_if, void>::type + operator()(StringIn const& string_in, boost::optional& result_out) const + { + typedef cnv::string_range range_type; + typedef typename range_type::char_type char_type; + + char_type const* beg = cnv::string_range::begin(string_in); + char_type const* end = cnv::string_range::end(string_in); + int result; if (boost::spirit::qi::parse(beg, end, boost::spirit::int_, result)) if (beg == end) // ensure the whole string was parsed result_out = result; } - void operator()(std::string const& str, boost::optional& result) const - { - parse_(str.begin(), str.end(), result); - } - void operator()(char const* str, boost::optional& result) const - { - parse_(str, str + strlen(str), result); - } -}; +#endif #endif // BOOST_CONVERT_SPIRIT_BASED_CONVERTER_HPP diff --git a/test/int_to_str.cpp b/test/int_to_str.hpp similarity index 52% rename from test/int_to_str.cpp rename to test/int_to_str.hpp index a156397..b5c941e 100644 --- a/test/int_to_str.cpp +++ b/test/int_to_str.hpp @@ -1,27 +1,23 @@ -// Boost.Convert test and usage example // Copyright (c) 2009-2014 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_TEST_INT_TO_STR_HPP +#define BOOST_CONVERT_TEST_INT_TO_STR_HPP + #include "./test.hpp" #include -#include #include using std::string; -using std::wstring; +template void -test::cnv::int_to_string() +test::cnv::int_to_str(Converter const& cnv) { - boost::cnv::cstream ccnv; // std::stringstream-based char converter - boost::cnv::wstream wcnv; // std::stringstream-based wchar_t converter - string const not_int_str = "not an int"; string const std_str = "-11"; char const* const c_str = "-12"; - wstring const wstd_str = L"-13"; - wchar_t const* const wc_str = L"-14"; char const array_str[] = "-15"; //////////////////////////////////////////////////////////////////////////// @@ -29,35 +25,22 @@ test::cnv::int_to_string() // containers as the fallback values. //////////////////////////////////////////////////////////////////////////// - string s01 = boost::convert< string>(-1, ccnv).value_or(std_str); - string s02 = boost::convert< string>(-2, ccnv).value_or(c_str); - wstring s03 = boost::convert(-3, wcnv).value_or(wstd_str); - wstring s04 = boost::convert(-4, wcnv).value_or(wc_str); - string s05 = boost::convert< string>(-5, ccnv).value_or(array_str); - boost::optional< string> rs01 = boost::convert< string>(-1, ccnv); - boost::optional< string> rs02 = boost::convert< string>(-2, ccnv); - boost::optional rs03 = boost::convert(-3, wcnv); - boost::optional rs04 = boost::convert(-4, wcnv); - boost::optional< string> rs05 = boost::convert< string>(-5, ccnv); + string s01 = boost::convert< string>(-1, cnv).value_or(std_str); + string s02 = boost::convert< string>(-2, cnv).value_or(c_str); + string s05 = boost::convert< string>(-5, cnv).value_or(array_str); + boost::optional< string> rs01 = boost::convert< string>(-1, cnv); + boost::optional< string> rs02 = boost::convert< string>(-2, cnv); + boost::optional< string> rs05 = boost::convert< string>(-5, cnv); BOOST_TEST(s01 == "-1"); BOOST_TEST(rs01 && rs01.value() == "-1"); BOOST_TEST(s02 == "-2"); BOOST_TEST(rs02 && rs02.value() == "-2"); - BOOST_TEST(s03 == L"-3"); BOOST_TEST(rs03 && rs03.value() == L"-3"); - BOOST_TEST(s04 == L"-4"); BOOST_TEST(rs04 && rs04.value() == L"-4"); BOOST_TEST(s05 == "-5"); BOOST_TEST(rs05 && rs05.value() == "-5"); - //////////////////////////////////////////////////////////////////////////// - // Testing int-to-string conversion with no fallback value. - //////////////////////////////////////////////////////////////////////////// - - string s11 = boost::convert< string>(-1, ccnv).value(); - wstring s12 = boost::convert(-2, wcnv).value(); - boost::optional< string> rs11 = boost::convert< string>(-1, ccnv); - boost::optional rs12 = boost::convert(-2, wcnv); + string s11 = boost::convert< string>(-1, cnv).value(); + boost::optional< string> rs11 = boost::convert< string>(-1, cnv); BOOST_TEST( s11 == "-1"); - BOOST_TEST( s12 == L"-2"); BOOST_TEST(rs11 && rs11.value() == "-1"); - BOOST_TEST(rs12 && rs12.value() == L"-2"); - } + +#endif // BOOST_CONVERT_TEST_INT_TO_STR_HPP diff --git a/test/main.cpp b/test/main.cpp index e27a721..a3f28bb 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -5,12 +5,14 @@ #include "./test.hpp" #include "./str_to_int.hpp" +#include "./int_to_str.hpp" #include #include #include #include #include +#include #include @@ -61,15 +63,22 @@ main(int argc, char const* argv[]) test::cnv::scratchpad(); test::cnv::is_converter(); test::cnv::stream(); - - BOOST_TEST(test::performance::spirit_framework()); + test::cnv::spirit(); test::cnv::sfinae(); - test::cnv::int_to_string(); + test::cnv::str_to_int(boost::cnv::lexical_cast()); test::cnv::str_to_int(boost::cnv::cstream()); test::cnv::str_to_int(boost::cnv::strtol()); test::cnv::str_to_int(boost::cnv::printf()); + test::cnv::str_to_int(boost::cnv::spirit()); + + test::cnv::int_to_str(boost::cnv::lexical_cast()); + test::cnv::int_to_str(boost::cnv::cstream()); + test::cnv::int_to_str(boost::cnv::strtol()); + test::cnv::int_to_str(boost::cnv::printf()); +// test::cnv::int_to_str(boost::cnv::spirit()); + test::cnv::type_to_str(boost::cnv::printf()); test::cnv::str_to_type(boost::cnv::strtol()); test::cnv::str_to_type(boost::cnv::printf()); @@ -81,7 +90,7 @@ main(int argc, char const* argv[]) test::cnv::fallbacks(); test::cnv::encryption(); test::cnv::performance(); - test::cnv::spirit(); + BOOST_TEST(test::performance::spirit_framework()); return boost::report_errors(); } diff --git a/test/spirit.cpp b/test/spirit.cpp index da85540..0ed58da 100644 --- a/test/spirit.cpp +++ b/test/spirit.cpp @@ -6,8 +6,37 @@ #include "./test.hpp" #include #include +#include +#include + +using std::string; +using boost::convert; + +namespace arg = boost::cnv::parameter; + +struct boost::cnv::by_default : public boost::cnv::spirit {}; void test::cnv::spirit() { + boost::cnv::spirit cnv; + + boost::optional i1 = convert("uhm"); + boost::optional i2 = convert("123"); + boost::optional i3 = convert("0x23", cnv(arg::base = boost::cnv::base::hex)); +// boost::optional d1 = convert("12.uhm"); +// boost::optional d2 = convert("12.3"); + boost::optional s1 = convert(123456789012345678); +// boost::optional s2 = convert(12.34); + + BOOST_TEST(!i1); + BOOST_TEST( i2 && i2.value() == 123); + BOOST_TEST( i3 && i3.value() == 35); +// BOOST_TEST(!d1); +// BOOST_TEST( d2 && d2.value() == 12.3); + BOOST_TEST( s1); + BOOST_TEST( s1 && s1.value() == "123456789012345678"); +// BOOST_TEST( s2 && s2.value() == "12.34"); + +// printf("%s\n", s2->c_str()); } diff --git a/test/stream.cpp b/test/stream.cpp index bf29a09..557166c 100644 --- a/test/stream.cpp +++ b/test/stream.cpp @@ -13,6 +13,7 @@ namespace arg = boost::cnv::parameter; //[stream_using using std::string; +using std::wstring; using boost::convert; //] static @@ -192,4 +193,50 @@ test::cnv::stream() test_skipws(); test_manipulators(); test_locale(); + + boost::cnv::cstream ccnv; // std::stringstream-based char converter + boost::cnv::wstream wcnv; // std::stringstream-based wchar_t converter + + string const not_int_str = "not an int"; + string const std_str = "-11"; + char const* const c_str = "-12"; + wstring const wstd_str = L"-13"; + wchar_t const* const wc_str = L"-14"; + char const array_str[] = "-15"; + + //////////////////////////////////////////////////////////////////////////// + // Testing int-to-string conversion with various string + // containers as the fallback values. + //////////////////////////////////////////////////////////////////////////// + + string s01 = boost::convert< string>(-1, ccnv).value_or(std_str); + string s02 = boost::convert< string>(-2, ccnv).value_or(c_str); + wstring s03 = boost::convert(-3, wcnv).value_or(wstd_str); + wstring s04 = boost::convert(-4, wcnv).value_or(wc_str); + string s05 = boost::convert< string>(-5, ccnv).value_or(array_str); + boost::optional< string> rs01 = boost::convert< string>(-1, ccnv); + boost::optional< string> rs02 = boost::convert< string>(-2, ccnv); + boost::optional rs03 = boost::convert(-3, wcnv); + boost::optional rs04 = boost::convert(-4, wcnv); + boost::optional< string> rs05 = boost::convert< string>(-5, ccnv); + + BOOST_TEST(s01 == "-1"); BOOST_TEST(rs01 && rs01.value() == "-1"); + BOOST_TEST(s02 == "-2"); BOOST_TEST(rs02 && rs02.value() == "-2"); + BOOST_TEST(s03 == L"-3"); BOOST_TEST(rs03 && rs03.value() == L"-3"); + BOOST_TEST(s04 == L"-4"); BOOST_TEST(rs04 && rs04.value() == L"-4"); + BOOST_TEST(s05 == "-5"); BOOST_TEST(rs05 && rs05.value() == "-5"); + + //////////////////////////////////////////////////////////////////////////// + // Testing int-to-string conversion with no fallback value. + //////////////////////////////////////////////////////////////////////////// + + string s11 = boost::convert< string>(-1, ccnv).value(); + wstring s12 = boost::convert(-2, wcnv).value(); + boost::optional< string> rs11 = boost::convert< string>(-1, ccnv); + boost::optional rs12 = boost::convert(-2, wcnv); + + BOOST_TEST( s11 == "-1"); + BOOST_TEST( s12 == L"-2"); + BOOST_TEST(rs11 && rs11.value() == "-1"); + BOOST_TEST(rs12 && rs12.value() == L"-2"); } diff --git a/test/test.hpp b/test/test.hpp index ca1a578..3e9a646 100644 --- a/test/test.hpp +++ b/test/test.hpp @@ -151,6 +151,7 @@ namespace test static void spirit (); template static void str_to_int (Cnv const&); + template static void int_to_str (Cnv const&); template static void type_to_str (Cnv const&); template static void str_to_type (Cnv const&); };