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