Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-06 09:38:30

0001 // -*- C++ -*-
0002 //
0003 // PersistentOStream.h is a part of ThePEG - Toolkit for HEP Event Generation
0004 // Copyright (C) 1999-2019 Leif Lonnblad
0005 //
0006 // ThePEG is licenced under version 3 of the GPL, see COPYING for details.
0007 // Please respect the MCnet academic guidelines, see GUIDELINES for details.
0008 //
0009 #ifndef ThePEG_PersistentOStream_H
0010 #define ThePEG_PersistentOStream_H
0011 // This is the declaration of the PersistentOStream class.
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 /** @ingroup Persistency
0024  * PersistentOStream is used to write objects persistently
0025  * to a stream from which they can be read in again with a
0026  * PersistentIStream. Pointers to objects of classes
0027  * derived from <code>PersistentBase</code> may be written out if a
0028  * static ClassDescription object is present for the
0029  * class. Also basic types may be written to the stream, as well as
0030  * containers of pointers to persistent objects and basic types.
0031  *
0032  * The <code>PersistentOStream</code> keeps a list of all pointers to
0033  * written persistent objects, so that if several pointers to the
0034  * smame object is written, the object will only be written once.
0035  *
0036  * Each base class of a given object will be asked to write its
0037  * members to the stream starting from the least derived class going to
0038  * the most derived one. Members may be pointers to other persistent
0039  * objects or basic types or containers of these. The output for each
0040  * object part should be implemented by specializing the
0041  * ClassTraits<T>::output method, which otherwise
0042  * will call the non-virtual <code>persistentOutput</code> function of
0043  * the class. Note that for diamond-shaped multiple inheritance
0044  * structures, the virtual base classes will be written out several
0045  * times for the same object.
0046  *
0047  * @see PersistentIStream
0048  * @see ClassDescription
0049  * @see ClassTraits
0050  */
0051 class PersistentOStream {
0052 
0053 public:
0054 
0055   ThePEG_DECLARE_POINTERS(PersistentBase,BPtr);
0056 
0057   /** A map of objects indexed by integers */
0058   ThePEG_DECLARE_MAP(cBPtr, int, ObjectMap);
0059 
0060   /** A map relating class descriptions to integers. */
0061   ThePEG_DECLARE_MAP(const ClassDescriptionBase *, int, ClassMap);
0062 
0063   /** A vector of bare pointers to InputDescription objects. */
0064   typedef ClassDescriptionBase::DescriptionVector DescriptionVector;
0065 
0066 public:
0067 
0068   /**
0069    * Constuctor giving an output stream. Optionally a vector of
0070    * libraries to be loaded before the resulting file can be read in
0071    * again can be given in \a libs.
0072    */
0073   PersistentOStream(ostream &, const vector<string> & libs = vector<string>());
0074 
0075   /**
0076    * Constuctor giving a file name to read. If the first
0077    * character in the string is a '|', the corresponding program is
0078    * run and its standard input is used instead. If the filename ends
0079    * in ".gz" the file is compressed with gzip. Optionally a vector of
0080    * libraries to be loaded before the resulting file can be read in
0081    * again can be given in \a libs.
0082    */
0083   PersistentOStream(string, const vector<string> & libs = vector<string>());
0084 
0085   /**
0086    * The destructor
0087    */
0088   ~PersistentOStream();
0089 
0090   /**
0091    * Operator for writing persistent objects to the stream.
0092    * @param p a pointer to the object to be written.
0093    * @return a reference to the stream.
0094    */
0095   template <typename T>
0096   PersistentOStream & operator<<(const RCPtr<T> & p) { 
0097     return outputPointer(p); 
0098   }
0099 
0100   /**
0101    * Operator for writing persistent objects to the stream.
0102    * @param p a pointer to the object to be written.
0103    * @return a reference to the stream.
0104    */
0105   template <typename T>
0106   PersistentOStream & operator<<(const ConstRCPtr<T> & p) { 
0107     return outputPointer(p); 
0108   }
0109 
0110   /**
0111    * Operator for writing persistent objects to the stream.
0112    * @param p a pointer to the object to be written.
0113    * @return a reference to the stream.
0114    */
0115   template <typename T>
0116   PersistentOStream & operator<<(const TransientRCPtr<T> & p) { 
0117     return outputPointer(p); 
0118   }
0119 
0120   /**
0121    * Operator for writing persistent objects to the stream.
0122    * @param p a pointer to the object to be written.
0123    * @return a reference to the stream.
0124    */
0125   template <typename T>
0126   PersistentOStream & operator<<(const TransientConstRCPtr<T> & p) {
0127     return outputPointer(p);
0128   }
0129 
0130 
0131   /** @name Operators for extracting built-in types from the stream. */
0132   //@{
0133   /**
0134    * Write a character string.
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    * Write a character.
0144    */
0145   PersistentOStream & operator<<(char c) {
0146     escape(c);
0147     put(tSep);
0148     return *this;
0149   }
0150 
0151   /**
0152    * Write a signed character.
0153    */
0154   PersistentOStream & operator<<(signed char c) {
0155     return (*this) << static_cast<char>(c);
0156   }
0157   
0158   /**
0159    * Write an unsigned character.
0160    */
0161   PersistentOStream & operator<<(unsigned char c) {
0162     return (*this) << static_cast<char>(c);
0163   }
0164   
0165   /**
0166    * Write an integer.
0167    */
0168   PersistentOStream & operator<<(int i) {
0169     os() << i;
0170     put(tSep);
0171     return *this;
0172   }
0173 
0174   /**
0175    * Write an unsigned integer.
0176    */
0177   PersistentOStream & operator<<(unsigned int i) {
0178     os() << i;
0179     put(tSep);
0180     return *this;
0181   }
0182 
0183   /**
0184    * Write a long integer.
0185    */
0186   PersistentOStream & operator<<(long i) {
0187     os() << i;
0188     put(tSep);
0189     return *this;
0190   }
0191 
0192   /**
0193    * Write an unsigned long integer.
0194    */
0195   PersistentOStream & operator<<(unsigned long i) {
0196     os() << i;
0197     put(tSep);
0198     return *this;
0199   }
0200 
0201   /**
0202    * Write a short integer.
0203    */
0204   PersistentOStream & operator<<(short i) {
0205     os() << i;
0206     put(tSep);
0207     return *this;
0208   }
0209 
0210   /**
0211    * Write an unsigned short integer.
0212    */
0213   PersistentOStream & operator<<(unsigned short i) {
0214     os() << i;
0215     put(tSep);
0216     return *this;
0217   }
0218 
0219   /**
0220    * Write a double.
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    * Write a float.
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    * Write a boolean.
0247    */
0248   PersistentOStream & operator<<(bool t) {
0249     if (t) put(tYes);
0250     else put(tNo);
0251     // This is a workaround for a possible bug in gcc 4.0.0
0252     // which inserts tYes and tNo as global symbols although
0253     // they are private
0254     //  put(t? tYes: tNo);
0255     put(tSep);
0256     return *this;
0257   }
0258 
0259   /**
0260    * Write a c-style character string (to be read in as a std::string).
0261    */
0262   PersistentOStream & operator<<(const char * s) {
0263     *this << string(s);
0264     return *this;
0265   }
0266 
0267   /**
0268    * Write a Complex.
0269    */
0270   PersistentOStream & operator<<(Complex z) {
0271     *this << z.real() << z.imag();
0272     return *this;
0273   }
0274   //@}
0275 
0276   /**
0277    * Output of containers of streamable objects.
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    * Write out a persistent object given a pointer to it.
0289    */
0290   PersistentOStream & outputPointer(tcBPtr);
0291 
0292   /**
0293    * For a given object, write the member variables corresponding to a
0294    * given ClassDescriptionBase object.
0295    * @param obj the object to be written.
0296    * @param cd a pointer to a ClassDescriptionBase describing the
0297    * (sub)class to written.
0298    */
0299   void putObjectPart(tcBPtr obj, const ClassDescriptionBase * cd);
0300 
0301   /**
0302    * Remove all objects that have been written, except those which are
0303    * to be saved, from the list of written objects.
0304    */
0305   PersistentOStream & flush();
0306   
0307   /**
0308    * Instuct the stream to save the following objects (protecting them from
0309    * being flushed).
0310    */
0311   PersistentOStream & push() {
0312     lastSavedObject.push(writtenObjects.size() - 1);
0313     return *this;
0314   }
0315 
0316   /**
0317    * Instuct the stream not to save the following objects.
0318    */
0319   PersistentOStream & pop() {
0320     lastSavedObject.pop();
0321     return *this;
0322   }
0323 
0324   /**
0325    * Check the state of the stream.
0326    */
0327   bool good() const { return !badState && os(); }
0328 
0329   /**
0330    * Check the state of the stream.
0331    */
0332   operator bool() const { return good(); }
0333 
0334   /**
0335    * Check the state of the stream.
0336    */
0337   bool operator!() const { return !good(); }
0338 
0339 private:
0340 
0341   /** @cond EXCEPTIONCLASSES */
0342   /** @ingroup Persistency
0343    * Internal exception class.
0344    */
0345   struct MissingClass: public Exception {};
0346   /** @ingroup Persistency
0347    * Internal exception class.
0348    */
0349   struct WriteError: public Exception {};
0350   /** @endcond */
0351 
0352   /**
0353    * The version of this PersistentOStream implementation.
0354    */
0355   static const int version = 0;
0356 
0357   /**
0358    * The subversion of this PersistentOStream implementation.
0359    */
0360   static const int subVersion = 3;
0361 
0362   /** @name Special marker characters */
0363   //@{
0364   /**
0365    * The special marker character indicating the beginning of an object.
0366    */
0367   static const char tBegin = '{';
0368 
0369   /**
0370    * The special marker character indicating the end of an object.
0371    */
0372   static const char tEnd = '}';
0373 
0374   /**
0375    * The marker character indicating the beginning of the next base
0376    * class in case of multiple inheritance.
0377    */
0378   /**
0379    * The special marker character indicating an escaped marker character.
0380    */
0381   static const char tNext = '|';
0382 
0383   /**
0384    * The special marker character indicating an escaped marker character.
0385    */
0386   static const char tNull = '\\';
0387 
0388   /**
0389    * The special marker character indicating the end of a value.
0390    */
0391   static const char tSep = '\n';
0392 
0393   /**
0394    * The special marker character used to avoid confusion with escaped
0395    * tSep markers.
0396    */
0397   static const char tNoSep = 'n';
0398 
0399   /**
0400    * The special marker character indicating a true boolean value.
0401    */
0402   static const char tYes = 'y';
0403 
0404   /**
0405    * The special marker character indicating a false boolean value.
0406    */
0407   static const char tNo = 'n';
0408   //@}
0409 
0410   /**
0411    * Return true if the given character is aspecial marker character.
0412    */
0413   bool isToken(char c) const {
0414     return c == tBegin || c == tEnd || c == tNext || c == tSep || c == tNull;
0415   }
0416 
0417   /**
0418    * Set the stream in a bad state.
0419    */
0420   void setBadState() {
0421     breakThePEG();
0422     badState = true;
0423   }
0424 
0425   /**
0426    * Check if the state is ok.
0427    */
0428   void checkState() { if ( ! os() ) badState = true; }
0429 
0430   /**
0431    * Write out class information to the associated ostream.
0432    */
0433   const ClassDescriptionBase * writeClassId(tcBPtr);
0434 
0435   /**
0436    * write out class information to the associated ostream.
0437    */
0438   void writeClassDescription(const ClassDescriptionBase *);
0439 
0440   /**
0441    * Put a "begin object" marker on the associated ostream
0442    */
0443   void beginObject() { put(tBegin); }
0444 
0445   /**
0446    * Put a "end of object" marker on the associated ostream
0447    */
0448   void endObject() { put(tEnd); }
0449 
0450   /**
0451    * Put an "next base class" marker on the associated ostream
0452    */
0453   void endBase() { put(tNext); }
0454 
0455   /**
0456    * Put a character on the associated ostream
0457    */
0458   void put(char c) { os().put(c); }
0459 
0460   /**
0461    * Put a character on the associated ostream but escape it if it is
0462    * a token.
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    * Return a reference to the associated ostream.
0474    */
0475   ostream & os() { return *theOStream; }
0476 
0477   /**
0478    * Return a const reference to the associated ostream.
0479    */
0480   const ostream & os() const { return *theOStream; }
0481 
0482   /**
0483    * Write out initial metainfo on the stream.
0484    */
0485   void init(const vector<string> & libs);
0486 
0487   /**
0488    * List of written objects.
0489    */
0490   ObjectMap writtenObjects;
0491 
0492   /**
0493    * List of written objects that are to be saved.
0494    */
0495   stack<int> lastSavedObject;
0496 
0497   /**
0498    * List of written classes.
0499    */
0500   ClassMap writtenClasses;
0501 
0502   /**
0503    * A pointer to the associated ostream.
0504    */
0505   ostream * theOStream;
0506 
0507   /**
0508    * True if no errors has occurred.
0509    */
0510   bool badState;
0511 
0512   /**
0513    * True if the associated ostream should be deleted in the destructor.
0514    */
0515   bool allocStream;
0516 
0517 private:
0518 
0519   /**
0520    * Standard ctors and assignment are private and not implemented.
0521    */
0522   PersistentOStream();
0523 
0524   /**
0525    * Standard ctors and assignment are private and not implemented.
0526    */
0527   PersistentOStream(const PersistentOStream &);
0528 
0529   /**
0530    * Standard ctors and assignment are private and not implemented.
0531    */
0532   PersistentOStream & operator=(const PersistentOStream &) = delete;
0533 
0534 };
0535 
0536 /**
0537  * Operator for applying manipulators to the stream.
0538  */
0539 inline PersistentOStream &
0540 operator<<(PersistentOStream & os, PersistentOManip func) {
0541   return (*func)(os);
0542 }
0543 
0544 
0545 /**
0546  * The manipulator for calling PersistentOStream::flush().
0547  */
0548 inline PersistentOStream & flush(PersistentOStream & os) { return os.flush(); }
0549 
0550 /**
0551  * The manipulator for calling PersistentOStream::push().
0552  */
0553 inline PersistentOStream & push(PersistentOStream & os) { return os.push(); }
0554 
0555 /**
0556  * The manipulator for calling PersistentOStream::pop().
0557  */
0558 inline PersistentOStream & pop(PersistentOStream & os) { return os.pop(); }
0559 
0560 
0561 /**
0562  * @name Partial specializations of operator<< for output of
0563  * std::containers.
0564  */
0565 //@{
0566 /** Output a pair of objects. */
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  * Output a multimap of key/object pairs.
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  * Output a map of key/object pairs.
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  * Output a set of objects.
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  * Output a multiset of objects.
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  * Output a list of objects.
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  * Output a vector of objects.
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  * Output an array of objects.
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  * Output a deque of objects.
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  * Output a valarray.
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 /* ThePEG_PersistentOStream_H */