1// This file is part of the ustl library, an STL implementation. 2// 3// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net> 4// This file is free software, distributed under the MIT License. 5// 6/// \file uctrstrm.h 7/// 8/// \brief Serialization templates for standard containers. 9/// Because containers are templates, a single operator>> is impossible. 10/// Making virtual read/write is also impossible because not all containers 11/// contain serializable elements. Therefore, use the macros in this file. 12/// 13 14#ifndef UCTRSTRM_H_75B2C3EA4980DDDC6B6DFFF767A3B7AC 15#define UCTRSTRM_H_75B2C3EA4980DDDC6B6DFFF767A3B7AC 16 17#include "mistream.h" 18#include "sostream.h" 19#include "uiosfunc.h" 20 21namespace ustl { 22 23//---------------------------------------------------------------------- 24// Macros for easily declaring a container streamable. 25//---------------------------------------------------------------------- 26 27/// \brief Declares container template \p type streamable. 28/// 29/// Use TEMPLATE_TYPE and TEMPLATE_DECL macros to pass in templated 30/// type with commas and the template declaration. 31/// 32#define STD_TEMPLATE_CTR_STREAMABLE(type, template_decl) \ 33 template_decl \ 34 inline istream& operator>> (istream& is, type& v) \ 35 { return (container_read (is, v)); } \ 36 template_decl \ 37 inline ostream& operator<< (ostream& os, const type& v) \ 38 { return (container_write (os, v)); } \ 39 template_decl \ 40 inline ostringstream& operator<< (ostringstream& os, const type& v) \ 41 { return (container_text_write (os, v)); } \ 42 template_decl \ 43 inline size_t stream_size_of (const type& v) \ 44 { return (container_stream_size (v)); } 45 46/// \brief Declares non-resizable container template \p type streamable. 47#define STD_TEMPLATE_NR_CTR_STREAMABLE(type, template_decl) \ 48 template_decl \ 49 inline istream& operator>> (istream& is, type& v) \ 50 { return (nr_container_read (is, v)); } \ 51 template_decl \ 52 inline ostream& operator<< (ostream& os, const type& v) \ 53 { return (nr_container_write (os, v)); } \ 54 template_decl \ 55 inline ostringstream& operator<< (ostringstream& os, const type& v) \ 56 { return (container_text_write (os, v)); } \ 57 template_decl \ 58 inline size_t stream_size_of (const type& v) \ 59 { return (nr_container_stream_size (v)); } 60 61//---------------------------------------------------------------------- 62// Fixed size container serialization. 63//---------------------------------------------------------------------- 64 65/// Reads fixed size container \p v from stream \p is. 66template <typename Container> 67inline istream& nr_container_read (istream& is, Container& v) 68{ 69 foreach (typename Container::iterator, i, v) 70 is >> *i; 71 return (is); 72} 73 74/// Writes fixed size container \p v into stream \p os. 75template <typename Container> 76inline ostream& nr_container_write (ostream& os, const Container& v) 77{ 78 foreach (typename Container::const_iterator, i, v) 79 os << *i; 80 return (os); 81} 82 83/// Computes the stream size of a fixed size standard container. 84template <typename Container> 85size_t nr_container_stream_size (const Container& v) 86{ 87 typedef typename Container::const_iterator vciter_t; 88 typedef typename iterator_traits<vciter_t>::value_type value_type; 89 size_t s = 0; 90 if (numeric_limits<value_type>::is_integral) 91 s += v.size() * stream_size_of(value_type()); 92 else 93 foreach (vciter_t, i, v) 94 s += stream_size_of(*i); 95 return (s); 96} 97 98//---------------------------------------------------------------------- 99// Resizable container serialization. 100//---------------------------------------------------------------------- 101 102/// Reads container \p v from stream \p is. 103template <typename Container> 104istream& container_read (istream& is, Container& v) 105{ 106 typedef typename Container::value_type value_type; 107 typedef typename Container::iterator iterator; 108 typedef typename Container::written_size_type written_size_type; 109 written_size_type n; 110 is >> n; 111 const size_t expectedSize = n * stream_size_of(value_type()); 112#if !PLATFORM_ANDROID 113 is.verify_remaining ("read", typeid(v).name(), expectedSize); 114#endif 115 if (alignof(value_type()) > alignof(n)) 116 is >> ios::talign<value_type>(); 117 v.resize (n); 118 nr_container_read (is, v); 119 is >> ios::talign<written_size_type>(); 120 return (is); 121} 122 123/// Writes the vector to stream \p os. 124template <typename Container> 125ostream& container_write (ostream& os, const Container& v) 126{ 127 typedef typename Container::value_type value_type; 128 typedef typename Container::written_size_type written_size_type; 129 const written_size_type sz (v.size()); 130 os << sz; 131 if (alignof(value_type()) > alignof(sz)) 132 os << ios::talign<value_type>(); 133 nr_container_write (os, v); 134 os << ios::talign<written_size_type>(); 135 return (os); 136} 137 138/// Computes the stream size of a standard container. 139template <typename Container> 140size_t container_stream_size (const Container& v) 141{ 142 typedef typename Container::value_type value_type; 143 typedef typename Container::written_size_type written_size_type; 144 const written_size_type sz (v.size()); 145 size_t sizeSize = stream_size_of (sz); 146 if (alignof(value_type()) > alignof(sz)) 147 sizeSize = Align (sizeSize, alignof(value_type())); 148 return (Align (sizeSize + nr_container_stream_size (v), alignof(sz))); 149} 150 151/// \brief Writes element \p v into stream \p os as text. 152/// Specialize to custom print elements. 153template <typename T> 154inline ostringstream& container_element_text_write (ostringstream& os, const T& v) 155{ return (os << v); } 156 157/// Writes container \p v into stream \p os as text. 158template <typename Container> 159ostringstream& container_text_write (ostringstream& os, const Container& v) 160{ 161 typename Container::const_iterator i = v.begin(); 162 os << '('; 163 while (i < v.end()) { 164 container_element_text_write (os, *i); 165 if (++i >= v.end()) break; 166 os << ','; 167 } 168 os << ')'; 169 return (os); 170} 171 172//---------------------------------------------------------------------- 173 174} // namespace ustl 175 176#endif 177 178