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 | |