Utils: Add customizable lexical_cast implementation
g0dil [Fri, 15 May 2009 13:22:29 +0000 (13:22 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1206 270642c3-0616-0410-b53a-bc976706d245

Utils/String.ct
Utils/String.hh
Utils/String.test.cc

index 8e27ac4..3491a2e 100644 (file)
@@ -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_
 
index 623068b..ee71b55 100644 (file)
@@ -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////////////////////////////////////////
index 1f6a17c..1ba4935 100644 (file)
@@ -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_