1/*!
2 * This file contains the implemetation of packer and unpacker for std vector
3 * Created on: Jan 5, 2016
4 * Author: Yaroslav Zaluzhnyi
5 */
6
7
8 //! Structures that do a nested packing, depending on the existence of 'pack' function inside of the object
9 //There is no pack() inside
10 template<bool cond, typename T1, typename Memory1, int ... prp>
11 struct pack_cond
12 {
13 //! Serialize the object
14 void packing(ExtPreAlloc<Memory1> & mem, const openfpm::vector<T1> & obj, Pack_stat & sts)
15 {
16 //Call an array primitive packer
17 Packer<openfpm::vector<T1>, Memory1, PACKER_ARRAY_PRIMITIVE>::pack(mem,obj,sts,obj.size());
18 }
19 };
20
21 //! Structures that do a nested packing, depending on the existence of 'pack' function inside of the object
22 //There is pack() inside
23 template<typename T1, typename Memory1, int ... prp>
24 struct pack_cond<true, T1, Memory1, prp...>
25 {
26 //! Serialize the object
27 void packing(ExtPreAlloc<Memory1> & mem, const openfpm::vector<T1> & obj, Pack_stat & sts)
28 {
29 //Pack the size of a vector
30 Packer<size_t, Memory1>::pack(mem,obj.size(),sts);
31
32 //Call a packer in nested way
33 for (size_t i = 0; i < obj.size(); i++) {
34 obj.get(i).template pack<prp...>(mem,sts);
35 }
36 }
37 };
38
39 //! Structures that do a nested unpacking, depending on the existence of 'pack' function inside the object
40 // There is no pack() inside
41 template<bool cond, typename T1, typename Memory1, int ... prp>
42 struct unpack_cond
43 {
44 //! De-serialize the object
45 void unpacking(ExtPreAlloc<Memory1> & mem, openfpm::vector<T1> & obj, Unpack_stat & ps)
46 {
47 //Call the array of primitives unpacker
48 Unpacker<openfpm::vector<T1>, Memory1, PACKER_ARRAY_PRIMITIVE>::unpack(mem,obj,ps);
49 }
50
51 };
52
53 //! Structures that do a nested unpacking, depending on the existence of 'pack' function inside the object
54 // There is pack() inside
55 template<typename T1, typename Memory1, int ... prp>
56 struct unpack_cond<true, T1, Memory1, prp...>
57 {
58 //! De-serialize the object
59 void unpacking(ExtPreAlloc<Memory1> & mem, openfpm::vector<T1> & obj, Unpack_stat & ps)
60 {
61 //Unpacking a size of a source vector
62 size_t u1 = 0;
63 Unpacker<size_t, Memory1>::unpack(mem,u1,ps);
64
65 //Resize a destination vector
66 obj.resize(u1);
67
68 //Call an unpacker in nested way
69
70 //std::cout<< demangle(typeid(obj.get(1)).name()) << std::endl;
71 for (size_t i = 0; i < obj.size(); i++) {
72 obj.get(i).template unpack<prp...>(mem,ps);
73 }
74 }
75 };
76
77 //! Structures that do a pack request, depending on the existence of 'packRequest' function inside of the object
78 //There is no packRequest() inside
79 template<bool cond, typename T1, int ... prp>
80 struct packRequest_cond
81 {
82 //! Calculate the size required to serialize the object
83 void packingRequest(const openfpm::vector<T1> & obj, size_t & req)
84 {
85 //Pushback a size of number of elements of the internal vectors
86 req += sizeof(obj.size());
87
88 size_t alloc_ele = obj.template packMem<prp...>(obj.size(),0);
89
90 req += alloc_ele;
91 }
92
93 };
94
95 //! Structures that do a pack request, depending on the existence of 'packRequest' function inside of the object
96 //There is packRequest() inside
97 template<typename T1, int ... prp>
98 struct packRequest_cond<true, T1, prp...>
99 {
100 //! Calculate the size required to serialize the object
101 void packingRequest(const openfpm::vector<T1> & obj, size_t & req)
102 {
103 //Pushback a size of number of elements of the external vectors
104 req += sizeof(obj.size());
105
106 //Call an packRequest in nested way
107 for (size_t i = 0; i < obj.size(); i++)
108 {
109 obj.get(i).template packRequest<prp...>(req);
110 }
111 }
112 };
113
114 //! Structures that calculate memory for an object, depending on the existence of 'packMem' function inside the object
115 //There is no packMem() inside
116 template<bool cond, typename T1, int ... prp>
117 struct packMem_cond
118 {
119 //! Calculate the bytes required to serialize the vector
120 size_t packMemory(const T1 & obj, size_t n, size_t e)
121 {
122 return obj.size() * sizeof(T);
123 }
124 };
125
126 //! Structures that calculate memory for an object, depending on the existence of 'packMem' function inside the object
127 // There is packMem() inside
128 template<typename T1, int ... prp>
129 struct packMem_cond<true, T1, prp...>
130 {
131 //! Calculate the bytes required to serialize the vector
132 size_t packMemory(const T1 & obj, size_t n, size_t e)
133 {
134 size_t res = 0;
135
136 for (size_t i = 0; i < n; i++) {
137 res += obj.get(i).template packMem<prp...>(obj.get(i).size(),0);
138 }
139
140 return res;
141 }
142 };
143
144
145 //! Indicate that the vector has a packer function
146 static bool pack()
147 {
148 return true;
149 }
150
151 //! Indicate that the vector has the function packRequest
152 static bool packRequest()
153 {
154 return true;
155 }
156
157 //! Indicate that the vector has the function pack Memory
158 static bool packMem()
159 {
160 return true;
161 }
162
163
164 /*! \brief pack a vector
165 *
166 * \param mem preallocated memory where to pack the vector
167 * \param sts pack-stat info
168 *
169 */
170 template<int ... prp> void pack(ExtPreAlloc<HeapMemory> & mem, Pack_stat & sts) const
171 {
172 //Call a nested packer
173 pack_cond<has_pack<T>::type::value, T,HeapMemory, prp...> p;
174 p.packing(mem, *this, sts);
175
176 }
177
178 /*! \brief Insert an allocation request into the vector
179 *
180 * \tparam prp properties to pack
181 *
182 * \param req counter with the byte required to pack the vector
183 *
184 */
185 template<int ... prp> void packRequest(size_t & req) const
186 {
187 //Call a nested pack request
188 packRequest_cond<has_packRequest<T>::value, T, prp...> pr;
189 pr.packingRequest(*this, req);
190
191 }
192
193 /*! \brief unpack a vector
194 *
195 * \warning the properties should match the packed properties,
196 *
197 * \param mem preallocated memory from where to unpack the vector
198 * \param ps unpack info
199 *
200 */
201 template<unsigned int ... prp> void unpack(ExtPreAlloc<HeapMemory> & mem, Unpack_stat & ps)
202 {
203 unpack_cond<has_pack<T>::type::value, T, HeapMemory, prp...> unp;
204 unp.unpacking(mem, *this, ps);
205
206 }
207
208 /*! \brief Save this object into file
209 *
210 * \param file filename
211 *
212 * \return true if succed
213 *
214 */
215 bool save(const std::string & file) const
216 {
217 size_t req = 0;
218
219 Packer<openfpm::vector<T,HeapMemory,memory_traits_lin,grow_policy_double,STD_VECTOR>,HeapMemory>::packRequest(*this,req);
220
221 // allocate the memory
222 HeapMemory pmem;
223 //pmem.allocate(req);
224 ExtPreAlloc<HeapMemory> mem(req,pmem);
225
226 //Packing
227
228 Pack_stat sts;
229 Packer<openfpm::vector<T,HeapMemory,memory_traits_lin,grow_policy_double,STD_VECTOR>,HeapMemory>::pack(mem,*this,sts);
230
231 // Save into a binary file
232 std::ofstream dump (file, std::ios::out | std::ios::binary);
233 if (dump.is_open() == false)
234 return false;
235 dump.write ((const char *)pmem.getPointer(), pmem.size());
236
237 return true;
238 }
239
240 /*! \brief Load this object from file
241 *
242 * \param file filename
243 *
244 * \return true if succed
245 *
246 */
247 bool load(const std::string & file)
248 {
249 std::ifstream fs (file, std::ios::in | std::ios::binary | std::ios::ate );
250 if (fs.is_open() == false)
251 {
252 std::cerr << __FILE__ << ":" << __LINE__ << " error, opening file: " << file << std::endl;
253 return false;
254 }
255
256 // take the size of the file
257 size_t sz = fs.tellg();
258
259 fs.close();
260
261 // reopen the file without ios::ate to read
262 std::ifstream input (file, std::ios::in | std::ios::binary );
263 if (input.is_open() == false)
264 return false;
265
266 // Create the HeapMemory and the ExtPreAlloc memory
267 size_t req = 0;
268 req += sz;
269 HeapMemory pmem;
270 ExtPreAlloc<HeapMemory> mem(req,pmem);
271
272 mem.allocate(pmem.size());
273
274 // read
275 input.read((char *)pmem.getPointer(), sz);
276
277 //close the file
278 input.close();
279
280 //Unpacking
281 Unpack_stat ps;
282
283 Unpacker<openfpm::vector<T,HeapMemory,memory_traits_lin,grow_policy_double,STD_VECTOR>,HeapMemory>::unpack(mem,*this,ps);
284
285 return true;
286 }
287