File indexing completed on 2021-02-14 12:44:52
0001
0002
0003
0004
0005 #ifndef GENERS_GENERICIO_HH_
0006 #define GENERS_GENERICIO_HH_
0007
0008 #include "Alignment/Geners/interface/IOPointeeType.hh"
0009 #include "Alignment/Geners/interface/binaryIO.hh"
0010
0011 #include "Alignment/Geners/interface/ArrayAdaptor.hh"
0012 #include "Alignment/Geners/interface/ClearIfPointer.hh"
0013 #include "Alignment/Geners/interface/StrippedType.hh"
0014
0015 namespace gs {
0016
0017
0018
0019
0020
0021
0022 template <class Stream, class Item>
0023 inline bool write_item(Stream &os, const Item &item, const bool writeClassId = true) {
0024 char *ps = nullptr;
0025 return process_const_item<GenericWriter>(item, os, ps, writeClassId);
0026 }
0027
0028
0029
0030
0031
0032
0033 template <class Stream, class Item>
0034 inline void restore_item(Stream &is, Item *item, const bool readClassId = true) {
0035 typedef std::vector<ClassId> State;
0036 assert(item);
0037 State state;
0038 const bool status = GenericReader<Stream, State, Item *, Int2Type<IOTraits<int>::ISPOINTER>>::process(
0039 item, is, &state, readClassId);
0040 if (is.fail())
0041 throw IOReadFailure("In gs::restore_item: input stream failure");
0042 if (!status)
0043 throw IOInvalidData("In gs::restore_item: invalid input stream data");
0044 }
0045
0046
0047
0048
0049
0050
0051
0052
0053 template <class Item, class Stream>
0054 inline CPP11_auto_ptr<Item> read_item(Stream &is, const bool readClassId = true) {
0055 typedef std::vector<ClassId> State;
0056 Item *item = nullptr;
0057 State state;
0058 const bool status = GenericReader<Stream, State, Item *, Int2Type<IOTraits<int>::ISNULLPOINTER>>::process(
0059 item, is, &state, readClassId);
0060 CPP11_auto_ptr<Item> ptr(item);
0061 if (is.fail())
0062 throw IOReadFailure("In gs::read_item: input stream failure");
0063 if (!status || item == nullptr)
0064 throw IOInvalidData("In gs::read_item: invalid input stream data");
0065 return ptr;
0066 }
0067
0068
0069
0070
0071
0072
0073
0074
0075 template <class Stream, class Item>
0076 inline bool write_array(Stream &os, Item *items, const std::size_t length) {
0077 char *ps = nullptr;
0078 return process_const_item<GenericWriter>(ArrayAdaptor<Item>(items, length), os, ps, false);
0079 }
0080
0081
0082
0083
0084
0085 template <class Stream, class Item>
0086 inline void read_array(Stream &is, Item *items, const std::size_t length) {
0087 typedef std::vector<ClassId> State;
0088 State state;
0089 ArrayAdaptor<Item> adap(items, length);
0090 const bool st = process_item<GenericReader>(adap, is, &state, false);
0091 if (is.fail())
0092 throw IOReadFailure("In gs::read_array: input stream failure");
0093 if (!st)
0094 throw IOInvalidData("In gs::read_array: invalid input stream data");
0095 }
0096 }
0097
0098 namespace gs {
0099 template <class Stream, class State, class Item, class Stage>
0100 struct GenericWriter2 : public GenericWriter<Stream, State, Item, Stage> {};
0101
0102 template <class Stream, class State, class Item, class Stage>
0103 struct GenericReader2 : public GenericReader<Stream, State, Item, Stage> {};
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139 template <class Stream, class State, class T>
0140 struct GenericWriter<Stream, State, T, Int2Type<IOTraits<int>::ISPOD>> {
0141 inline static bool process(const T &s, Stream &os, State *, const bool processClassId) {
0142 static const ClassId current(ClassId::makeId<T>());
0143 const bool status = processClassId ? current.write(os) : true;
0144 if (status)
0145 write_pod(os, s);
0146 return status && !os.fail();
0147 }
0148 };
0149
0150 template <class Stream, class State, class T>
0151 struct GenericReader<Stream, State, T, Int2Type<IOTraits<int>::ISPOD>> {
0152 inline static bool readIntoPtr(T *&ptr, Stream &str, State *, const bool processClassId) {
0153 CPP11_auto_ptr<T> myptr;
0154 if (ptr == nullptr)
0155 myptr = CPP11_auto_ptr<T>(new T());
0156 if (processClassId) {
0157 static const ClassId current(ClassId::makeId<T>());
0158 ClassId id(str, 1);
0159 current.ensureSameName(id);
0160 }
0161 read_pod(str, ptr ? ptr : myptr.get());
0162 if (str.fail())
0163 return false;
0164 if (ptr == nullptr)
0165 ptr = myptr.release();
0166 return true;
0167 }
0168
0169 inline static bool process(T &s, Stream &os, State *st, const bool processClassId) {
0170 T *ps = &s;
0171 return readIntoPtr(ps, os, st, processClassId);
0172 }
0173 };
0174
0175
0176
0177
0178
0179
0180 template <class Stream, class State, class Container>
0181 struct GenericWriter<Stream, State, Container, InContainerHeader> {
0182 inline static bool process(const Container &, Stream &os, State *, const bool processClassId) {
0183 typedef typename Container::value_type T;
0184
0185 static const ClassId current(ClassId::makeId<Container>());
0186 bool status = processClassId ? current.write(os) : true;
0187
0188
0189
0190
0191
0192 if (status && !(IOTraits<T>::IsPOD && IOTraits<Container>::IsContiguous)) {
0193 static const ClassId itemId(ClassId::makeId<T>());
0194 status = itemId.write(os);
0195 }
0196 return status;
0197 }
0198 };
0199
0200 template <class Stream, class State, class Container>
0201 struct GenericReader<Stream, State, Container, InContainerHeader> {
0202 inline static bool process(Container &a, Stream &is, State *state, const bool processClassId) {
0203 typedef typename Container::value_type T;
0204
0205 if (processClassId) {
0206 static const ClassId current(ClassId::makeId<Container>());
0207 ClassId id(is, 1);
0208 current.ensureSameName(id);
0209 }
0210 a.clear();
0211 if (!(IOTraits<T>::IsPOD && IOTraits<Container>::IsContiguous)) {
0212 ClassId id(is, 1);
0213
0214
0215
0216
0217
0218 state->push_back(id);
0219 }
0220 return true;
0221 }
0222 };
0223
0224
0225
0226
0227
0228
0229 template <class Stream, class State, class Container>
0230 struct GenericWriter<Stream, State, Container, InContainerFooter> {
0231 inline static bool process(const Container &, Stream &, State *, bool) { return true; }
0232 };
0233
0234 template <class Stream, class State, class Container>
0235 struct GenericReader<Stream, State, Container, InContainerFooter> {
0236 inline static bool process(Container &, Stream &, State *state, bool) {
0237 typedef typename Container::value_type T;
0238 if (!(IOTraits<T>::IsPOD && IOTraits<Container>::IsContiguous))
0239 state->pop_back();
0240 return true;
0241 }
0242 };
0243
0244
0245
0246
0247
0248
0249 template <class Stream, class State, class Container>
0250 struct GenericWriter<Stream, State, Container, InContainerSize> {
0251 inline static bool process(const std::size_t &sz, Stream &os, State *, bool ) {
0252 write_pod(os, sz);
0253 return !os.fail();
0254 }
0255 };
0256
0257 template <class Stream, class State, class Container>
0258 struct GenericReader<Stream, State, Container, InContainerSize> {
0259 inline static bool process(std::size_t &sz, Stream &is, State *, bool ) {
0260 read_pod(is, &sz);
0261 return !is.fail();
0262 }
0263 };
0264
0265
0266
0267
0268
0269
0270 template <class Stream, class State, class ArrayLike>
0271 struct GenericWriter<Stream, State, ArrayLike, InPODArray> {
0272 inline static bool process(const ArrayLike &a, Stream &os, State *, bool) {
0273 const std::size_t len = a.size();
0274 write_pod(os, len);
0275 if (len)
0276 write_pod_array(os, &a[0], len);
0277 return !os.fail();
0278 }
0279 };
0280
0281 template <class Stream, class State, class ArrayLike>
0282 struct GenericReader<Stream, State, ArrayLike, InPODArray> {
0283 inline static bool process(ArrayLike &a, Stream &s, State *, bool) {
0284 std::size_t len = 0;
0285 read_pod(s, &len);
0286 if (s.fail())
0287 return false;
0288 a.resize(len);
0289 if (!len)
0290 return true;
0291 read_pod_array(s, &a[0], len);
0292 return !s.fail();
0293 }
0294 };
0295
0296
0297
0298
0299
0300
0301 template <class Stream, class State, class T>
0302 struct GenericWriter<Stream, State, T, Int2Type<IOTraits<int>::ISWRITABLE>> {
0303 inline static bool process(const T &s, Stream &os, State *, const bool processClassId) {
0304 return (processClassId ? s.classId().write(os) : true) && s.write(os) && !os.fail();
0305 }
0306 };
0307
0308 template <class Stream, class State, class T>
0309 struct GenericReader<Stream, State, T, Int2Type<IOTraits<int>::ISWRITABLE>> {
0310 inline static bool process(T &s, Stream &is, State *st, const bool processClassId) {
0311 typedef IOTraits<T> M;
0312 T *ps = &s;
0313 return GenericReader<Stream, State, T, Int2Type<M::Signature &(M::ISPLACEREADABLE | M::ISHEAPREADABLE)>>::
0314 readIntoPtr(ps, is, st, processClassId);
0315 }
0316 };
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328 template <class Stream, class State, class Ptr>
0329 struct GenericWriter<Stream, State, Ptr, Int2Type<IOTraits<int>::ISPOINTER>> {
0330 inline static bool process(const Ptr &ptr, Stream &os, State *s, const bool processClassId) {
0331
0332
0333 typedef typename IOPointeeType<Ptr>::type Pointee;
0334 typedef IOTraits<Pointee> M;
0335 static_assert((M::Signature & (M::ISPOINTER | M::ISSHAREDPTR)) == 0, "can not write pointers to pointers");
0336
0337
0338
0339 assert(ptr);
0340 return process_const_item<GenericWriter2>(*ptr, os, s, processClassId);
0341 }
0342 };
0343
0344 template <class Stream, class State, class Ptr>
0345 struct GenericReader<Stream, State, Ptr, Int2Type<IOTraits<int>::ISPOINTER>> {
0346 inline static bool process(Ptr &ptr, Stream &str, State *s, const bool processClassId) {
0347
0348
0349
0350 typedef typename IOPointeeType<Ptr>::type Pointee;
0351 typedef IOTraits<Pointee> M;
0352 static_assert((M::Signature & (M::ISPOINTER | M::ISSHAREDPTR)) == 0, "can not read pointers to pointers");
0353
0354 return GenericReader<
0355 Stream,
0356 State,
0357 Pointee,
0358 Int2Type<M::Signature &(M::ISPOD | M::ISSTDCONTAINER | M::ISHEAPREADABLE | M::ISPLACEREADABLE | M::ISPAIR |
0359 M::ISTUPLE | M::ISEXTERNAL | M::ISSTRING)>>::readIntoPtr(ptr, str, s, processClassId);
0360 }
0361 };
0362
0363 template <class Stream, class State, class Ptr>
0364 struct GenericReader<Stream, State, Ptr, Int2Type<IOTraits<int>::ISNULLPOINTER>> {
0365 inline static bool process(Ptr &ptr, Stream &str, State *s, const bool processClassId) {
0366
0367
0368
0369 typedef typename IOPointeeType<Ptr>::type Pointee;
0370 typedef IOTraits<Pointee> M;
0371 static_assert((M::Signature & (M::ISNULLPOINTER | M::ISSHAREDPTR)) == 0, "can not read pointers to pointers");
0372
0373 return GenericReader<
0374 Stream,
0375 State,
0376 Pointee,
0377 Int2Type<M::Signature &(M::ISPOD | M::ISSTDCONTAINER | M::ISPUREHEAPREADABLE | M::ISPLACEREADABLE | M::ISPAIR |
0378 M::ISTUPLE | M::ISEXTERNAL | M::ISSTRING)>>::readIntoPtr(ptr, str, s, processClassId);
0379 }
0380 };
0381
0382
0383
0384
0385
0386
0387
0388
0389 template <class Stream, class State, class Ptr>
0390 struct GenericWriter<Stream, State, Ptr, Int2Type<IOTraits<int>::ISSHAREDPTR>> {
0391 inline static bool process(const Ptr &ptr, Stream &os, State *s, const bool processClassId) {
0392 typedef typename Ptr::element_type Pointee;
0393 typedef IOTraits<Pointee> M;
0394 static_assert((M::Signature & (M::ISPOINTER | M::ISSHAREDPTR)) == 0, "can not write pointers to pointers");
0395 assert(ptr.get());
0396 return process_const_item<GenericWriter2>(*ptr, os, s, processClassId);
0397 }
0398 };
0399
0400 template <class Stream, class State, class ShPtr>
0401 struct GenericReader<Stream, State, ShPtr, Int2Type<IOTraits<int>::ISSHAREDPTR>> {
0402 inline static bool process(ShPtr &a, Stream &str, State *s, const bool processClassId) {
0403 typedef typename ShPtr::element_type Pointee;
0404 typedef IOTraits<Pointee> M;
0405 static_assert((M::Signature & (M::ISPOINTER | M::ISSHAREDPTR)) == 0, "can not read pointers to pointers");
0406 Pointee *ptr = 0;
0407 const bool status = GenericReader<Stream, State, Pointee *, Int2Type<IOTraits<int>::ISNULLPOINTER>>::process(
0408 ptr, str, s, processClassId);
0409 if (status) {
0410 assert(ptr);
0411 a = std::shared_ptr<Pointee>(ptr);
0412 return true;
0413 } else {
0414 delete ptr;
0415 return false;
0416 }
0417 }
0418 };
0419
0420
0421
0422
0423
0424
0425 template <class Stream, class State, class T>
0426 struct GenericWriter<Stream, State, T, Int2Type<IOTraits<int>::ISPAIR>> {
0427 inline static bool process(const T &s, Stream &os, State *st, const bool processClassId) {
0428
0429
0430
0431
0432
0433
0434 static const ClassId current(ClassId::makeId<T>());
0435 return (processClassId ? current.write(os) : true) &&
0436 process_const_item<GenericWriter2>(s.first, os, st, false) &&
0437 process_const_item<GenericWriter2>(s.second, os, st, false);
0438 }
0439 };
0440
0441 template <class Stream, class State, class T>
0442 struct GenericReader<Stream, State, T, Int2Type<IOTraits<int>::ISPAIR>> {
0443 inline static bool readIntoPtr(T *&ptr, Stream &str, State *s, const bool processClassId) {
0444 CPP11_auto_ptr<T> myptr;
0445 if (ptr == 0) {
0446 myptr = CPP11_auto_ptr<T>(new T());
0447 clearIfPointer(myptr.get()->first);
0448 clearIfPointer(myptr.get()->second);
0449 }
0450 std::vector<std::vector<ClassId>> itemIds;
0451 if (processClassId) {
0452 static const ClassId current(ClassId::makeId<T>());
0453 ClassId pairId(str, 1);
0454 current.ensureSameName(pairId);
0455 pairId.templateParameters(&itemIds);
0456 assert(itemIds.size() == 2U);
0457 } else {
0458 assert(!s->empty());
0459 s->back().templateParameters(&itemIds);
0460 if (itemIds.size() != 2U) {
0461 std::string err(
0462 "In gs::GenericReader::readIntoPtr: "
0463 "bad class id for std::pair on the "
0464 "class id stack: ");
0465 err += s->back().id();
0466 throw IOInvalidData(err);
0467 }
0468 }
0469 if (!(process_item<GenericReader2>((ptr ? ptr : myptr.get())->first, str, &itemIds[0], false) &&
0470 process_item<GenericReader2>((ptr ? ptr : myptr.get())->second, str, &itemIds[1], false)))
0471 return false;
0472 if (ptr == 0)
0473 ptr = myptr.release();
0474 return true;
0475 }
0476
0477 inline static bool process(T &s, Stream &os, State *st, const bool processClassId) {
0478 T *ps = &s;
0479 return readIntoPtr(ps, os, st, processClassId);
0480 }
0481 };
0482
0483
0484
0485
0486
0487
0488 template <class Stream, class State>
0489 struct GenericWriter<Stream, State, std::string, Int2Type<IOTraits<int>::ISSTRING>> {
0490 inline static bool process(const std::string &s, Stream &os, State *, const bool processClassId) {
0491 static const ClassId current(ClassId::makeId<std::string>());
0492 const bool status = processClassId ? current.write(os) : true;
0493 if (status)
0494 write_string<char>(os, s);
0495 return status && !os.fail();
0496 }
0497 };
0498
0499 template <class Stream, class State>
0500 struct GenericReader<Stream, State, std::string, Int2Type<IOTraits<int>::ISSTRING>> {
0501 inline static bool readIntoPtr(std::string *&ptr, Stream &is, State *, const bool processClassId) {
0502 CPP11_auto_ptr<std::string> myptr;
0503 if (ptr == nullptr)
0504 myptr = CPP11_auto_ptr<std::string>(new std::string());
0505 if (processClassId) {
0506 static const ClassId current(ClassId::makeId<std::string>());
0507 ClassId id(is, 1);
0508 current.ensureSameName(id);
0509 }
0510 read_string<char>(is, ptr ? ptr : myptr.get());
0511 if (is.fail())
0512 return false;
0513 if (ptr == nullptr)
0514 ptr = myptr.release();
0515 return true;
0516 }
0517
0518 inline static bool process(std::string &s, Stream &is, State *st, const bool processClassId) {
0519 std::string *ptr = &s;
0520 return readIntoPtr(ptr, is, st, processClassId);
0521 }
0522 };
0523
0524
0525
0526
0527
0528
0529 template <class Stream, class State, class Container>
0530 struct GenericReader<Stream, State, Container, InContainerCycle> {
0531 private:
0532 typedef typename Container::value_type item_type;
0533 typedef IOTraits<item_type> M;
0534
0535
0536 inline static bool process2(Container &obj, Stream &is, State *st, const std::size_t itemN, Int2Type<1>) {
0537 item_type ptr = 0;
0538 const bool status =
0539 GenericReader<Stream, State, item_type, Int2Type<IOTraits<int>::ISNULLPOINTER>>::process(ptr, is, st, true);
0540 if (status) {
0541 assert(ptr);
0542 InsertContainerItem<Container>::insert(obj, ptr, itemN);
0543 } else
0544 delete ptr;
0545 return status;
0546 }
0547
0548
0549 inline static bool process2(Container &obj, Stream &is, State *st, const std::size_t itemN, Int2Type<2>) {
0550 typedef typename item_type::element_type Pointee;
0551 Pointee *ptr = 0;
0552 const bool status =
0553 GenericReader<Stream, State, Pointee *, Int2Type<IOTraits<int>::ISNULLPOINTER>>::process(ptr, is, st, true);
0554 if (status) {
0555 assert(ptr);
0556 std::shared_ptr<Pointee> sptr(ptr);
0557 InsertContainerItem<Container>::insert(obj, sptr, itemN);
0558 } else
0559 delete ptr;
0560 return status;
0561 }
0562
0563
0564 inline static bool process2(Container &obj, Stream &is, State *st, const std::size_t itemN, Int2Type<3>) {
0565
0566 assert(!st->empty());
0567 item_type *ptr = item_type::read(st->back(), is);
0568 if (ptr) {
0569 InsertContainerItem<Container>::insert(obj, *ptr, itemN);
0570 delete ptr;
0571 }
0572 return ptr;
0573 }
0574
0575
0576
0577 inline static bool process2(Container &obj, Stream &is, State *st, const std::size_t itemN, Int2Type<4>) {
0578 typedef typename StrippedType<item_type>::type NCType;
0579 NCType item;
0580 NCType *pitem = &item;
0581 bool status =
0582 GenericReader<Stream, State, NCType *, Int2Type<IOTraits<int>::ISPOINTER>>::process(pitem, is, st, false);
0583 if (status)
0584 InsertContainerItem<Container>::insert(obj, item, itemN);
0585 return status;
0586 }
0587
0588 public:
0589 inline static bool process(Container &obj, Stream &is, State *st, const std::size_t itemN) {
0590
0591
0592
0593
0594
0595
0596 return process2(obj,
0597 is,
0598 st,
0599 itemN,
0600 Int2Type<M::IsPointer * 1 + M::IsSharedPtr * 2 + M::IsHeapReadable * 3 +
0601 !(M::IsPointer || M::IsSharedPtr || M::IsHeapReadable) * 4>());
0602 }
0603 };
0604
0605
0606
0607
0608
0609
0610 template <class Stream, class State, class T>
0611 struct GenericReader<Stream, State, T, Int2Type<IOTraits<int>::ISSTDCONTAINER>> {
0612 inline static bool readIntoPtr(T *&ptr, Stream &str, State *s, const bool processClassId) {
0613 if (ptr)
0614 return process_item<GenericReader2>(*ptr, str, s, processClassId);
0615 else {
0616 CPP11_auto_ptr<T> myptr(new T());
0617 if (!process_item<GenericReader2>(*myptr, str, s, processClassId))
0618 return false;
0619 ptr = myptr.release();
0620 return true;
0621 }
0622 }
0623 };
0624
0625 template <class Stream, class State, class T>
0626 struct GenericReader<Stream, State, T, Int2Type<IOTraits<int>::ISHEAPREADABLE>> {
0627 inline static bool readIntoPtr(T *&ptr, Stream &str, State *s, const bool processClassId) {
0628 T *readback = 0;
0629 if (processClassId) {
0630 ClassId id(str, 1);
0631 readback = T::read(id, str);
0632 } else {
0633 assert(!s->empty());
0634 readback = T::read(s->back(), str);
0635 }
0636 if (readback) {
0637 if (ptr) {
0638 try {
0639
0640
0641 *const_cast<typename StrippedType<T>::type *>(ptr) = *readback;
0642 } catch (...) {
0643 delete readback;
0644 throw;
0645 }
0646 delete readback;
0647 } else
0648 ptr = readback;
0649 }
0650 return readback;
0651 }
0652 };
0653
0654 template <class Stream, class State, class T>
0655 struct GenericReader<Stream, State, T, Int2Type<IOTraits<int>::ISPUREHEAPREADABLE>> {
0656 inline static bool readIntoPtr(T *&ptr, Stream &str, State *s, const bool processClassId) {
0657 T *readback = nullptr;
0658 if (processClassId) {
0659 ClassId id(str, 1);
0660 readback = T::read(id, str);
0661 } else {
0662 assert(!s->empty());
0663 readback = T::read(s->back(), str);
0664 }
0665 if (readback) {
0666 assert(!ptr);
0667 ptr = readback;
0668 }
0669 return readback;
0670 }
0671 };
0672
0673 template <class Stream, class State, class T>
0674 struct GenericReader<Stream, State, T, Int2Type<IOTraits<int>::ISPLACEREADABLE>> {
0675 inline static bool readIntoPtr(T *&ptr, Stream &str, State *s, const bool processClassId) {
0676 CPP11_auto_ptr<T> myptr;
0677 if (ptr == 0)
0678 myptr = CPP11_auto_ptr<T>(new T());
0679 if (processClassId) {
0680 ClassId id(str, 1);
0681 T::restore(id, str, ptr ? ptr : myptr.get());
0682 } else {
0683 assert(!s->empty());
0684 T::restore(s->back(), str, ptr ? ptr : myptr.get());
0685 }
0686 if (ptr == 0)
0687 ptr = myptr.release();
0688 return ptr;
0689 }
0690 };
0691 }
0692
0693 #endif