00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef _UIUC_CHARM_PUP_STL_H
00016 #define _UIUC_CHARM_PUP_STL_H
00017
00018 #include <conv-config.h>
00019
00020
00021
00022
00023 #include <algorithm>
00024 #include <array>
00025 #include <set>
00026 #include <vector>
00027 #include <deque>
00028 #include <forward_list>
00029 #include <list>
00030 #include <map>
00031 #include <memory>
00032 #include <random>
00033 #include <tuple>
00034 #include <unordered_map>
00035 #include <unordered_set>
00036 #include <string>
00037 #include <complex>
00038 #include <utility>
00039 #include "pup.h"
00040
00041 #include <cstddef>
00042
00043 namespace PUP {
00044
00045
00046 template <class A,class B>
00047 inline void operator|(er &p,typename std::pair<A,B> &v);
00048 template <class A,class B>
00049 inline void operator|(er &p,typename std::pair<const A,B> &v);
00050 template <class T>
00051 inline void operator|(er &p,std::complex<T> &v);
00052 template <class T>
00053 inline void operator|(er &p, std::unique_ptr<T, std::default_delete<T>> &ptr);
00054 template <class charType>
00055 inline void operator|(er &p,typename std::basic_string<charType> &v);
00056 inline void operator|(er &p,std::string &v);
00057 template <class container>
00058 inline size_t PUP_stl_container_size(er &p,container &c);
00059 template <class container, class dtype>
00060 inline void PUP_stl_container_items(er &p, container &c, size_t nElem);
00061 template <> inline void PUP_stl_container_items<std::vector<bool>,bool>(er &p, std::vector<bool> &c, size_t nElem);
00062 template <class container,class dtype>
00063 inline void PUP_stl_container(er &p,container &c);
00064 template <class container,class dtype>
00065 inline void PUP_stl_map(er &p,container &c);
00066 template <class T>
00067 inline void operator|(er &p,typename std::vector<T> &v);
00068 template <class T>
00069 inline void operator|(er &p,typename std::deque<T> &d);
00070 template <class T>
00071 inline void operator|(er &p,typename std::list<T> &v);
00072 template <class T>
00073 inline void operator|(er &p,typename std::forward_list<T> &fl);
00074 template <class V,class T,class Cmp>
00075 inline void operator|(er &p,typename std::map<V,T,Cmp> &m);
00076 template <class V,class T,class Cmp>
00077 inline void operator|(er &p,typename std::multimap<V,T,Cmp> &m);
00078 template <class T>
00079 inline void operator|(er &p,typename std::set<T> &m);
00080 template <class T,class Cmp>
00081 inline void operator|(er &p,typename std::multiset<T,Cmp> &m);
00082 template <> inline void operator|(er &p,std::vector<bool> &v);
00083
00084 template <class A,class B>
00085 inline void operator|(er &p,typename std::pair<A,B> &v)
00086 {
00087 p.syncComment(sync_index);
00088 p|v.first;
00089 p.syncComment(sync_item);
00090 p|v.second;
00091 }
00092
00093 template <class A,class B>
00094 inline void operator|(er &p,typename std::pair<const A,B> &v)
00095 {
00096 p.syncComment(sync_index);
00097 p|*(A *)&v.first;
00098 p.syncComment(sync_item);
00099 p|v.second;
00100 }
00101 template <class T>
00102 inline void operator|(er &p,std::complex<T> &v)
00103 {
00104 T re=v.real(), im=v.imag();
00105 p|re; p|im;
00106 v=std::complex<T>(re,im);
00107 }
00108 template <class charType>
00109 inline void operator|(er &p,typename std::basic_string<charType> &v)
00110 {
00111 size_t nChar=v.length();
00112 p|nChar;
00113 if (p.isUnpacking()) {
00114 charType *buf=new charType[nChar];
00115 p(buf,nChar);
00116 v=std::basic_string<charType>(buf,nChar);
00117 delete[] buf;
00118 }
00119 else {
00120
00121 p((charType *)v.data(),nChar);
00122 }
00123 }
00124 inline void operator|(er &p,std::string &v)
00125 {
00126 p.syncComment(sync_begin_object,"std::string");
00127 size_t nChar=v.length();
00128 p|nChar;
00129 if (p.isUnpacking()) {
00130 char *buf=new char[nChar];
00131 p(buf,nChar);
00132 v=std::basic_string<char>(buf,nChar);
00133 delete[] buf;
00134 }
00135 else {
00136
00137 p((char *)v.data(),nChar);
00138 }
00139 p.syncComment(sync_end_object);
00140 }
00141
00142
00143
00144 template <class container>
00145 inline void reserve_if_applicable(container &c, size_t nElem)
00146 {
00147 c.clear();
00148 c.reserve(nElem);
00149 }
00150 template <class dtype>
00151 inline void reserve_if_applicable(std::deque<dtype> &c, size_t nElem)
00152 {
00153 c.clear();
00154 }
00155 template <class dtype>
00156 inline void reserve_if_applicable(std::list<dtype> &c, size_t nElem)
00157 {
00158 c.clear();
00159 }
00160 template <class dtype>
00161 inline void reserve_if_applicable(std::set<dtype> &c, size_t nElem)
00162 {
00163 c.clear();
00164 }
00165 template <class dtype>
00166 inline void reserve_if_applicable(std::multiset<dtype> &c, size_t nElem)
00167 {
00168 c.clear();
00169 }
00170 template <class K, class V>
00171 inline void reserve_if_applicable(std::map<K, V> &c, size_t nElem)
00172 {
00173 c.clear();
00174 }
00175 template <class K, class V>
00176 inline void reserve_if_applicable(std::multimap<K, V> &c, size_t nElem)
00177 {
00178 c.clear();
00179 }
00180
00181 template <class container, class... Args>
00182 inline void emplace(container &c, Args&&... args)
00183 {
00184 c.emplace(std::forward<Args>(args)...);
00185 }
00186 template <class dtype, class... Args>
00187 inline void emplace(std::vector<dtype> &c, Args&&... args)
00188 {
00189 c.emplace_back(std::forward<Args>(args)...);
00190 }
00191 template <class dtype, class... Args>
00192 inline void emplace(std::deque<dtype> &c, Args&&... args)
00193 {
00194 c.emplace_back(std::forward<Args>(args)...);
00195 }
00196 template <class dtype, class... Args>
00197 inline void emplace(std::list<dtype> &c, Args&&... args)
00198 {
00199 c.emplace_back(std::forward<Args>(args)...);
00200 }
00201
00202
00203 template <class container>
00204 inline size_t PUP_stl_container_size(er &p,container &c) {
00205 size_t nElem=c.size();
00206 p|nElem;
00207 return nElem;
00208 }
00209
00210
00211 template <class container, class dtype>
00212 inline void PUP_stl_container_items(er &p, container &c, size_t nElem)
00213 {
00214 if (p.isUnpacking())
00215 {
00216 reserve_if_applicable(c, nElem);
00217 for (size_t i = 0; i < nElem; ++i)
00218 {
00219 p.syncComment(sync_item);
00220 detail::TemporaryObjectHolder<dtype> n;
00221 p|n;
00222 emplace(c, std::move(n.t));
00223 }
00224 }
00225 else
00226 {
00227 for (typename container::iterator it=c.begin(); it!=c.end(); ++it)
00228 {
00229 p.syncComment(sync_item);
00230
00231 p|*(dtype *)&(*it);
00232 }
00233 }
00234 }
00235
00236
00237 template<>
00238 inline void PUP_stl_container_items<std::vector<bool>, bool>(er &p, std::vector<bool> &c, size_t nElem)
00239 {
00240 if (p.isUnpacking())
00241 c.resize(nElem);
00242
00243 std::deque<bool> q(c.begin(), c.end());
00244
00245 for (std::deque<bool>::iterator it = q.begin(); it != q.end(); it++)
00246 {
00247 p.syncComment(sync_item);
00248 p|*it;
00249 }
00250 }
00251
00252 template <class container,class dtype>
00253 inline void PUP_stl_container(er &p,container &c) {
00254 p.syncComment(sync_begin_array);
00255 size_t nElem=PUP_stl_container_size(p,c);
00256 PUP_stl_container_items<container, dtype>(p, c, nElem);
00257 p.syncComment(sync_end_array);
00258 }
00259
00260
00261 template <class dtype>
00262 inline void PUP_stl_forward_list(er &p,std::forward_list<dtype> &c) {
00263 p.syncComment(sync_begin_array);
00264 size_t nElem;
00265 if (p.isUnpacking())
00266 {
00267 p | nElem;
00268 auto iter = c.before_begin();
00269 for (size_t i = 0; i < nElem; ++i)
00270 {
00271 p.syncComment(sync_item);
00272 detail::TemporaryObjectHolder<dtype> n;
00273 p|n;
00274 iter = c.emplace_after(iter, std::move(n.t));
00275 }
00276 }
00277 else
00278 {
00279 nElem = 0;
00280 for (auto& n: c)
00281 {
00282 ++nElem;
00283 }
00284 p | nElem;
00285 for (auto& n : c)
00286 {
00287 p.syncComment(sync_item);
00288 p | n;
00289 }
00290 }
00291 p.syncComment(sync_end_array);
00292 }
00293
00294 template <class container, class K, class V>
00295 inline void PUP_stl_map(er &p,container &c) {
00296 p.syncComment(sync_begin_list);
00297 size_t nElem=PUP_stl_container_size(p,c);
00298 if (p.isUnpacking())
00299 {
00300 reserve_if_applicable(c, nElem);
00301 for (size_t i=0;i<nElem;i++)
00302 {
00303 detail::TemporaryObjectHolder<K> k;
00304 detail::TemporaryObjectHolder<V> v;
00305
00306
00307 p.syncComment(sync_index);
00308 p | k;
00309 p.syncComment(sync_item);
00310 p | v;
00311
00312 c.emplace(std::piecewise_construct, std::forward_as_tuple(std::move(k.t)), std::forward_as_tuple(std::move(v.t)));
00313 }
00314 }
00315 else
00316 {
00317 for (auto& kv : c)
00318 {
00319 p | kv;
00320 }
00321 }
00322 p.syncComment(sync_end_list);
00323 }
00324
00325 template <class T>
00326 inline void operator|(er &p, typename std::vector<T> &v) {
00327 if (PUP::as_bytes<T>::value) {
00328 size_t nElem = PUP_stl_container_size(p, v);
00329 if (p.isUnpacking()) {
00330 v.resize(nElem);
00331 v.shrink_to_fit();
00332 }
00333 PUParray(p, v.data(), nElem);
00334 } else {
00335 PUP_stl_container<std::vector<T>, T>(p, v);
00336 }
00337 }
00338
00339 template <class T>
00340 inline void operator|(er &p,typename std::deque<T> &d)
00341 { PUP_stl_container<std::deque<T>,T>(p,d); }
00342 template <class T>
00343 inline void operator|(er &p,typename std::list<T> &v)
00344 { PUP_stl_container<std::list<T>,T>(p,v); }
00345 template <class T>
00346 inline void operator|(er &p,typename std::forward_list<T> &fl)
00347 { PUP_stl_forward_list<T>(p,fl); }
00348
00349 template <class V,class T,class Cmp>
00350 inline void operator|(er &p,typename std::map<V,T,Cmp> &m)
00351 { PUP_stl_map<std::map<V,T,Cmp>,V,T >(p,m); }
00352 template <class V,class T,class Cmp>
00353 inline void operator|(er &p,typename std::multimap<V,T,Cmp> &m)
00354 { PUP_stl_map<std::multimap<V,T,Cmp>,V,T >(p,m); }
00356 template <class V,class T,class Cmp>
00357 inline void operator|(er &p,typename std::unordered_map<V,T,Cmp> &m)
00358 { PUP_stl_map<std::unordered_map<V,T,Cmp>,V,T >(p,m); }
00359 template <class V,class T,class Cmp>
00360 inline void operator|(er &p,typename std::unordered_multimap<V,T,Cmp> &m)
00361 { PUP_stl_map<std::unordered_multimap<V,T,Cmp>,V,T >(p,m); }
00362
00363 template <class T>
00364 inline void operator|(er &p,typename std::set<T> &m)
00365 { PUP_stl_container<std::set<T>,T >(p,m); }
00366 template <class T,class Cmp>
00367 inline void operator|(er &p,typename std::multiset<T,Cmp> &m)
00368 { PUP_stl_container<std::multiset<T,Cmp>,T >(p,m); }
00369 template <class T>
00370 inline void operator|(er &p,typename std::unordered_set<T> &m)
00371 { PUP_stl_container<std::unordered_set<T>,T >(p,m); }
00372 template <class T,class Cmp>
00373 inline void operator|(er &p,typename std::unordered_multiset<T,Cmp> &m)
00374 { PUP_stl_container<std::unordered_multiset<T,Cmp>,T >(p,m); }
00375
00376
00377
00378 template <>
00379 inline void operator|(er &p,std::vector<bool> &v) {
00380 PUP_stl_container<std::vector<bool>, bool>(p, v);
00381 }
00382
00383
00384
00385
00386
00387 template <bool B>
00388 struct requires_impl {
00389 using template_error_type_failed_to_meet_requirements_on_template_parameters
00390 = std::nullptr_t;
00391 };
00392
00393 template <>
00394 struct requires_impl<false> {};
00395
00396 template <bool B>
00397 using Requires = typename requires_impl<
00398 B>::template_error_type_failed_to_meet_requirements_on_template_parameters;
00399
00400 template <typename T, std::size_t N,
00401 Requires<!PUP::as_bytes<T>::value> = nullptr>
00402 inline void pup(PUP::er& p, std::array<T, N>& a) {
00403 std::for_each(a.begin(), a.end(), [&p](T& t) { p | t; });
00404 }
00405
00406 template <typename T, std::size_t N,
00407 Requires<PUP::as_bytes<T>::value> = nullptr>
00408 inline void pup(PUP::er& p, std::array<T, N>& a) {
00409 PUParray(p, a.data(), N);
00410 }
00411
00412 template <typename T, std::size_t N>
00413 inline void operator|(er& p, std::array<T, N>& a) {
00414 pup(p, a);
00415 }
00416
00417 template <typename T, Requires<std::is_enum<T>::value> = nullptr>
00418 inline void operator|(PUP::er& p, T& s) {
00419 pup_bytes(&p, static_cast<void*>(&s), sizeof(T));
00420 }
00421
00422 template <size_t N = 0, typename... Args,
00423 Requires<0 == sizeof...(Args)> = nullptr>
00424 void pup_tuple_impl(PUP::er& , std::tuple<Args...>& ) {
00425 }
00426
00427 template <size_t N = 0, typename... Args,
00428 Requires<(0 < sizeof...(Args) && 0 == N)> = nullptr>
00429 void pup_tuple_impl(PUP::er& p, std::tuple<Args...>& t) {
00430 p | std::get<N>(t);
00431 }
00432
00433 template <size_t N, typename... Args,
00434 Requires<(sizeof...(Args) > 0 && N > 0)> = nullptr>
00435 void pup_tuple_impl(PUP::er& p, std::tuple<Args...>& t) {
00436 p | std::get<N>(t);
00437 pup_tuple_impl<N - 1>(p, t);
00438 }
00439
00440 template <typename... Args>
00441 inline void pup(PUP::er& p, std::tuple<Args...>& t) {
00442 pup_tuple_impl<sizeof...(Args) - 1>(p, t);
00443 }
00444
00445 template <typename... Args>
00446 inline void operator|(PUP::er& p, std::tuple<Args...>& t) {
00447 pup(p, t);
00448 }
00449
00450 template <typename T,
00451 Requires<!std::is_base_of<PUP::able, T>::value> = nullptr>
00452 inline void pup(PUP::er& p, std::unique_ptr<T>& t) {
00453 bool is_nullptr = nullptr == t;
00454 p | is_nullptr;
00455 if (!is_nullptr) {
00456 T* t1;
00457 if (p.isUnpacking()) {
00458 t1 = new T;
00459 } else {
00460 t1 = t.get();
00461 }
00462 p | *t1;
00463 if (p.isUnpacking()) {
00464 t.reset(t1);
00465 }
00466 }
00467 }
00468
00469 template <typename T, Requires<std::is_base_of<PUP::able, T>::value> = nullptr>
00470 inline void pup(PUP::er& p, std::unique_ptr<T>& t) {
00471 T* t1 = nullptr;
00472 if (p.isUnpacking()) {
00473 p | t1;
00474 t = std::unique_ptr<T>(t1);
00475 } else {
00476 t1 = t.get();
00477 p | t1;
00478 }
00479 }
00480
00481 template <typename T>
00482 inline void operator|(PUP::er& p, std::unique_ptr<T>& t) {
00483 pup(p, t);
00484 }
00485
00486
00487
00488
00489 template<
00490 class UIntType, size_t w, size_t n, size_t m, size_t r,
00491 UIntType a, size_t u, UIntType d, size_t s,UIntType b, size_t t,UIntType c, size_t l, UIntType f>
00492 inline void pup(PUP::er& p, std::mersenne_twister_engine<UIntType, w, n, m, r,
00493 a, u, d, s, b, t, c, l, f>& engine){
00494 std::stringstream o;
00495 std::string state;
00496
00497 if(p.isUnpacking()){
00498 p | state;
00499 o.str(state);
00500 o>>engine;
00501 }
00502 else{
00503 o<<engine;
00504 state=o.str();
00505 p | state;
00506 }
00507 }
00508
00509 template<class UIntType, size_t w, size_t n, size_t m, size_t r,
00510 UIntType a, size_t u, UIntType d, size_t s,UIntType b, size_t t,UIntType c, size_t l, UIntType f>
00511 inline void operator|(PUP::er& p, std::mersenne_twister_engine<UIntType, w, n, m, r,
00512 a, u, d, s, b, t, c, l, f>& engine) {
00513 pup(p,engine);
00514 }
00515
00516 template<class UIntType, UIntType a, UIntType c, UIntType m>
00517 inline void pup(PUP::er& p, std::linear_congruential_engine<UIntType, a, c, m>& engine){
00518 std::stringstream o;
00519 std::string state;
00520
00521 if(p.isUnpacking()){
00522 p | state;
00523 o.str(state);
00524 o>>engine;
00525 }
00526 else{
00527 o<<engine;
00528 state=o.str();
00529 p | state;
00530 }
00531 }
00532
00533 template<class UIntType, UIntType a, UIntType c, UIntType m>
00534 inline void operator|(PUP::er& p, std::linear_congruential_engine<UIntType, a, c, m>& engine) {
00535 pup(p,engine);
00536 }
00537
00538 template<class UIntType, size_t w, size_t s, size_t r>
00539 inline void pup(PUP::er& p, std::subtract_with_carry_engine<UIntType, w, s, r>& engine){
00540 std::stringstream o;
00541 std::string state;
00542
00543 if(p.isUnpacking()){
00544 p | state;
00545 o.str(state);
00546 o>>engine;
00547 }
00548 else{
00549 o<<engine;
00550 state=o.str();
00551 p | state;
00552 }
00553 }
00554
00555 template<class UIntType, size_t w, size_t s, size_t r>
00556 inline void operator|(PUP::er& p, std::subtract_with_carry_engine<UIntType, w, s, r>& engine) {
00557 pup(p,engine);
00558 }
00559
00560 template<class Engine, size_t P, size_t R>
00561 inline void pup(PUP::er& p, std::discard_block_engine<Engine, P, R>& engine) {
00562 std::stringstream o;
00563 std::string state;
00564
00565 if(p.isUnpacking()){
00566 p | state;
00567 o.str(state);
00568 o>>engine;
00569 }
00570 else{
00571 o<<engine;
00572 state=o.str();
00573 p | state;
00574 }
00575 }
00576
00577 template<class Engine, size_t P, size_t R>
00578 inline void operator|(PUP::er& p, std::discard_block_engine<Engine, P, R>& engine) {
00579 pup(p,engine);
00580 }
00581
00582 template<class Engine, std::size_t W, class UIntType>
00583 inline void pup(PUP::er& p, std::independent_bits_engine<Engine, W, UIntType>& engine) {
00584 std::stringstream o;
00585 std::string state;
00586
00587 if(p.isUnpacking()){
00588 p | state;
00589 o.str(state);
00590 o>>engine;
00591 }
00592 else{
00593 o<<engine;
00594 state=o.str();
00595 p | state;
00596 }
00597 }
00598
00599 template<class Engine, std::size_t W, class UIntType>
00600 inline void operator|(PUP::er& p, std::independent_bits_engine<Engine, W, UIntType>& engine) {
00601 pup(p,engine);
00602 }
00603
00604 template<class Engine, std::size_t K>
00605 inline void pup(PUP::er& p, std::shuffle_order_engine<Engine, K>& engine) {
00606 std::stringstream o;
00607 std::string state;
00608
00609 if(p.isUnpacking()){
00610 p | state;
00611 o.str(state);
00612 o>>engine;
00613 }
00614 else{
00615 o<<engine;
00616 state=o.str();
00617 p | state;
00618 }
00619 }
00620
00621 template<class Engine, std::size_t K>
00622 inline void operator|(PUP::er& p, std::shuffle_order_engine<Engine, K>& engine) {
00623 pup(p,engine);
00624 }
00625
00626 }
00627
00628 #endif