diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-08-10 18:30:25 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-08-10 18:30:25 +0200 |
commit | 5d1ba0388af2f66d1d83db755361d3b2eb5f68ad (patch) | |
tree | f265cbe1ae81a84631e4a2d63dfd471a30404633 /xml | |
parent | 60366c5e3e326eb0d5b828ba8bbd81f317cd24e3 (diff) |
Add streaming API to serializer
Show what can be done with it in the xhtml example.
Diffstat (limited to 'xml')
-rw-r--r-- | xml/serializer | 16 | ||||
-rw-r--r-- | xml/serializer.ixx | 55 |
2 files changed, 71 insertions, 0 deletions
diff --git a/xml/serializer b/xml/serializer index 316a501..eb592df 100644 --- a/xml/serializer +++ b/xml/serializer @@ -185,6 +185,8 @@ namespace xml // namespace is declared. If both prefix and namespace are empty, // then the default namespace declaration is cleared (xmlns=""). // + // This function should be called after start_element(). + // void namespace_decl (const std::string& ns, const std::string& prefix); @@ -251,6 +253,20 @@ namespace xml genxSender sender_; std::size_t depth_; }; + + // Stream-like interface for serializer. If the passed argument + // is a function with the void f(serializer&) signature or is a + // function object with the void operator() (serializer&) const + // operator, then this function (object) is called with the passed + // serializer. Otherwise, the argument is passed to the serializer's + // characters() function. + // + serializer& + operator<< (serializer&, void (*func) (serializer&)); + + template <typename T> + serializer& + operator<< (serializer&, const T& value); } #include <xml/serializer.ixx> diff --git a/xml/serializer.ixx b/xml/serializer.ixx index ea3dcf0..5cff976 100644 --- a/xml/serializer.ixx +++ b/xml/serializer.ixx @@ -118,4 +118,59 @@ namespace xml { characters (value_traits<T>::serialize (value, *this)); } + + // operator<< + // + + inline serializer& + operator<< (serializer& s, void (*func) (serializer&)) + { + func (s); + return s; + } + + namespace details + { + // Detect whether T defines void operator(A) const. + // + template <typename T, typename A> + struct is_functor + { + typedef char no[1]; + typedef char yes[2]; + + template <typename X, X> struct check; + + template <typename> + static no& test (...); + + template <typename X> + static yes& test (check<void (X::*) (A) const, &X::operator ()>*); + + static const bool value = sizeof (test<T> (0)) == sizeof (yes); + }; + + template <typename T, bool = is_functor<T, serializer&>::value> + struct inserter; + + template <typename T> + struct inserter<T, true> + { + static void insert (serializer& s, const T& f) {f (s);} + }; + + template <typename T> + struct inserter<T, false> + { + static void insert (serializer& s, const T& v) {s.characters (v);} + }; + } + + template <typename T> + inline serializer& + operator<< (serializer& s, const T& value) + { + details::inserter<T>::insert (s, value); + return s; + } } |