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