From 4565a2608bb51c875cac2cdc8675bcda6a2ce185 Mon Sep 17 00:00:00 2001 From: g0dil <g0dil@wiback.org> Date: Fri, 15 May 2009 13:22:29 +0000 Subject: [PATCH] Utils: Add customizable lexical_cast implementation --- Utils/String.ct | 89 ++++++++++++++++++++++++++++++++++++++++++++ Utils/String.hh | 7 ++++ Utils/String.test.cc | 19 ++++++++++ 3 files changed, 115 insertions(+) diff --git a/Utils/String.ct b/Utils/String.ct index 8e27ac486..3491a2ed0 100644 --- a/Utils/String.ct +++ b/Utils/String.ct @@ -28,6 +28,8 @@ // Custom includes #include <boost/range.hpp> #include <sstream> +#include <boost/lexical_cast.hpp> +#include <boost/shared_ptr.hpp> #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<typename Target> + class lexical_stream + { + private: + typedef char char_type; + + public: + lexical_stream() + { + stream.unsetf(std::ios::skipws); + if(std::numeric_limits<Target>::is_specialized) + stream.precision(std::numeric_limits<Target>::digits10 + 1); + } + template <class Source> + bool operator<<(const Source &input) + { + if(std::numeric_limits<Source>::is_specialized) + stream.precision(std::numeric_limits<Source>::digits10 + 1); + return !(stream << input).fail(); + } + template<typename InputStreamable> + bool operator>>(InputStreamable &output) + { + return !boost::is_pointer<InputStreamable>::value && + stream >> output && + stream.get() == std::char_traits<char_type>::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<char_type> stream; + }; + + template <class Target> + class lexical_caster + { + public: + lexical_caster() : interpreter_ (new senf::detail::lexical_stream<Target>()) {} + template <class Source> + 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 <class Mod> + lexical_caster const & operator[](Mod mod) const + { + (*interpreter_) << mod; + return *this; + } + + private: + boost::shared_ptr< senf::detail::lexical_stream<Target> > interpreter_; + }; +}} + +template <class Target, class Source> +prefix_ Target senf::lexical_cast(Source const & arg) +{ + senf::detail::lexical_stream<Target> interpreter; + Target result; + + if(!(interpreter << arg && interpreter >> result)) + boost::throw_exception(boost::bad_lexical_cast(typeid(Source), typeid(Target))); + return result; +} + +template <class Target> +prefix_ senf::detail::lexical_caster<Target> senf::lexical_cast() +{ + return detail::lexical_caster<Target>(); +} + ///////////////////////////////ct.e//////////////////////////////////////// #undef prefix_ diff --git a/Utils/String.hh b/Utils/String.hh index 623068b65..ee71b555e 100644 --- a/Utils/String.hh +++ b/Utils/String.hh @@ -45,6 +45,13 @@ namespace senf { template <class T> std::string str(T const & t); + template <class Target, class Source> + Target lexical_cast(Source const & arg); + + namespace detail { template <class Target> class lexical_caster; } + + template <class Target> + detail::lexical_caster<Target> lexical_cast(); } ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/Utils/String.test.cc b/Utils/String.test.cc index 1f6a17ce0..1ba4935dd 100644 --- a/Utils/String.test.cc +++ b/Utils/String.test.cc @@ -28,6 +28,7 @@ // Custom includes #include "String.hh" +#include <iomanip> #include "auto_unit_test.hh" #include <boost/test/test_tools.hpp> @@ -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<unsigned>()[std::setbase(0)](std::string("0x1a2b")), + 6699u ) ); + SENF_CHECK_NO_THROW( + BOOST_CHECK_EQUAL( + senf::lexical_cast<std::string>()[std::hex][std::uppercase][std::showbase](6699u), + "0X1A2B" ) ); + SENF_CHECK_NO_THROW( + BOOST_CHECK_EQUAL( + senf::lexical_cast<unsigned>(std::string("6699")), 6699u ) ); + SENF_CHECK_NO_THROW( + BOOST_CHECK_EQUAL( + senf::lexical_cast<std::string>(6699u), "6699" ) ); +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ -- GitLab