Utils/Termlib: Extend the completion API
[senf.git] / Utils / String.ct
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_