From: g0dil Date: Fri, 15 May 2009 13:22:29 +0000 (+0000) Subject: Utils: Add customizable lexical_cast implementation X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=9135a4d83cebb5d4f01cceaf1d8f6ca45cafc7e1;p=senf.git Utils: Add customizable lexical_cast implementation git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1206 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Utils/String.ct b/Utils/String.ct index 8e27ac4..3491a2e 100644 --- a/Utils/String.ct +++ b/Utils/String.ct @@ -28,6 +28,8 @@ // Custom includes #include #include +#include +#include #define prefix_ ///////////////////////////////ct.p//////////////////////////////////////// @@ -50,6 +52,93 @@ prefix_ std::string senf::stringJoin(ForwardReadableRange const & range, std::st return ss.str(); } +// Copied from boost/lexical_cast.hpp +namespace senf { +namespace detail { + template + class lexical_stream + { + private: + typedef char char_type; + + public: + lexical_stream() + { + stream.unsetf(std::ios::skipws); + if(std::numeric_limits::is_specialized) + stream.precision(std::numeric_limits::digits10 + 1); + } + template + bool operator<<(const Source &input) + { + if(std::numeric_limits::is_specialized) + stream.precision(std::numeric_limits::digits10 + 1); + return !(stream << input).fail(); + } + template + bool operator>>(InputStreamable &output) + { + return !boost::is_pointer::value && + stream >> output && + stream.get() == std::char_traits::eof(); + } + bool operator>>(std::string &output) + { + output = stream.str(); + return true; + } + bool operator>>(std::wstring &output) + { + output = stream.str(); + return true; + } + private: + std::basic_stringstream stream; + }; + + template + class lexical_caster + { + public: + lexical_caster() : interpreter_ (new senf::detail::lexical_stream()) {} + template + Target operator()(Source const & arg) const + { + Target result; + if(!((*interpreter_) << arg && (*interpreter_) >> result)) + boost::throw_exception(boost::bad_lexical_cast(typeid(Source), typeid(Target))); + return result; + } + + template + lexical_caster const & operator[](Mod mod) const + { + (*interpreter_) << mod; + return *this; + } + + private: + boost::shared_ptr< senf::detail::lexical_stream > interpreter_; + }; +}} + +template +prefix_ Target senf::lexical_cast(Source const & arg) +{ + senf::detail::lexical_stream interpreter; + Target result; + + if(!(interpreter << arg && interpreter >> result)) + boost::throw_exception(boost::bad_lexical_cast(typeid(Source), typeid(Target))); + return result; +} + +template +prefix_ senf::detail::lexical_caster senf::lexical_cast() +{ + return detail::lexical_caster(); +} + ///////////////////////////////ct.e//////////////////////////////////////// #undef prefix_ diff --git a/Utils/String.hh b/Utils/String.hh index 623068b..ee71b55 100644 --- a/Utils/String.hh +++ b/Utils/String.hh @@ -45,6 +45,13 @@ namespace senf { template std::string str(T const & t); + template + Target lexical_cast(Source const & arg); + + namespace detail { template class lexical_caster; } + + template + detail::lexical_caster lexical_cast(); } ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/Utils/String.test.cc b/Utils/String.test.cc index 1f6a17c..1ba4935 100644 --- a/Utils/String.test.cc +++ b/Utils/String.test.cc @@ -28,6 +28,7 @@ // Custom includes #include "String.hh" +#include #include "auto_unit_test.hh" #include @@ -42,6 +43,24 @@ BOOST_AUTO_UNIT_TEST(stringJoin) "foo::bar::baz" ); } +BOOST_AUTO_UNIT_TEST(lexicalCast) +{ + SENF_CHECK_NO_THROW( + BOOST_CHECK_EQUAL( + senf::lexical_cast()[std::setbase(0)](std::string("0x1a2b")), + 6699u ) ); + SENF_CHECK_NO_THROW( + BOOST_CHECK_EQUAL( + senf::lexical_cast()[std::hex][std::uppercase][std::showbase](6699u), + "0X1A2B" ) ); + SENF_CHECK_NO_THROW( + BOOST_CHECK_EQUAL( + senf::lexical_cast(std::string("6699")), 6699u ) ); + SENF_CHECK_NO_THROW( + BOOST_CHECK_EQUAL( + senf::lexical_cast(6699u), "6699" ) ); +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_