Skip to content
Snippets Groups Projects
Commit 4565a260 authored by g0dil's avatar g0dil
Browse files

Utils: Add customizable lexical_cast implementation

parent cbf91493
No related branches found
No related tags found
No related merge requests found
......@@ -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_
......
......@@ -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////////////////////////////////////////
......
......@@ -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_
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment