File indexing completed on 2026-08-06 09:38:30
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef ThePEG_PersistentOStream_H
0010 #define ThePEG_PersistentOStream_H
0011
0012
0013 #include "ThePEG/Config/ThePEG.h"
0014 #include "ThePEG/Utilities/ClassDescription.h"
0015 #include "ThePEG/Utilities/Exception.h"
0016 #include "ThePEG/Utilities/Debug.h"
0017 #include "PersistentOStream.fh"
0018 #include "PersistentOStream.xh"
0019 #include <valarray>
0020
0021 namespace ThePEG {
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 class PersistentOStream {
0052
0053 public:
0054
0055 ThePEG_DECLARE_POINTERS(PersistentBase,BPtr);
0056
0057
0058 ThePEG_DECLARE_MAP(cBPtr, int, ObjectMap);
0059
0060
0061 ThePEG_DECLARE_MAP(const ClassDescriptionBase *, int, ClassMap);
0062
0063
0064 typedef ClassDescriptionBase::DescriptionVector DescriptionVector;
0065
0066 public:
0067
0068
0069
0070
0071
0072
0073 PersistentOStream(ostream &, const vector<string> & libs = vector<string>());
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083 PersistentOStream(string, const vector<string> & libs = vector<string>());
0084
0085
0086
0087
0088 ~PersistentOStream();
0089
0090
0091
0092
0093
0094
0095 template <typename T>
0096 PersistentOStream & operator<<(const RCPtr<T> & p) {
0097 return outputPointer(p);
0098 }
0099
0100
0101
0102
0103
0104
0105 template <typename T>
0106 PersistentOStream & operator<<(const ConstRCPtr<T> & p) {
0107 return outputPointer(p);
0108 }
0109
0110
0111
0112
0113
0114
0115 template <typename T>
0116 PersistentOStream & operator<<(const TransientRCPtr<T> & p) {
0117 return outputPointer(p);
0118 }
0119
0120
0121
0122
0123
0124
0125 template <typename T>
0126 PersistentOStream & operator<<(const TransientConstRCPtr<T> & p) {
0127 return outputPointer(p);
0128 }
0129
0130
0131
0132
0133
0134
0135
0136 PersistentOStream & operator<<(string s) {
0137 for ( string::const_iterator i = s.begin(); i < s.end(); ++i ) escape(*i);
0138 put(tSep);
0139 return *this;
0140 }
0141
0142
0143
0144
0145 PersistentOStream & operator<<(char c) {
0146 escape(c);
0147 put(tSep);
0148 return *this;
0149 }
0150
0151
0152
0153
0154 PersistentOStream & operator<<(signed char c) {
0155 return (*this) << static_cast<char>(c);
0156 }
0157
0158
0159
0160
0161 PersistentOStream & operator<<(unsigned char c) {
0162 return (*this) << static_cast<char>(c);
0163 }
0164
0165
0166
0167
0168 PersistentOStream & operator<<(int i) {
0169 os() << i;
0170 put(tSep);
0171 return *this;
0172 }
0173
0174
0175
0176
0177 PersistentOStream & operator<<(unsigned int i) {
0178 os() << i;
0179 put(tSep);
0180 return *this;
0181 }
0182
0183
0184
0185
0186 PersistentOStream & operator<<(long i) {
0187 os() << i;
0188 put(tSep);
0189 return *this;
0190 }
0191
0192
0193
0194
0195 PersistentOStream & operator<<(unsigned long i) {
0196 os() << i;
0197 put(tSep);
0198 return *this;
0199 }
0200
0201
0202
0203
0204 PersistentOStream & operator<<(short i) {
0205 os() << i;
0206 put(tSep);
0207 return *this;
0208 }
0209
0210
0211
0212
0213 PersistentOStream & operator<<(unsigned short i) {
0214 os() << i;
0215 put(tSep);
0216 return *this;
0217 }
0218
0219
0220
0221
0222 PersistentOStream & operator<<(double d) {
0223 if ( ! isfinite(d) )
0224 throw WriteError()
0225 << "Tried to write a NaN or Inf double to a persistent stream."
0226 << Exception::runerror;
0227 os() << setprecision(18) << d;
0228 put(tSep);
0229 return *this;
0230 }
0231
0232
0233
0234
0235 PersistentOStream & operator<<(float f) {
0236 if ( ! isfinite(f) )
0237 throw WriteError()
0238 << "Tried to write a NaN or Inf float to a persistent stream."
0239 << Exception::runerror;
0240 os() << setprecision(9) << f;
0241 put(tSep);
0242 return *this;
0243 }
0244
0245
0246
0247
0248 PersistentOStream & operator<<(bool t) {
0249 if (t) put(tYes);
0250 else put(tNo);
0251
0252
0253
0254
0255 put(tSep);
0256 return *this;
0257 }
0258
0259
0260
0261
0262 PersistentOStream & operator<<(const char * s) {
0263 *this << string(s);
0264 return *this;
0265 }
0266
0267
0268
0269
0270 PersistentOStream & operator<<(Complex z) {
0271 *this << z.real() << z.imag();
0272 return *this;
0273 }
0274
0275
0276
0277
0278
0279 template <typename Container>
0280 void putContainer(const Container & c) {
0281 *this << c.size();
0282 for ( typename Container::const_iterator it = c.begin();
0283 it != c.end() && good() ; ++it )
0284 *this << *it;
0285 }
0286
0287
0288
0289
0290 PersistentOStream & outputPointer(tcBPtr);
0291
0292
0293
0294
0295
0296
0297
0298
0299 void putObjectPart(tcBPtr obj, const ClassDescriptionBase * cd);
0300
0301
0302
0303
0304
0305 PersistentOStream & flush();
0306
0307
0308
0309
0310
0311 PersistentOStream & push() {
0312 lastSavedObject.push(writtenObjects.size() - 1);
0313 return *this;
0314 }
0315
0316
0317
0318
0319 PersistentOStream & pop() {
0320 lastSavedObject.pop();
0321 return *this;
0322 }
0323
0324
0325
0326
0327 bool good() const { return !badState && os(); }
0328
0329
0330
0331
0332 operator bool() const { return good(); }
0333
0334
0335
0336
0337 bool operator!() const { return !good(); }
0338
0339 private:
0340
0341
0342
0343
0344
0345 struct MissingClass: public Exception {};
0346
0347
0348
0349 struct WriteError: public Exception {};
0350
0351
0352
0353
0354
0355 static const int version = 0;
0356
0357
0358
0359
0360 static const int subVersion = 3;
0361
0362
0363
0364
0365
0366
0367 static const char tBegin = '{';
0368
0369
0370
0371
0372 static const char tEnd = '}';
0373
0374
0375
0376
0377
0378
0379
0380
0381 static const char tNext = '|';
0382
0383
0384
0385
0386 static const char tNull = '\\';
0387
0388
0389
0390
0391 static const char tSep = '\n';
0392
0393
0394
0395
0396
0397 static const char tNoSep = 'n';
0398
0399
0400
0401
0402 static const char tYes = 'y';
0403
0404
0405
0406
0407 static const char tNo = 'n';
0408
0409
0410
0411
0412
0413 bool isToken(char c) const {
0414 return c == tBegin || c == tEnd || c == tNext || c == tSep || c == tNull;
0415 }
0416
0417
0418
0419
0420 void setBadState() {
0421 breakThePEG();
0422 badState = true;
0423 }
0424
0425
0426
0427
0428 void checkState() { if ( ! os() ) badState = true; }
0429
0430
0431
0432
0433 const ClassDescriptionBase * writeClassId(tcBPtr);
0434
0435
0436
0437
0438 void writeClassDescription(const ClassDescriptionBase *);
0439
0440
0441
0442
0443 void beginObject() { put(tBegin); }
0444
0445
0446
0447
0448 void endObject() { put(tEnd); }
0449
0450
0451
0452
0453 void endBase() { put(tNext); }
0454
0455
0456
0457
0458 void put(char c) { os().put(c); }
0459
0460
0461
0462
0463
0464 void escape(char c) {
0465 if ( isToken(c) ) {
0466 put(tNull);
0467 put( c == tSep? tNoSep: c );
0468 } else
0469 put(c);
0470 }
0471
0472
0473
0474
0475 ostream & os() { return *theOStream; }
0476
0477
0478
0479
0480 const ostream & os() const { return *theOStream; }
0481
0482
0483
0484
0485 void init(const vector<string> & libs);
0486
0487
0488
0489
0490 ObjectMap writtenObjects;
0491
0492
0493
0494
0495 stack<int> lastSavedObject;
0496
0497
0498
0499
0500 ClassMap writtenClasses;
0501
0502
0503
0504
0505 ostream * theOStream;
0506
0507
0508
0509
0510 bool badState;
0511
0512
0513
0514
0515 bool allocStream;
0516
0517 private:
0518
0519
0520
0521
0522 PersistentOStream();
0523
0524
0525
0526
0527 PersistentOStream(const PersistentOStream &);
0528
0529
0530
0531
0532 PersistentOStream & operator=(const PersistentOStream &) = delete;
0533
0534 };
0535
0536
0537
0538
0539 inline PersistentOStream &
0540 operator<<(PersistentOStream & os, PersistentOManip func) {
0541 return (*func)(os);
0542 }
0543
0544
0545
0546
0547
0548 inline PersistentOStream & flush(PersistentOStream & os) { return os.flush(); }
0549
0550
0551
0552
0553 inline PersistentOStream & push(PersistentOStream & os) { return os.push(); }
0554
0555
0556
0557
0558 inline PersistentOStream & pop(PersistentOStream & os) { return os.pop(); }
0559
0560
0561
0562
0563
0564
0565
0566
0567 template <typename T1, typename T2>
0568 inline PersistentOStream & operator<<(PersistentOStream & os,
0569 const pair<T1,T2> & p) {
0570 return os << p.first << p.second;
0571 }
0572
0573
0574
0575
0576 template <typename Key, typename T, typename Cmp, typename A>
0577 inline PersistentOStream & operator<<(PersistentOStream & os,
0578 const multimap<Key,T,Cmp,A> & m) {
0579 os.putContainer(m);
0580 return os;
0581 }
0582
0583
0584
0585
0586 template <typename Key, typename T, typename Cmp, typename A>
0587 inline PersistentOStream & operator<<(PersistentOStream & os,
0588 const map<Key,T,Cmp,A> & m) {
0589 os.putContainer(m);
0590 return os;
0591 }
0592
0593
0594
0595
0596 template <typename Key, typename Cmp, typename A>
0597 inline PersistentOStream & operator<<(PersistentOStream & os,
0598 const set<Key,Cmp,A> & s) {
0599 os.putContainer(s);
0600 return os;
0601 }
0602
0603
0604
0605
0606
0607 template <typename Key, typename Cmp, typename A>
0608 inline PersistentOStream & operator<<(PersistentOStream & os,
0609 const multiset<Key,Cmp,A> & s) {
0610 os.putContainer(s);
0611 return os;
0612 }
0613
0614
0615
0616
0617
0618 template <typename T, typename A>
0619 inline PersistentOStream & operator<<(PersistentOStream & os,
0620 const list<T,A> & l) {
0621 os.putContainer(l);
0622 return os;
0623 }
0624
0625
0626
0627
0628
0629 template <typename T, typename A>
0630 inline PersistentOStream & operator<<(PersistentOStream & os,
0631 const vector<T,A> & v) {
0632 os.putContainer(v);
0633 return os;
0634 }
0635
0636
0637
0638
0639 template <typename T, size_t N>
0640 inline PersistentOStream & operator<<(PersistentOStream & os,
0641 const array<T,N> & a) {
0642 for ( auto it = a.cbegin(); it != a.cend() && os.good() ; ++it )
0643 os << *it;
0644 return os;
0645 }
0646
0647
0648
0649
0650 template <typename T, typename A>
0651 inline PersistentOStream & operator<<(PersistentOStream & os,
0652 const deque<T,A> & d) {
0653 os.putContainer(d);
0654 return os;
0655 }
0656
0657
0658
0659
0660 template <typename T>
0661 inline PersistentOStream & operator<<(PersistentOStream & os,
0662 const std::valarray<T> & v) {
0663 os << v.size();
0664 for ( int i = 0, N = v.size(); i < N; ++i ) os << v[i];
0665 return os;
0666 }
0667
0668
0669 }
0670
0671 #endif