/*------------------------------------------------------------------------*/ /* */ /* OBJSTRM.H */ /* */ /* Copyright (c) 1992, 1994 Borland International */ /* All Rights Reserved */ /* */ /*------------------------------------------------------------------------*/ #if !defined( CLASSLIB_OBJSTRM_H ) #define CLASSLIB_OBJSTRM_H #if !defined( __IOSTREAM_H ) #include #endif #if !defined( __FSTREAM_H ) #include #endif #if !defined( __SYSTYPES_H ) #include #endif #if !defined( __TYPEINFO_H ) && !defined(BI_NO_RTTI) #include #endif #if !defined( __CHECKS_H ) #include #endif #if !defined( CLASSLIB_DEFS_H ) #include #endif #if !defined( CLASSLIB_STREAMBL_H ) #include #endif #if !defined( CLASSLIB_VECTIMP_H ) #include #endif #if defined( BI_CLASSLIB_NO_po ) #pragma option -po- #endif /*------------------------------------------------------------------------*/ /* */ /* The __link() macro forces the compiler to link in a static instance */ /* of class TStreamableClass, which in turn registers its associated */ /* TStreamable object with the stream manager. Applications that do */ /* not use streaming won't use __link(), and that will reduce the amount */ /* of code that is linked into the application. */ /* */ /*------------------------------------------------------------------------*/ struct fLink { struct fLink *f; class TStreamableClass *t; }; #define __link( s ) \ extern TStreamableClass s; \ static fLink force ## s = \ { (fLink *)&force ## s, (TStreamableClass *)&s }; typedef unsigned P_id_type; class _BIDSCLASS _RTTI TStreamable; class _BIDSCLASS TStreamableTypes; class _BIDSCLASS opstream; class _BIDSCLASS ipstream; class _EXPCLASS string; ipstream _BIDSFAR& _BIDSENTRY _BIDSFUNC operator >> ( ipstream _BIDSFAR& is, string _BIDSFAR& str ); opstream _BIDSFAR& _BIDSENTRY _BIDSFUNC operator << ( opstream _BIDSFAR& os, const string _BIDSFAR& str ); /* -----------------------------------------------------------------------*/ /* */ /* _TYPENAME(obj) provides a macro for getting the type name from a */ /* pointer to an object. If runtime type information is available, this */ /* macro uses the typeid of the object to get its name. If runtime type */ /* information is not available, it uses the CastableID() for the object.*/ /* */ /* -----------------------------------------------------------------------*/ #if defined( BI_NO_RTTI ) # define _TYPENAME(obj) (obj)->CastableID() #else # define _TYPENAME(obj) typeid(*obj).name() #endif /* -----------------------------------------------------------------------*/ /* */ /* class TStreamable */ /* */ /* This is the base class from which all streamable objects must be */ /* derived. */ /* */ /* -----------------------------------------------------------------------*/ enum StreamableInit { streamableInit }; class _BIDSCLASS _RTTI TStreamableBase { public: virtual _BIDSENTRY ~TStreamableBase(); #if defined( BI_NO_RTTI ) typedef const char * _BIDSENTRY Type_id; virtual void * _BIDSENTRY FindBase( Type_id id ) const; public: virtual Type_id _BIDSENTRY CastableID() const = 0; virtual void * _BIDSENTRY MostDerived() const = 0; #endif // BI_NO_RTTI }; class _BIDSCLASS _RTTI TStreamable : public TStreamableBase { friend class _BIDSCLASS _RTTI TOldStreamer; protected: virtual const char * _BIDSENTRY streamableName() const = 0; virtual void * _BIDSENTRY read( ipstream& ); virtual void _BIDSENTRY write( opstream& ); #if defined( BI_NO_RTTI ) public: virtual void * _BIDSENTRY FindBase( Type_id id ) const; protected: virtual Type_id _BIDSENTRY CastableID() const { return streamableName(); } virtual void * _BIDSENTRY MostDerived() const { return 0; } #endif }; class _BIDSCLASS _RTTI TStreamer { friend class ipstream; friend class opstream; public: TStreamableBase * _BIDSENTRY GetObject() const { return object; } protected: _BIDSENTRY TStreamer( TStreamableBase *obj ) : object(obj) {} virtual const char * _BIDSENTRY StreamableName() const = 0; virtual void * _BIDSENTRY Read( ipstream&, uint32 ) const = 0; virtual void _BIDSENTRY Write( opstream& ) const = 0; private: virtual uint32 _BIDSENTRY ClassVersion() const = 0; TStreamableBase *object; }; class _BIDSCLASS _RTTI TOldStreamer : public TStreamer { public: _BIDSENTRY TOldStreamer( TStreamable *obj ) : TStreamer(obj) {}; protected: virtual const char * _BIDSENTRY StreamableName() const { return STATIC_CAST(TStreamable *,GetObject())->streamableName(); } virtual void * _BIDSENTRY Read( ipstream& is, uint32 ) const { return STATIC_CAST(TStreamable *,GetObject())->read( is ); } virtual void _BIDSENTRY Write( opstream& os ) const { STATIC_CAST(TStreamable *,GetObject())->write( os ); } private: virtual uint32 _BIDSENTRY ClassVersion() const { return 0; } }; class _BIDSCLASS _RTTI TNewStreamer : public TStreamer { public: _BIDSENTRY TNewStreamer( TStreamableBase *obj ) : TStreamer(obj) {}; protected: virtual const char * _BIDSENTRY StreamableName() const { return _TYPENAME(GetObject()); } }; /* ------------------------------------------------------------------------*/ /* */ /* class TPWrittenObjects */ /* */ /* Maintains a database of all objects that have been written to the */ /* current persistent stream. */ /* */ /* Used by opstream when it writes a pointer from a stream to save the */ /* address and ID of the object being written. */ /* */ /* ------------------------------------------------------------------------*/ class _BIDSCLASS TPWrittenObjects { friend opstream; public: void _BIDSENTRY RemoveAll(); class _BIDSCLASS TPWObj { public: _BIDSENTRY TPWObj() : Address(0), Ident(0) {} _BIDSENTRY TPWObj( const void *adr, P_id_type id ) : Address(adr), Ident(id) {} friend int _BIDSENTRY operator == ( const TPWObj& o1, const TPWObj& o2 ) { return o1.Address == o2.Address; } friend int _BIDSENTRY operator < ( const TPWObj& o1, const TPWObj& o2 ) { return o1.Address < o2.Address; } const void *Address; P_id_type Ident; }; private: _BIDSENTRY TPWrittenObjects(); void _BIDSENTRY RegisterObject( TStreamableBase *adr ); void _BIDSENTRY RegisterVB( const TStreamableBase *adr ); P_id_type _BIDSENTRY FindObject( TStreamableBase *adr ); P_id_type _BIDSENTRY FindVB( TStreamableBase *adr ); P_id_type CurId; TSVectorImp Data; }; /* ------------------------------------------------------------------------*/ /* */ /* class TPReadObjects */ /* */ /* Maintains a database of all objects that have been read from the */ /* current persistent stream. */ /* */ /* Used by ipstream when it reads a pointer from a stream to determine */ /* the address of the object being referred to. */ /* */ /* ------------------------------------------------------------------------*/ class _BIDSCLASS TPReadObjects { friend ipstream; public: void _BIDSENTRY RemoveAll(); private: _BIDSENTRY TPReadObjects(); void _BIDSENTRY RegisterObject( TStreamableBase *adr ); TStreamableBase * _BIDSENTRY Find( P_id_type id ); TCVectorImp Data; }; /* ------------------------------------------------------------------------*/ /* */ /* class pstream */ /* */ /* Base class for handling streamable objects. */ /* */ /* ------------------------------------------------------------------------*/ class _BIDSCLASS pstream { friend TStreamableTypes; friend TStreamableClass; public: enum PointerTypes { ptNull, ptIndexed, ptObject }; _BIDSENTRY pstream( streambuf _BIDSFAR * ); virtual _BIDSENTRY ~pstream(); int _BIDSENTRY rdstate() const; int _BIDSENTRY eof() const; int _BIDSENTRY fail() const; int _BIDSENTRY bad() const; int _BIDSENTRY good() const; void _BIDSENTRY clear( int = 0 ); _BIDSENTRY operator void *() const; int _BIDSENTRY operator ! () const; streambuf _BIDSFAR * _BIDSENTRY rdbuf() const; static void _BIDSENTRY initTypes(); static void _BIDSENTRY releaseTypes(); static void _BIDSENTRY registerType( TStreamableClass *ts ); protected: _BIDSENTRY pstream(); streambuf _BIDSFAR *bp; int state; void _BIDSENTRY init( streambuf _BIDSFAR * ); void _BIDSENTRY setstate( int ); static TStreamableTypes *types; }; /* ------------------------------------------------------------------------*/ /* */ /* class ipstream */ /* */ /* Base class for reading streamable objects */ /* */ /* ------------------------------------------------------------------------*/ class _BIDSCLASS ipstream : virtual public pstream { friend class TStreamableClass; public: _BIDSENTRY ipstream( streambuf _BIDSFAR * ); streampos _BIDSENTRY tellg(); ipstream& _BIDSENTRY seekg( streampos ); ipstream& _BIDSENTRY seekg( streamoff, ios::seek_dir ); uint8 _BIDSENTRY readByte(); void _BIDSENTRY readBytes( void _BIDSFAR *, size_t ); void _BIDSENTRY freadBytes( void _BIDSFARDATA *data, size_t sz ); uint32 _BIDSENTRY readWord(); uint16 _BIDSENTRY readWord16(); uint32 _BIDSENTRY readWord32(); char _BIDSFAR * _BIDSENTRY readString(); char _BIDSFAR * _BIDSENTRY readString( char _BIDSFAR *, unsigned ); char _BIDSFARDATA * _BIDSENTRY freadString(); char _BIDSFARDATA * _BIDSENTRY freadString( char _BIDSFARDATA *buf, unsigned maxLen ); friend ipstream& _BIDSENTRY operator >> ( ipstream&, signed char& ); friend ipstream& _BIDSENTRY operator >> ( ipstream&, unsigned char& ); friend ipstream& _BIDSENTRY operator >> ( ipstream&, char& ); friend ipstream& _BIDSENTRY operator >> ( ipstream&, signed short& ); friend ipstream& _BIDSENTRY operator >> ( ipstream&, unsigned short& ); friend ipstream& _BIDSENTRY operator >> ( ipstream&, signed int& ); friend ipstream& _BIDSENTRY operator >> ( ipstream&, unsigned int& ); friend ipstream& _BIDSENTRY operator >> ( ipstream&, signed long& ); friend ipstream& _BIDSENTRY operator >> ( ipstream&, unsigned long& ); friend ipstream& _BIDSENTRY operator >> ( ipstream&, float& ); friend ipstream& _BIDSENTRY operator >> ( ipstream&, double& ); friend ipstream& _BIDSENTRY operator >> ( ipstream&, long double& ); friend ipstream _BIDSFAR& _BIDSENTRY _BIDSFUNC operator >> ( ipstream _BIDSFAR& is, string _BIDSFAR& str ); uint32 _BIDSENTRY getVersion() const; TStreamableBase _BIDSFAR * _BIDSENTRY readObject( TStreamableBase _BIDSFAR *&mem, ModuleId mid = GetModuleId() ); TStreamableBase _BIDSFAR * _BIDSENTRY readObjectPointer( TStreamableBase _BIDSFAR *&mem, ModuleId mid = GetModuleId() ); TStreamableBase _BIDSFAR * _BIDSENTRY find( P_id_type ); void _BIDSENTRY registerObject( TStreamableBase _BIDSFAR *adr ); protected: _BIDSENTRY ipstream(); const ObjectBuilder _BIDSFAR * _BIDSENTRY readPrefix( ModuleId mid ); void _BIDSENTRY readData( const ObjectBuilder _BIDSFAR *, TStreamableBase _BIDSFAR *& ); void _BIDSENTRY readSuffix(); void _BIDSENTRY readVersion(); private: uint32 readStringLength(); TPReadObjects objs; uint32 version; }; /* ------------------------------------------------------------------------*/ /* */ /* class opstream */ /* */ /* Base class for writing streamable objects */ /* */ /* ------------------------------------------------------------------------*/ class _BIDSCLASS opstream : virtual public pstream { public: _BIDSENTRY opstream( streambuf _BIDSFAR * ); _BIDSENTRY ~opstream(); streampos _BIDSENTRY tellp(); opstream& _BIDSENTRY seekp( streampos ); opstream& _BIDSENTRY seekp( streamoff, ios::seek_dir ); opstream& _BIDSENTRY flush(); void _BIDSENTRY writeByte( uint8 ); void _BIDSENTRY writeBytes( const void _BIDSFAR *, size_t ); void _BIDSENTRY fwriteBytes( const void _BIDSFARDATA *data, size_t sz ); void _BIDSENTRY writeWord( uint32 ); void _BIDSENTRY writeWord16( uint16 ); void _BIDSENTRY writeWord32( uint32 ); void _BIDSENTRY writeString( const char _BIDSFAR * ); void _BIDSENTRY fwriteString( const char _BIDSFARDATA * str ); friend opstream& _BIDSENTRY operator << ( opstream&, signed char ); friend opstream& _BIDSENTRY operator << ( opstream&, unsigned char ); friend opstream& _BIDSENTRY operator << ( opstream&, char ); friend opstream& _BIDSENTRY operator << ( opstream&, signed short ); friend opstream& _BIDSENTRY operator << ( opstream&, unsigned short ); friend opstream& _BIDSENTRY operator << ( opstream&, signed int ); friend opstream& _BIDSENTRY operator << ( opstream&, unsigned int ); friend opstream& _BIDSENTRY operator << ( opstream&, signed long ); friend opstream& _BIDSENTRY operator << ( opstream&, unsigned long ); friend opstream& _BIDSENTRY operator << ( opstream&, float ); friend opstream& _BIDSENTRY operator << ( opstream&, double ); friend opstream& _BIDSENTRY operator << ( opstream&, long double ); void _BIDSENTRY writeObject( const TStreamableBase _BIDSFAR *t, int isPtr = 0, ModuleId mid = GetModuleId() ); void _BIDSENTRY writeObjectPointer( const TStreamableBase _BIDSFAR *t, ModuleId mid = GetModuleId() ); P_id_type _BIDSENTRY findObject( TStreamableBase _BIDSFAR *adr ); void _BIDSENTRY registerObject( TStreamableBase _BIDSFAR *adr ); P_id_type _BIDSENTRY findVB( TStreamableBase _BIDSFAR *adr ); void _BIDSENTRY registerVB( TStreamableBase _BIDSFAR *adr ); protected: _BIDSENTRY opstream(); void _BIDSENTRY writePrefix( const TStreamableBase _BIDSFAR * ); void _BIDSENTRY writeData( const TStreamableBase _BIDSFAR *, ModuleId mid ); void _BIDSENTRY writeSuffix( const TStreamableBase _BIDSFAR * ); private: void _BIDSENTRY writeVersion(); TPWrittenObjects *objs; }; /* ------------------------------------------------------------------------*/ /* */ /* class fpbase */ /* */ /* Base class for handling streamable objects on file streams */ /* */ /* ------------------------------------------------------------------------*/ class _BIDSCLASS fpbase : virtual public pstream { public: _BIDSENTRY fpbase(); _BIDSENTRY fpbase( const char _BIDSFAR *, int, int = filebuf::openprot ); _BIDSENTRY fpbase( int ); _BIDSENTRY fpbase( int, char _BIDSFAR *, int ); void _BIDSENTRY open( const char _BIDSFAR *, int, int = filebuf::openprot ); void _BIDSENTRY attach( int ); void _BIDSENTRY close(); void _BIDSENTRY setbuf( char _BIDSFAR *, int ); filebuf _BIDSFAR * _BIDSENTRY rdbuf(); private: filebuf buf; }; /* ------------------------------------------------------------------------*/ /* */ /* class ifpstream */ /* */ /* Base class for reading streamable objects from file streams */ /* */ /* ------------------------------------------------------------------------*/ class _BIDSCLASS ifpstream : public fpbase, public ipstream { public: _BIDSENTRY ifpstream(); _BIDSENTRY ifpstream( const char _BIDSFAR *, int = ios::in, int = filebuf::openprot ); _BIDSENTRY ifpstream( int ); _BIDSENTRY ifpstream( int, char _BIDSFAR *, int ); filebuf _BIDSFAR * _BIDSENTRY rdbuf(); void _BIDSENTRY open( const char _BIDSFAR *, int = ios::in, int = filebuf::openprot ); }; /* ------------------------------------------------------------------------*/ /* */ /* class ofpstream */ /* */ /* Base class for writing streamable objects to file streams */ /* */ /* ------------------------------------------------------------------------*/ class _BIDSCLASS ofpstream : public fpbase, public opstream { public: _BIDSENTRY ofpstream(); _BIDSENTRY ofpstream( const char _BIDSFAR *, int = ios::out, int = filebuf::openprot ); _BIDSENTRY ofpstream( int ); _BIDSENTRY ofpstream( int, char _BIDSFAR *, int ); filebuf _BIDSFAR * _BIDSENTRY rdbuf(); void _BIDSENTRY open( const char _BIDSFAR *, int = ios::out, int = filebuf::openprot ); }; /* ------------------------------------------------------------------------*/ /* */ /* Inline functions */ /* */ /* ------------------------------------------------------------------------*/ inline _BIDSENTRY pstream::pstream( streambuf _BIDSFAR *sb ) { init( sb ); } inline int _BIDSENTRY pstream::rdstate() const { return state; } inline int _BIDSENTRY pstream::eof() const { return state & ios::eofbit; } inline int _BIDSENTRY pstream::fail() const { return state & (ios::failbit | ios::badbit | ios::hardfail); } inline int _BIDSENTRY pstream::bad() const { return state & (ios::badbit | ios::hardfail); } inline int _BIDSENTRY pstream::good() const { return state == 0; } inline void _BIDSENTRY pstream::clear( int i ) { state = (i & 0xFF) | (state & ios::hardfail); } inline _BIDSENTRY pstream::operator void _BIDSFAR *() const { return fail() ? 0 : (void *)this; } inline int _BIDSENTRY pstream::operator! () const { return fail(); } inline streambuf _BIDSFAR * _BIDSENTRY pstream::rdbuf() const { return bp; } inline _BIDSENTRY pstream::pstream() { } inline void _BIDSENTRY pstream::init( streambuf *sbp ) { state = 0; bp = sbp; } inline void _BIDSENTRY pstream::setstate( int b ) { state |= (b&0xFF); } inline _BIDSENTRY ipstream::ipstream( streambuf _BIDSFAR *sb ) { pstream::init( sb ); readVersion(); } inline _BIDSENTRY ipstream::ipstream() { if( bp != 0 ) readVersion(); } inline TStreamableBase * _BIDSENTRY ipstream::find( P_id_type id ) { return objs.Find( id ); } inline void _BIDSENTRY ipstream::registerObject( TStreamableBase *adr ) { objs.RegisterObject( adr ); } inline uint32 _BIDSENTRY ipstream::getVersion() const { return version; } inline void _BIDSENTRY pstream::registerType( TStreamableClass *ts ) { types->RegisterType( GetModuleId(), *ts ); } inline _BIDSENTRY opstream::~opstream() { delete objs; } inline void _BIDSENTRY opstream::writeWord( uint32 word32 ) { writeWord32( word32 ); } inline void _BIDSENTRY opstream::writeSuffix( const TStreamableBase * ) { writeByte( ']' ); } inline P_id_type _BIDSENTRY opstream::findObject( TStreamableBase *adr ) { return objs->FindObject( adr ); } inline void _BIDSENTRY opstream::registerObject( TStreamableBase *adr ) { objs->RegisterObject( adr ); } inline P_id_type _BIDSENTRY opstream::findVB( TStreamableBase *adr ) { return objs->FindVB( adr ); } inline void _BIDSENTRY opstream::registerVB( TStreamableBase *adr ) { objs->RegisterVB( adr ); } inline _BIDSENTRY fpbase::fpbase() { pstream::init( &buf ); } inline _BIDSENTRY fpbase::fpbase( const char *name, int omode, int prot ) { pstream::init( &buf ); open( name, omode, prot ); } inline _BIDSENTRY fpbase::fpbase( int f ) : buf( f ) { pstream::init( &buf ); } inline _BIDSENTRY fpbase::fpbase( int f, char *b, int len ) : buf( f, b, len ) { pstream::init( &buf ); } inline filebuf * _BIDSENTRY fpbase::rdbuf() { return &buf; } inline _BIDSENTRY ifpstream::ifpstream() { } inline _BIDSENTRY ifpstream::ifpstream( const char* name, int omode, int prot ) : fpbase( name, omode | ios::in | ios::binary, prot ) { } inline _BIDSENTRY ifpstream::ifpstream( int f ) : fpbase( f ) { } inline _BIDSENTRY ifpstream::ifpstream(int f, char* b, int len) : fpbase(f, b, len) { } inline filebuf * _BIDSENTRY ifpstream::rdbuf() { return fpbase::rdbuf(); } inline void _BIDSENTRY ifpstream::open( const char _BIDSFAR *name, int omode, int prot ) { fpbase::open( name, omode | ios::in | ios::binary, prot ); readVersion(); } inline _BIDSENTRY ofpstream::ofpstream() { } inline _BIDSENTRY ofpstream::ofpstream( const char* name, int omode, int prot ) : fpbase( name, omode | ios::out | ios::binary, prot ) { } inline _BIDSENTRY ofpstream::ofpstream( int f ) : fpbase( f ) { } inline _BIDSENTRY ofpstream::ofpstream(int f, char* b, int len) : fpbase(f, b, len) { } inline filebuf * _BIDSENTRY ofpstream::rdbuf() { return fpbase::rdbuf(); } inline void _BIDSENTRY ofpstream::open( const char _BIDSFAR *name, int omode, int prot ) { fpbase::open( name, omode | ios::out | ios::binary, prot ); } inline ipstream& _BIDSENTRY operator >> ( ipstream& ps, signed char &ch ) { ch = ps.readByte(); return ps; } inline ipstream& _BIDSENTRY operator >> ( ipstream& ps, unsigned char &ch ) { ch = ps.readByte(); return ps; } inline ipstream& _BIDSENTRY operator >> ( ipstream& ps, char &ch ) { ch = ps.readByte(); return ps; } inline ipstream& _BIDSENTRY operator >> ( ipstream& ps, signed short &sh ) { sh = ps.readWord16(); return ps; } inline ipstream& _BIDSENTRY operator >> ( ipstream& ps, unsigned short &sh ) { sh = ps.readWord16(); return ps; } inline ipstream& _BIDSENTRY operator >> ( ipstream& ps, signed int &i ) { i = (int)(ps.readWord32()); return ps; } inline ipstream& _BIDSENTRY operator >> ( ipstream& ps, unsigned int &i ) { i = (unsigned int)(ps.readWord32()); return ps; } inline ipstream& _BIDSENTRY operator >> ( ipstream& ps, signed long &l ) { ps.readBytes( &l, sizeof(l) ); return ps; } inline ipstream& _BIDSENTRY operator >> ( ipstream& ps, unsigned long &l ) { ps.readBytes( &l, sizeof(l) ); return ps; } inline ipstream& _BIDSENTRY operator >> ( ipstream& ps, float &f ) { ps.readBytes( &f, sizeof(f) ); return ps; } inline ipstream& _BIDSENTRY operator >> ( ipstream& ps, double &d ) { ps.readBytes( &d, sizeof(d) ); return ps; } inline ipstream& _BIDSENTRY operator >> ( ipstream& ps, long double &l ) { ps.readBytes( &l, sizeof(l) ); return ps; } #if defined( UNIQUE_BOOL ) inline ipstream& _BIDSENTRY operator >> ( ipstream& ps, bool &b ) { b = static_cast(ps.readWord32()); return ps; } #endif inline opstream& _BIDSENTRY operator << ( opstream& ps, signed char ch ) { ps.writeByte( ch ); return ps; } inline opstream& _BIDSENTRY operator << ( opstream& ps, unsigned char ch ) { ps.writeByte( ch ); return ps; } inline opstream& _BIDSENTRY operator << ( opstream& ps, char ch ) { ps.writeByte( ch ); return ps; } inline opstream& _BIDSENTRY operator << ( opstream& ps, signed short sh ) { ps.writeWord16( sh ); return ps; } inline opstream& _BIDSENTRY operator << ( opstream& ps, unsigned short sh ) { ps.writeWord16( sh ); return ps; } inline opstream& _BIDSENTRY operator << ( opstream& ps, signed int i ) { ps.writeWord32( i ); return ps; } inline opstream& _BIDSENTRY operator << ( opstream& ps, unsigned int i ) { ps.writeWord32( i ); return ps; } inline opstream& _BIDSENTRY operator << ( opstream& ps, signed long l ) { ps.writeBytes( &l, sizeof(l) ); return ps; } inline opstream& _BIDSENTRY operator << ( opstream& ps, unsigned long l ) { ps.writeBytes( &l, sizeof(l) ); return ps; } inline opstream& _BIDSENTRY operator << ( opstream& ps, float f ) { ps.writeBytes( &f, sizeof(f) ); return ps; } inline opstream& _BIDSENTRY operator << ( opstream& ps, double d ) { ps.writeBytes( &d, sizeof(d) ); return ps; } inline opstream& _BIDSENTRY operator << ( opstream& ps, long double l ) { ps.writeBytes( &l, sizeof(l) ); return ps; } template void WriteBaseObject( Base *base, opstream& out ) { Base::Streamer strmr(base); out << strmr.ClassVersion(); strmr.Write( out ); } template void ReadBaseObject( Base *base, ipstream& in ) { uint32 version = 0; if( in.getVersion() > 0 ) in >> version; Base::Streamer(base).Read( in, version ); } template void WriteVirtualBase( Base *base, opstream& out ) { if( !out.good() ) return; if( out.findVB( base ) != 0 ) { out.writeByte( pstream::ptIndexed ); // use ptIndexed to indicate // that we've already seen // this virtual base. Don't // need to actually write it. } else { Base::Streamer strmr(base); out.registerObject( (TStreamableBase *)((char *)base + 1) ); out.writeByte( pstream::ptObject ); out.writeWord32( strmr.ClassVersion() ); strmr.Write( out ); } } template void ReadVirtualBase( Base *base, ipstream& in ) { char ch; in >> ch; switch( ch ) { case pstream::ptIndexed: { break; // We've already read this virtual base } case pstream::ptObject: { uint32 ver = 0; if( in.getVersion() > 0 ) ver = in.readWord32(); Base::Streamer strmr(base); // register the address in.registerObject(strmr.GetObject()); strmr.Read( in, ver ); break; } } } /* Individual Components for Streamable Declarations */ #define DECLARE_STREAMER( exp, cls, ver ) \ public: \ class exp Streamer : public TNewStreamer \ { \ public: \ \ Streamer( TStreamableBase *obj ); \ \ virtual uint32 ClassVersion() const \ { return ver; } \ \ virtual void Write( opstream& ) const; \ virtual void *Read( ipstream&, uint32 ) const; \ \ cls *GetObject() const \ { \ return object; \ } \ \ static TStreamer *Build( TStreamableBase *obj ) \ { \ return new Streamer( obj ? obj : new cls(streamableInit) ); \ } \ \ private: \ cls *object; \ \ }; \ friend Streamer; \ friend void ReadBaseObject( cls *, ipstream& ); \ friend void WriteBaseObject( cls *, opstream& ); \ friend void ReadVirtualBase( cls *, ipstream& ); \ friend void WriteVirtualBase( cls *, opstream& ) #define DECLARE_STREAMER_FROM_BASE( exp, cls, base ) \ public: \ class exp Streamer : public base::Streamer \ { \ public: \ \ Streamer( TStreamableBase *obj ) : base::Streamer(obj){} \ \ cls *GetObject() const \ { \ return object; \ } \ \ static TStreamer *Build( TStreamableBase *obj ) \ { \ return new Streamer( obj ? obj : new cls(streamableInit) ); \ } \ \ private: \ cls *object; \ \ }; \ friend Streamer; \ friend void ReadBaseObject( cls *, ipstream& ); \ friend void WriteBaseObject( cls *, opstream& ); \ friend void ReadVirtualBase( cls *, ipstream& ); \ friend void WriteVirtualBase( cls *, opstream& ) #define DECLARE_ABSTRACT_STREAMER( exp, cls, ver ) \ public: \ class exp Streamer : public TNewStreamer \ { \ public: \ \ Streamer( TStreamableBase *obj ); \ \ virtual uint32 ClassVersion() const \ { return ver; } \ \ virtual void Write( opstream& ) const; \ virtual void *Read( ipstream&, uint32 ) const; \ \ cls *GetObject() const \ { \ return object; \ } \ \ private: \ cls *object; \ \ }; \ friend Streamer; \ friend void ReadBaseObject( cls *, ipstream& ); \ friend void WriteBaseObject( cls *, opstream& ); \ friend void ReadVirtualBase( cls *, ipstream& ); \ friend void WriteVirtualBase( cls *, opstream& ) #define DECLARE_STREAMABLE_OPS( cls ) \ static ipstream& readRef( ipstream& is, cls& cl ); \ friend inline ipstream& operator >> ( ipstream& is, cls& cl ) \ { return cls::readRef( is, cl ); } \ static ipstream& readPtr( ipstream& is, cls*& cl ); \ friend inline ipstream& operator >> ( ipstream& is, cls*& cl ) \ { return cls::readPtr( is, cl ); } \ static opstream& writeRef( opstream& is, const cls& cl ); \ friend inline opstream& operator << ( opstream& os, const cls& cl ) \ { return cls::writeRef( os, cl ); } \ static opstream& writePtr( opstream& is, const cls* cl ); \ friend inline opstream& operator << ( opstream& os, const cls* cl ) \ { return cls::writePtr( os, cl ); } #define DECLARE_STREAMABLE_CTOR( cls ) \ public: \ cls ( StreamableInit ) #if defined( BI_NO_RTTI ) #define DECLARE_CASTABLE \ public: \ virtual void *FindBase( Type_id id ) const; \ public: \ virtual Type_id CastableID() const; \ virtual void *MostDerived() const { return (void *)this; } \ static Type_id CastableIdent #else #define DECLARE_CASTABLE friend class typeinfo #endif #define DECLARE_STREAMABLE( exp, cls, ver ) \ DECLARE_CASTABLE; \ DECLARE_STREAMER( exp, cls, ver ); \ DECLARE_STREAMABLE_OPS( cls ); \ DECLARE_STREAMABLE_CTOR( cls ) #define DECLARE_STREAMABLE_FROM_BASE( exp, cls, base ) \ DECLARE_CASTABLE; \ DECLARE_STREAMER_FROM_BASE( exp, cls, base ); \ DECLARE_STREAMABLE_OPS( cls ); \ DECLARE_STREAMABLE_CTOR( cls ) #define DECLARE_ABSTRACT_STREAMABLE( exp, cls, ver ) \ DECLARE_CASTABLE; \ DECLARE_ABSTRACT_STREAMER( exp, cls, ver ); \ DECLARE_STREAMABLE_OPS( cls ); \ DECLARE_STREAMABLE_CTOR( cls ) #if !defined( BI_NO_RTTI ) #define IMPLEMENT_CASTABLE( cls ) #define IMPLEMENT_CASTABLE1( cls, base1 ) #define IMPLEMENT_CASTABLE2( cls, base1, base2 ) #define IMPLEMENT_CASTABLE3( cls, base1, base2, base3 ) #define IMPLEMENT_CASTABLE4( cls, base1, base2, base3, base4 ) #define IMPLEMENT_CASTABLE5( cls, base1, base2, base3, base4, base5 ) #else // BI_NO_RTTI #define IMPLEMENT_CASTABLE_ID( cls ) \ TStreamableBase::Type_id cls::CastableIdent = #cls; \ TStreamableBase::Type_id cls::CastableID() const \ { \ return cls::CastableIdent; \ } \ #define IMPLEMENT_CASTABLE( cls ) \ IMPLEMENT_CASTABLE_ID( cls ); \ void *cls::FindBase( Type_id id ) const \ { \ return (strcmp( id, CastableIdent ) == 0) ? (void *)this : 0; \ } \ \ #define IMPLEMENT_CASTABLE1( cls, base1 ) \ IMPLEMENT_CASTABLE_ID( cls ); \ void *cls::FindBase( Type_id id ) const \ { \ if(strcmp( id, CastableIdent ) == 0) \ return (void *)this; \ else \ return base1::FindBase(id); \ } \ #define IMPLEMENT_CASTABLE2( cls, base1, base2 ) \ IMPLEMENT_CASTABLE_ID( cls ); \ void *cls::FindBase( Type_id id ) const \ { \ void *res = 0; \ if(strcmp( id, CastableIdent ) == 0) \ return (void *)this; \ else if( (res = base1::FindBase(id)) != 0 ) \ return res; \ else if( (res = base2::FindBase(id)) != 0 ) \ return res; \ else \ return 0; \ } \ #define IMPLEMENT_CASTABLE3( cls, base1, base2, base3 ) \ IMPLEMENT_CASTABLE_ID( cls ); \ void *cls::FindBase( Type_id id ) const \ { \ void *res = 0; \ if(strcmp( id, CastableIdent ) == 0) \ return (void *)this; \ else if( (res = base1::FindBase(id)) != 0 ) \ return res; \ else if( (res = base2::FindBase(id)) != 0 ) \ return res; \ else if( (res = base3::FindBase(id)) != 0 ) \ return res; \ else \ return 0; \ } \ #define IMPLEMENT_CASTABLE4( cls, base1, base2, base3, base4 ) \ IMPLEMENT_CASTABLE_ID( cls ); \ void *cls::FindBase( Type_id id ) const \ { \ void *res = 0; \ if(strcmp( id, CastableIdent ) == 0) \ return (void *)this; \ else if( (res = base1::FindBase(id)) != 0 ) \ return res; \ else if( (res = base2::FindBase(id)) != 0 ) \ return res; \ else if( (res = base3::FindBase(id)) != 0 ) \ return res; \ else if( (res = base4::FindBase(id)) != 0 ) \ return res; \ else \ return 0; \ } \ #define IMPLEMENT_CASTABLE5( cls, base1, base2, base3, base4, base5 )\ IMPLEMENT_CASTABLE_ID( cls ); \ void *cls::FindBase( Type_id id ) const \ { \ void *res = 0; \ if(strcmp( id, CastableIdent ) == 0) \ return (void *)this; \ else if( (res = base1::FindBase(id)) != 0 ) \ return res; \ else if( (res = base2::FindBase(id)) != 0 ) \ return res; \ else if( (res = base3::FindBase(id)) != 0 ) \ return res; \ else if( (res = base4::FindBase(id)) != 0 ) \ return res; \ else if( (res = base5::FindBase(id)) != 0 ) \ return res; \ else \ return 0; \ } \ #endif // BI_NO_RTTI #if defined( BI_NO_RTTI ) # define IMPLEMENT_STREAMABLE_CLASS( cls ) \ TStreamableClass r ## cls( cls::CastableIdent, &cls::Streamer::Build ) #else # define IMPLEMENT_STREAMABLE_CLASS( cls ) \ TStreamableClass r ## cls( typeid(cls).name(), &cls::Streamer::Build ) #endif #define IMPLEMENT_STREAMABLE_POINTER( cls ) \ ipstream& cls::readPtr( ipstream& is, cls*& cl ) \ { \ TStreamableBase *temp = 0; \ is.readObjectPointer( temp ); \ cl = TYPESAFE_DOWNCAST(temp,cls); \ return is; \ } \ ipstream& cls::readRef( ipstream& is, cls& cl ) \ { \ TStreamableBase *ptr = &cl; \ is.readObject( ptr ); \ return is; \ } \ opstream& cls::writeRef( opstream& os, const cls& cl ) \ { \ os.writeObject( &cl ); \ return os; \ } \ opstream& cls::writePtr( opstream& os, const cls* cl ) \ { \ os.writeObjectPointer( cl ); \ return os; \ } #define IMPLEMENT_STREAMER( cls ) \ cls::Streamer::Streamer( TStreamableBase *obj ) : \ TNewStreamer(obj), object(TYPESAFE_DOWNCAST(obj,cls)){} \ #define IMPLEMENT_STREAMABLE_CTOR( cls ) \ cls::cls ( StreamableInit ) {} #define IMPLEMENT_STREAMABLE_CTOR1( cls, base1 ) \ cls::cls ( StreamableInit ) : base1( streamableInit ) {} #define IMPLEMENT_STREAMABLE_CTOR2( cls, base1, base2 ) \ cls::cls ( StreamableInit ) : \ base1 ( streamableInit ), \ base2 ( streamableInit ) {} #define IMPLEMENT_STREAMABLE_CTOR3( cls, base1, base2, base3 ) \ cls::cls ( StreamableInit ) : \ base1 ( streamableInit ), \ base2 ( streamableInit ), \ base3 ( streamableInit ) {} #define IMPLEMENT_STREAMABLE_CTOR4( cls, base1, base2, base3, base4 )\ cls::cls ( StreamableInit ) : \ base1 ( streamableInit ), \ base2 ( streamableInit ), \ base3 ( streamableInit ), \ base4 ( streamableInit ) {} #define IMPLEMENT_STREAMABLE_CTOR5( cls, base1,base2,base3,base4,base5)\ cls::cls ( StreamableInit ) : \ base1 ( streamableInit ), \ base2 ( streamableInit ), \ base3 ( streamableInit ), \ base4 ( streamableInit ), \ base5 ( streamableInit ) {} /* Standard Combinations of Streamable Implementations */ #define IMPLEMENT_ABSTRACT_STREAMABLE( cls ) \ IMPLEMENT_STREAMER( cls ); \ IMPLEMENT_STREAMABLE_CTOR( cls ); \ IMPLEMENT_STREAMABLE_POINTER( cls ) #define IMPLEMENT_ABSTRACT_STREAMABLE1( cls, base1 ) \ IMPLEMENT_STREAMER( cls ); \ IMPLEMENT_STREAMABLE_CTOR1( cls, base1 ); \ IMPLEMENT_STREAMABLE_POINTER( cls ) #define IMPLEMENT_ABSTRACT_STREAMABLE2( cls, base1, base2 ) \ IMPLEMENT_STREAMER( cls ); \ IMPLEMENT_STREAMABLE_CTOR2( cls, base1, base2 ); \ IMPLEMENT_STREAMABLE_POINTER( cls ) #define IMPLEMENT_ABSTRACT_STREAMABLE3( cls, base1, base2, base3 ) \ IMPLEMENT_STREAMER( cls ); \ IMPLEMENT_STREAMABLE_CTOR3( cls, base1, base2, base3 ); \ IMPLEMENT_STREAMABLE_POINTER( cls ) #define IMPLEMENT_ABSTRACT_STREAMABLE4( cls, base1, base2, base3, base4 )\ IMPLEMENT_STREAMER( cls ); \ IMPLEMENT_STREAMABLE_CTOR4( cls, base1, base2, base3, base4 ); \ IMPLEMENT_STREAMABLE_POINTER( cls ) #define IMPLEMENT_ABSTRACT_STREAMABLE5( cls, base1, base2, base3, base4, base5 )\ IMPLEMENT_STREAMER( cls ); \ IMPLEMENT_STREAMABLE_CTOR5( cls, base1, base2, base3, base4, base5 );\ IMPLEMENT_STREAMABLE_POINTER( cls ) #define IMPLEMENT_STREAMABLE( cls ) \ IMPLEMENT_STREAMABLE_CLASS( cls ); \ IMPLEMENT_ABSTRACT_STREAMABLE( cls ) #define IMPLEMENT_STREAMABLE1( cls, base1 ) \ IMPLEMENT_STREAMABLE_CLASS( cls ); \ IMPLEMENT_ABSTRACT_STREAMABLE1( cls, base1 ) #define IMPLEMENT_STREAMABLE2( cls, base1, base2 ) \ IMPLEMENT_STREAMABLE_CLASS( cls ); \ IMPLEMENT_ABSTRACT_STREAMABLE2( cls, base1, base2 ) #define IMPLEMENT_STREAMABLE3( cls, base1, base2, base3 ) \ IMPLEMENT_STREAMABLE_CLASS( cls ); \ IMPLEMENT_ABSTRACT_STREAMABLE3( cls, base1, base2, base3 ) #define IMPLEMENT_STREAMABLE4( cls, base1, base2, base3, base4 ) \ IMPLEMENT_STREAMABLE_CLASS( cls ); \ IMPLEMENT_ABSTRACT_STREAMABLE4( cls, base1, base2, base3, base4 ) #define IMPLEMENT_STREAMABLE5( cls, base1, base2, base3, base4, base5 )\ IMPLEMENT_STREAMABLE_CLASS( cls ); \ IMPLEMENT_ABSTRACT_STREAMABLE5( cls, base1, base2, base3, base4, base5 ) #define IMPLEMENT_STREAMABLE_FROM_BASE( cls, base1 ) \ IMPLEMENT_STREAMABLE_CLASS( cls ); \ IMPLEMENT_STREAMABLE_CTOR1( cls, base1 ); \ IMPLEMENT_STREAMABLE_POINTER( cls ) #if defined( BI_CLASSLIB_NO_po ) #pragma option -po. #endif #endif // CLASSLIB_OBJSTRM_H