Build system improvements
[ustl.git] / uctrstrm.h
blob662b0bd73e198d20c2ccdb02420d46cc7cb53c9d
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 ///
14 #ifndef UCTRSTRM_H_75B2C3EA4980DDDC6B6DFFF767A3B7AC
15 #define UCTRSTRM_H_75B2C3EA4980DDDC6B6DFFF767A3B7AC
17 #include "mistream.h"
18 #include "sostream.h"
19 #include "uiosfunc.h"
20 #include <typeinfo>
22 namespace ustl {
24 //----------------------------------------------------------------------
25 // Macros for easily declaring a container streamable.
26 //----------------------------------------------------------------------
28 /// \brief Declares container template \p type streamable.
29 ///
30 /// Use TEMPLATE_TYPE and TEMPLATE_DECL macros to pass in templated
31 /// type with commas and the template declaration.
32 ///
33 #define STD_TEMPLATE_CTR_STREAMABLE(type, template_decl) \
34 template_decl \
35 inline istream& operator>> (istream& is, type& v) \
36 { return (container_read (is, v)); } \
37 template_decl \
38 inline ostream& operator<< (ostream& os, const type& v) \
39 { return (container_write (os, v)); } \
40 template_decl \
41 inline ostringstream& operator<< (ostringstream& os, const type& v) \
42 { return (container_text_write (os, v)); } \
43 template_decl \
44 struct object_stream_size<type > { \
45 inline size_t operator()(const type& v) const \
46 { return (container_stream_size (v)); } \
49 /// \brief Declares non-resizable container template \p type streamable.
50 #define STD_TEMPLATE_NR_CTR_STREAMABLE(type, template_decl) \
51 template_decl \
52 inline istream& operator>> (istream& is, type& v) \
53 { return (nr_container_read (is, v)); } \
54 template_decl \
55 inline ostream& operator<< (ostream& os, const type& v) \
56 { return (nr_container_write (os, v)); } \
57 template_decl \
58 inline ostringstream& operator<< (ostringstream& os, const type& v) \
59 { return (container_text_write (os, v)); } \
60 template_decl \
61 struct object_stream_size<type > { \
62 inline size_t operator()(const type& v) const \
63 { return (nr_container_stream_size (v)); } \
66 //----------------------------------------------------------------------
67 // Fixed size container serialization.
68 //----------------------------------------------------------------------
70 /// Reads fixed size container \p v from stream \p is.
71 template <typename Container>
72 inline istream& nr_container_read (istream& is, Container& v)
74 foreach (typename Container::iterator, i, v)
75 is >> *i;
76 return (is);
79 /// Writes fixed size container \p v into stream \p os.
80 template <typename Container>
81 inline ostream& nr_container_write (ostream& os, const Container& v)
83 foreach (typename Container::const_iterator, i, v)
84 os << *i;
85 return (os);
88 /// Computes the stream size of a fixed size standard container.
89 template <typename Container>
90 inline size_t nr_container_stream_size (const Container& v)
92 typedef typename Container::const_iterator vciter_t;
93 typedef typename iterator_traits<vciter_t>::value_type value_type;
94 if (!v.size())
95 return (0);
96 size_t s = 0, dvs;
97 vciter_t i = v.begin();
98 do {
99 dvs = stream_size_of(*i);
100 s += dvs;
101 } while (++i != v.end() && !__builtin_constant_p(dvs));
102 if (__builtin_constant_p(dvs))
103 s *= v.size();
104 return (s);
107 //----------------------------------------------------------------------
108 // Resizable container serialization.
109 //----------------------------------------------------------------------
111 /// Reads container \p v from stream \p is.
112 template <typename Container>
113 istream& container_read (istream& is, Container& v)
115 typedef typename Container::value_type value_type;
116 typedef typename Container::iterator iterator;
117 typedef typename Container::written_size_type written_size_type;
118 written_size_type n;
119 is >> n;
120 const size_t expectedSize = n * stream_size_of(value_type());
121 is.verify_remaining ("read", typeid(v).name(), expectedSize);
122 if (alignof(NullValue<value_type>()) > alignof(n))
123 is >> ios::talign<value_type>();
124 v.resize (n);
125 nr_container_read (is, v);
126 is >> ios::talign<written_size_type>();
127 return (is);
130 /// Writes the vector to stream \p os.
131 template <typename Container>
132 ostream& container_write (ostream& os, const Container& v)
134 typedef typename Container::value_type value_type;
135 typedef typename Container::written_size_type written_size_type;
136 const written_size_type sz (v.size());
137 os << sz;
138 if (alignof(NullValue<value_type>()) > alignof(sz))
139 os << ios::talign<value_type>();
140 nr_container_write (os, v);
141 os << ios::talign<written_size_type>();
142 return (os);
145 /// Computes the stream size of a standard container.
146 template <typename Container>
147 size_t container_stream_size (const Container& v)
149 typedef typename Container::value_type value_type;
150 typedef typename Container::written_size_type written_size_type;
151 const written_size_type sz (v.size());
152 size_t sizeSize = stream_size_of (sz);
153 if (alignof(NullValue<value_type>()) > alignof(sz))
154 sizeSize = Align (sizeSize, alignof(NullValue<value_type>()));
155 return (Align (sizeSize + nr_container_stream_size (v), alignof(sz)));
158 /// \brief Writes element \p v into stream \p os as text.
159 /// Specialize to custom print elements.
160 template <typename T>
161 inline ostringstream& container_element_text_write (ostringstream& os, const T& v)
162 { return (os << v); }
164 /// Writes container \p v into stream \p os as text.
165 template <typename Container>
166 ostringstream& container_text_write (ostringstream& os, const Container& v)
168 typename Container::const_iterator i = v.begin();
169 os << '(';
170 while (i < v.end()) {
171 container_element_text_write (os, *i);
172 os << ",)"[++i == v.end()];
174 return (os);
177 //----------------------------------------------------------------------
179 } // namespace ustl
181 #endif