Line data Source code
1 :
2 : /* Copyright (c) 2012-2017, Daniel Nachbaur <danielnachbaur@gmail.com>
3 : * Stefan.Eilemann@epfl.ch
4 : *
5 : * This library is free software; you can redistribute it and/or modify it under
6 : * the terms of the GNU Lesser General Public License version 2.1 as published
7 : * by the Free Software Foundation.
8 : *
9 : * This library is distributed in the hope that it will be useful, but WITHOUT
10 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 : * details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public License
15 : * along with this library; if not, write to the Free Software Foundation, Inc.,
16 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 : */
18 :
19 : #include <co/object.h>
20 : #include <co/objectVersion.h>
21 : #include <lunchbox/algorithm.h> // find_if
22 : #include <servus/serializable.h> // used inline
23 :
24 : namespace co
25 : {
26 : /** @name Specialized input operators */
27 : //@{
28 : /** Read a std::string. */
29 : template <>
30 383040 : inline DataIStream& DataIStream::operator>>(std::string& str)
31 : {
32 383040 : uint64_t nElems = 0;
33 383040 : *this >> nElems;
34 383040 : const uint64_t maxElems = getRemainingBufferSize();
35 383040 : LBASSERTINFO(nElems <= maxElems, nElems << " > " << maxElems);
36 383040 : if (nElems == 0)
37 371909 : str.clear();
38 11131 : else if (nElems <= maxElems)
39 11131 : str.assign(static_cast<const char*>(getRemainingBuffer(nElems)),
40 22262 : size_t(nElems));
41 : else
42 0 : str.assign(static_cast<const char*>(getRemainingBuffer(maxElems)),
43 0 : size_t(maxElems));
44 383040 : return *this;
45 : }
46 :
47 : /** Deserialize an object (id+version). */
48 : template <>
49 : inline DataIStream& DataIStream::operator>>(Object*& object)
50 : {
51 : ObjectVersion data;
52 : *this >> data;
53 : LBASSERT(object->getID() == data.identifier);
54 : object->sync(data.version);
55 : return *this;
56 : }
57 :
58 : /** Deserialize an inline serializable object. */
59 : template <class T>
60 : void DataIStream::_readSerializable(T& object, const boost::true_type&)
61 : {
62 : const size_t size = read<size_t>();
63 : object.fromBinary(getRemainingBuffer(size), size);
64 : }
65 :
66 : /** @cond IGNORE */
67 : template <class T>
68 4 : void DataIStream::_readArray(Array<T> array, const boost::true_type&)
69 : {
70 4 : _read(array.data, array.getNumBytes());
71 4 : }
72 :
73 : /** Read an Array of non-POD data */
74 : template <class T>
75 1 : void DataIStream::_readArray(Array<T> array, const boost::false_type&)
76 : {
77 3 : for (size_t i = 0; i < array.num; ++i)
78 2 : *this >> array.data[i];
79 1 : }
80 :
81 : template <>
82 1 : inline void DataIStream::_readArray(Array<void> array, const boost::false_type&)
83 : {
84 1 : _read(array.data, array.getNumBytes());
85 1 : }
86 :
87 : template <class T>
88 33 : inline DataIStream& DataIStream::operator>>(lunchbox::RefPtr<T>& ptr)
89 : {
90 33 : T* object = 0;
91 33 : *this >> object;
92 33 : ptr = object;
93 33 : return *this;
94 : }
95 :
96 : template <class T>
97 : inline DataIStream& DataIStream::operator>>(lunchbox::Buffer<T>& buffer)
98 : {
99 : uint64_t nElems = 0;
100 : *this >> nElems;
101 : LBASSERTINFO(nElems < LB_BIT48,
102 : "Out-of-sync co::DataIStream: " << nElems << " elements?");
103 : buffer.resize(nElems);
104 : return *this >> Array<T>(buffer.getData(), nElems);
105 : }
106 :
107 : template <class T>
108 2 : inline DataIStream& DataIStream::operator>>(std::vector<T>& value)
109 : {
110 2 : uint64_t nElems = 0;
111 2 : *this >> nElems;
112 2 : value.resize(nElems);
113 5 : for (uint64_t i = 0; i < nElems; ++i)
114 3 : *this >> value[i];
115 2 : return *this;
116 : }
117 :
118 : template <class K, class V>
119 : inline DataIStream& DataIStream::operator>>(std::map<K, V>& map)
120 : {
121 : map.clear();
122 : uint64_t nElems = 0;
123 : *this >> nElems;
124 : for (uint64_t i = 0; i < nElems; ++i)
125 : {
126 : typename std::map<K, V>::key_type key;
127 : typename std::map<K, V>::mapped_type value;
128 : *this >> key >> value;
129 : map.insert(std::make_pair(key, value));
130 : }
131 : return *this;
132 : }
133 :
134 : template <class T>
135 : inline DataIStream& DataIStream::operator>>(std::set<T>& value)
136 : {
137 : value.clear();
138 : uint64_t nElems = 0;
139 : *this >> nElems;
140 : for (uint64_t i = 0; i < nElems; ++i)
141 : {
142 : T item;
143 : *this >> item;
144 : value.insert(item);
145 : }
146 : return *this;
147 : }
148 :
149 : template <class K, class V>
150 : inline DataIStream& DataIStream::operator>>(std::unordered_map<K, V>& map)
151 : {
152 : map.clear();
153 : uint64_t nElems = 0;
154 : *this >> nElems;
155 : for (uint64_t i = 0; i < nElems; ++i)
156 : map.insert({read<K>(), read<V>()});
157 : return *this;
158 : }
159 :
160 : template <class T>
161 : inline DataIStream& DataIStream::operator>>(std::unordered_set<T>& value)
162 : {
163 : value.clear();
164 : uint64_t nElems = 0;
165 : *this >> nElems;
166 : for (uint64_t i = 0; i < nElems; ++i)
167 : value.insert(read<T>());
168 : return *this;
169 : }
170 :
171 : namespace
172 : {
173 : class ObjectFinder
174 : {
175 : public:
176 : explicit ObjectFinder(const uint128_t& id)
177 : : _id(id)
178 : {
179 : }
180 : bool operator()(co::Object* candidate) { return candidate->getID() == _id; }
181 : private:
182 : const uint128_t _id;
183 : };
184 : }
185 :
186 : template <typename O, typename C>
187 : inline void DataIStream::deserializeChildren(O* object,
188 : const std::vector<C*>& old_,
189 : std::vector<C*>& result)
190 : {
191 : ObjectVersions versions;
192 : *this >> versions;
193 : std::vector<C*> old = old_;
194 :
195 : // rebuild vector from serialized list
196 : result.clear();
197 : for (ObjectVersions::const_iterator i = versions.begin();
198 : i != versions.end(); ++i)
199 : {
200 : const ObjectVersion& version = *i;
201 :
202 : if (version.identifier == uint128_t())
203 : {
204 : result.push_back(0);
205 : continue;
206 : }
207 :
208 : typename std::vector<C*>::iterator j =
209 : lunchbox::find_if(old, ObjectFinder(version.identifier));
210 :
211 : if (j == old.end()) // previously unknown child
212 : {
213 : C* child = 0;
214 : object->create(&child);
215 : LocalNodePtr localNode = object->getLocalNode();
216 : LBASSERT(child);
217 : LBASSERT(!object->isMaster());
218 :
219 : LBCHECK(localNode->mapObject(child, version));
220 : result.push_back(child);
221 : }
222 : else
223 : {
224 : C* child = *j;
225 : old.erase(j);
226 : if (object->isMaster())
227 : child->sync(VERSION_HEAD);
228 : else
229 : child->sync(version.version);
230 :
231 : result.push_back(child);
232 : }
233 : }
234 :
235 : while (!old.empty()) // removed children
236 : {
237 : C* child = old.back();
238 : old.pop_back();
239 : if (!child)
240 : continue;
241 :
242 : if (child->isAttached() && !child->isMaster())
243 : {
244 : LocalNodePtr localNode = object->getLocalNode();
245 : localNode->unmapObject(child);
246 : }
247 : object->release(child);
248 : }
249 : }
250 : /** @endcond */
251 :
252 : /** Optimized specialization to read a std::vector of uint8_t. */
253 : template <>
254 : inline DataIStream& DataIStream::operator>>(std::vector<uint8_t>& value)
255 : {
256 : return _readFlatVector(value);
257 : }
258 :
259 : /** Optimized specialization to read a std::vector of uint16_t. */
260 : template <>
261 : inline DataIStream& DataIStream::operator>>(std::vector<uint16_t>& value)
262 : {
263 : return _readFlatVector(value);
264 : }
265 :
266 : /** Optimized specialization to read a std::vector of int16_t. */
267 : template <>
268 : inline DataIStream& DataIStream::operator>>(std::vector<int16_t>& value)
269 : {
270 : return _readFlatVector(value);
271 : }
272 :
273 : /** Optimized specialization to read a std::vector of uint32_t. */
274 : template <>
275 : inline DataIStream& DataIStream::operator>>(std::vector<uint32_t>& value)
276 : {
277 : return _readFlatVector(value);
278 : }
279 :
280 : /** Optimized specialization to read a std::vector of int32_t. */
281 : template <>
282 : inline DataIStream& DataIStream::operator>>(std::vector<int32_t>& value)
283 : {
284 : return _readFlatVector(value);
285 : }
286 :
287 : /** Optimized specialization to read a std::vector of uint64_t. */
288 : template <>
289 : inline DataIStream& DataIStream::operator>>(std::vector<uint64_t>& value)
290 : {
291 : return _readFlatVector(value);
292 : }
293 :
294 : /** Optimized specialization to read a std::vector of int64_t. */
295 : template <>
296 : inline DataIStream& DataIStream::operator>>(std::vector<int64_t>& value)
297 : {
298 : return _readFlatVector(value);
299 : }
300 :
301 : /** Optimized specialization to read a std::vector of float. */
302 : template <>
303 : inline DataIStream& DataIStream::operator>>(std::vector<float>& value)
304 : {
305 : return _readFlatVector(value);
306 : }
307 :
308 : /** Optimized specialization to read a std::vector of double. */
309 : template <>
310 1 : inline DataIStream& DataIStream::operator>>(std::vector<double>& value)
311 : {
312 1 : return _readFlatVector(value);
313 : }
314 :
315 : /** Optimized specialization to read a std::vector of ObjectVersion. */
316 : template <>
317 3 : inline DataIStream& DataIStream::operator>>(std::vector<ObjectVersion>& value)
318 : {
319 3 : return _readFlatVector(value);
320 : }
321 : //@}
322 : }
|