Line data Source code
1 :
2 : /* Copyright (c) 2007-2017, Stefan Eilemann <eile@equalizergraphics.com>
3 : * Cedric Stalder <cedric.stalder@gmail.com>
4 : * Daniel Nachbaur <danielnachbaur@gmail.com>
5 : *
6 : * This file is part of Collage <https://github.com/Eyescale/Collage>
7 : *
8 : * This library is free software; you can redistribute it and/or modify it under
9 : * the terms of the GNU Lesser General Public License version 2.1 as published
10 : * by the Free Software Foundation.
11 : *
12 : * This library is distributed in the hope that it will be useful, but WITHOUT
13 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15 : * details.
16 : *
17 : * You should have received a copy of the GNU Lesser General Public License
18 : * along with this library; if not, write to the Free Software Foundation, Inc.,
19 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 : */
21 :
22 : #ifndef CO_DATAISTREAM_H
23 : #define CO_DATAISTREAM_H
24 :
25 : #include <co/api.h>
26 : #include <co/types.h>
27 : #include <lunchbox/array.h> // used inline
28 : #include <lunchbox/bitOperation.h>
29 :
30 : #include <boost/type_traits.hpp>
31 : #include <map>
32 : #include <set>
33 : #include <unordered_map>
34 : #include <unordered_set>
35 : #include <vector>
36 :
37 : namespace co
38 : {
39 : namespace detail
40 : {
41 : class DataIStream;
42 : }
43 :
44 : /** A std::istream-like input data stream for binary data. */
45 : class DataIStream
46 : {
47 : public:
48 : /** @name Internal */
49 : //@{
50 : /** @internal @return the number of remaining buffers. */
51 : virtual size_t nRemainingBuffers() const = 0;
52 :
53 : virtual uint128_t getVersion() const = 0; //!< @internal
54 0 : virtual void reset() { _reset(); } //!< @internal
55 : //@}
56 :
57 : /** @name Data input */
58 : //@{
59 : /** @return a value from the stream. @version 1.0 */
60 : template <typename T>
61 83695 : T read()
62 : {
63 12026 : T value;
64 83695 : *this >> value;
65 83695 : return value;
66 : }
67 :
68 : /** Read a plain data item. @version 1.0 */
69 : template <class T>
70 3409600 : DataIStream& operator>>(T& value)
71 : {
72 3409600 : _read(value, boost::has_trivial_copy<T>());
73 3409626 : return *this;
74 : }
75 :
76 : /** Read a C array. @version 1.0 */
77 : template <class T>
78 6 : DataIStream& operator>>(Array<T> array)
79 : {
80 6 : _readArray(array, boost::has_trivial_copy<T>());
81 6 : return *this;
82 : }
83 :
84 : /**
85 : * Read a lunchbox::RefPtr. Refcount has to managed by caller.
86 : * @version 1.1
87 : */
88 : template <class T>
89 : DataIStream& operator>>(lunchbox::RefPtr<T>&);
90 :
91 : /** Read a lunchbox::Buffer. @version 1.0 */
92 : template <class T>
93 : DataIStream& operator>>(lunchbox::Buffer<T>&);
94 :
95 : /** Read a std::vector of serializable items. @version 1.0 */
96 : template <class T>
97 : DataIStream& operator>>(std::vector<T>&);
98 :
99 : /** Read a std::map of serializable items. @version 1.0 */
100 : template <class K, class V>
101 : DataIStream& operator>>(std::map<K, V>&);
102 :
103 : /** Read a std::set of serializable items. @version 1.0 */
104 : template <class T>
105 : DataIStream& operator>>(std::set<T>&);
106 :
107 : /** Read an unordered_map of serializable items. @version 1.0 */
108 : template <class K, class V>
109 : DataIStream& operator>>(std::unordered_map<K, V>&);
110 :
111 : /** Read an unordered_set of serializable items. @version 1.0 */
112 : template <class T>
113 : DataIStream& operator>>(std::unordered_set<T>&);
114 :
115 : /** @internal
116 : * Deserialize child objects.
117 : *
118 : * Existing children are synced to the new version. New children are created
119 : * by calling the <code>void create( C** child )</code> method on the
120 : * object, and are registered or mapped to the object's session. Removed
121 : * children are released by calling the <code>void release( C* )</code>
122 : * method on the object. The resulting child vector is created in
123 : * result. The old and result vector can be the same object, the result
124 : * vector is cleared and rebuild completely.
125 : */
126 : template <typename O, typename C>
127 : void deserializeChildren(O* object, const std::vector<C*>& old,
128 : std::vector<C*>& result);
129 :
130 : /** @deprecated
131 : * Get the pointer to the remaining data in the current buffer.
132 : *
133 : * The usage of this method is discouraged, no endian conversion or bounds
134 : * checking is performed by the DataIStream on the returned raw pointer.
135 : *
136 : * The buffer is advanced by the given size. If not enough data is present,
137 : * 0 is returned and the buffer is unchanged.
138 : *
139 : * The data written to the DataOStream by the sender is bucketized, it is
140 : * sent in multiple blocks. The remaining buffer and its size points into
141 : * one of the buffers, i.e., not all the data sent is returned by this
142 : * function. However, a write operation on the other end is never segmented,
143 : * that is, if the application writes n bytes to the DataOStream, a
144 : * symmetric read from the DataIStream has at least n bytes available.
145 : *
146 : * @param size the number of bytes to advance the buffer
147 : * @version 1.0
148 : */
149 : CO_API const void* getRemainingBuffer(const uint64_t size);
150 :
151 : /**
152 : * @return the size of the remaining data in the current buffer.
153 : * @version 1.0
154 : */
155 : CO_API uint64_t getRemainingBufferSize();
156 :
157 : /** @internal @return true if any data was read. */
158 : bool wasUsed() const;
159 :
160 : /** @return true if not all data has been read. @version 1.0 */
161 84 : bool hasData() { return _checkBuffer(); }
162 : /** @return the provider of the istream. */
163 : CO_API virtual NodePtr getRemoteNode() const = 0;
164 :
165 : /** @return the receiver of the istream. */
166 : CO_API virtual LocalNodePtr getLocalNode() const = 0;
167 : //@}
168 :
169 : protected:
170 : /** @name Internal */
171 : //@{
172 : CO_API DataIStream();
173 : CO_API virtual ~DataIStream();
174 :
175 : virtual bool getNextBuffer(CompressorInfo& info, uint32_t& nChunks,
176 : const void*& chunkData, uint64_t& size) = 0;
177 : //@}
178 :
179 : private:
180 : detail::DataIStream* const _impl;
181 :
182 : /** Read a number of bytes from the stream into a buffer. */
183 : CO_API void _read(void* data, uint64_t size);
184 :
185 : /**
186 : * Check that the current buffer has data left, get the next buffer is
187 : * necessary, return false if no data is left.
188 : */
189 : CO_API bool _checkBuffer();
190 : CO_API void _reset();
191 :
192 : const uint8_t* _decompress(const void* data, const CompressorInfo& info,
193 : uint32_t nChunks, uint64_t dataSize);
194 :
195 : /** Read a vector of trivial data. */
196 : template <class T>
197 4 : DataIStream& _readFlatVector(std::vector<T>& value)
198 : {
199 4 : uint64_t nElems = 0;
200 4 : *this >> nElems;
201 4 : LBASSERTINFO(nElems < LB_BIT48,
202 : "Out-of-sync DataIStream: " << nElems << " elements?");
203 4 : value.resize(size_t(nElems));
204 4 : if (nElems > 0)
205 4 : *this >> Array<T>(&value.front(), nElems);
206 4 : return *this;
207 : }
208 :
209 : /** Read a plain data item. */
210 : template <class T>
211 3409599 : void _read(T& value, const boost::true_type&)
212 : {
213 3409599 : _read(&value, sizeof(value));
214 3409626 : }
215 :
216 : /** Read a non-plain data item. */
217 : template <class T>
218 : void _read(T& value, const boost::false_type&)
219 : {
220 : _readSerializable(value, boost::is_base_of<servus::Serializable, T>());
221 : }
222 :
223 : /** Read a serializable object. */
224 : template <class T>
225 : void _readSerializable(T& value, const boost::true_type&);
226 :
227 : /** Read an Array of POD data */
228 : template <class T>
229 : void _readArray(Array<T>, const boost::true_type&);
230 :
231 : /** Read an Array of non-POD data */
232 : template <class T>
233 : void _readArray(Array<T>, const boost::false_type&);
234 : };
235 : }
236 :
237 : #include "dataIStream.ipp" // template implementation
238 :
239 : #endif // CO_DATAISTREAM_H
|