home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 20.ddi / CLASSSRC.PAK / OBJSTRM.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  16.6 KB  |  756 lines

  1. /*------------------------------------------------------------------------*/
  2. /*                                                                        */
  3. /*  OBJSTRM.CPP                                                           */
  4. /*                                                                        */
  5. /*  Copyright (c) 1992, 1993 Borland International                        */
  6. /*  All Rights Reserved                                                   */
  7. /*                                                                        */
  8. /*------------------------------------------------------------------------*/
  9.  
  10. #if !defined( __ALLOC_H )
  11. #include <alloc.h>
  12. #endif  // __ALLOC_H
  13.  
  14. #if !defined( __CHECKS_H )
  15. #include <checks.h>
  16. #endif  // __CHECKS_H
  17.  
  18. #if !defined( __CSTRING_H )
  19. #include <cstring.h>
  20. #endif  // __CSTRING_H
  21.  
  22. #if !defined( __CLASSLIB_STREAMBL_H )
  23. #include "classlib\streambl.h"
  24. #endif  // __CLASSLIB_STREAMBL_H
  25.  
  26. #if !defined( __CLASSLIB_OBJSTRM_H )
  27. #include "classlib\objstrm.h"
  28. #endif  // __CLASSLIB_OBJSTRM_H
  29.  
  30. #if defined( __FLAT__ )
  31. #define _fstrncpy strncpy
  32. #define _fstrcpy  strcpy
  33. #define _fstrlen  strlen
  34. #define _fmemcpy  memcpy
  35. #define farmalloc malloc
  36. #endif
  37.  
  38. DIAG_DEFINE_GROUP(Objstrm,1,0);
  39.  
  40. const uint32 streamVersion = 0x0100;
  41. const char versionIndicator = ':';
  42.  
  43. const char EOS = '\0';
  44.  
  45. const uint8 nullStringLen = UCHAR_MAX;
  46.  
  47. TStreamableTypes *pstream::types = 0;
  48.  
  49. const char *TStreamer::StreamableName() const
  50. {
  51.     return 0;
  52. }
  53.  
  54. TStreamableClass::TStreamableClass( const char *n,
  55.                                     BUILDER b,
  56.                                     int d,
  57.                                     ModuleId id ) :
  58.     ObjectBuilder( b, d ),
  59.     ModId(id)
  60. {
  61.     ObjectId = new char[strlen(n)+1];
  62.     strcpy( CONST_CAST(char *,ObjectId), n );
  63.     ipstream::initTypes();
  64.     if( id != 0 )   // id == 0 is used only during lookup.
  65.                     // It flags an instance that shouldn't be registered
  66.         pstream::types->RegisterType( id, *this );
  67. }
  68.  
  69. TStreamableClass::~TStreamableClass()
  70. {
  71.     if( ModId != 0 )
  72.         pstream::types->UnRegisterType( ModId, *this );
  73.     delete [] CONST_CAST(char *,ObjectId);
  74. }
  75.  
  76. void TStreamableTypes::RegisterType( ModuleId, TStreamableClass& ts )
  77. {
  78.     Types.Add(&ts);
  79. }
  80.  
  81. void TStreamableTypes::UnRegisterType( ModuleId, TStreamableClass& ts )
  82. {
  83.     Types.Detach(&ts);
  84. }
  85.  
  86. const ObjectBuilder *TStreamableTypes::Lookup( ModuleId,
  87.                                                const char *name ) const
  88. {
  89.     unsigned loc = Types.Find(&TStreamableClass(name,0,0,0));
  90.     if( loc == UINT_MAX )
  91.         {
  92.         string msg;
  93.         msg.reserve(128);
  94.         msg = "Attempt to stream unregistered type '";
  95.         msg += name;
  96.         msg += "'";
  97.         throw xmsg(msg);
  98.         }
  99.     return Types[loc];
  100. }
  101.  
  102. void TPReadObjects::RemoveAll()
  103. {
  104.     Data.Flush();
  105. }
  106.  
  107. void TPReadObjects::RegisterObject( TStreamableBase *adr )
  108. {
  109.     Data.Add( adr );
  110. }
  111.  
  112. TStreamableBase *TPReadObjects::Find( P_id_type id )
  113. {
  114.     return Data[id];
  115. }
  116.  
  117. TPReadObjects::TPReadObjects() : Data(5,5)
  118. {
  119.     Data.Add(0);    // prime it: 0 is not a legal index.
  120. }
  121.  
  122. TPWrittenObjects::TPWrittenObjects() : CurId(0), Data(5,5)
  123. {
  124. }
  125.  
  126. void TPWrittenObjects::RemoveAll()
  127. {
  128.     CurId = 0; Data.Flush();
  129. }
  130.  
  131. void TPWrittenObjects::RegisterObject( TStreamableBase *adr )
  132. {
  133.     Data.Add( TPWObj( ((char *)(void *)adr)+1, ++CurId ) );
  134. }
  135.  
  136. void TPWrittenObjects::RegisterVB( const TStreamableBase *adr )
  137. {
  138.     Data.Add( TPWObj( adr, ++CurId ) );
  139. }
  140.  
  141. P_id_type TPWrittenObjects::FindObject( TStreamableBase *d )
  142. {
  143.     unsigned res = Data.Find( TPWObj(((char *)(void *)d)+1,0) );
  144.     if( res == UINT_MAX )
  145.         return 0;
  146.     else
  147.         return Data[res].Ident;
  148. }
  149.  
  150. P_id_type TPWrittenObjects::FindVB( TStreamableBase *d )
  151. {
  152.     unsigned res = Data.Find( TPWObj(d,0) );
  153.     if( res == UINT_MAX )
  154.         return 0;
  155.     else
  156.         return Data[res].Ident;
  157. }
  158.  
  159. pstream::~pstream()
  160. {
  161. }
  162.  
  163. void pstream::initTypes()
  164. {
  165.     if( types == 0 )
  166.         types = new TStreamableTypes;
  167. }
  168.  
  169. streampos ipstream::tellg()
  170. {
  171.     streampos res;
  172.     if( !good() )
  173.         res = streampos(EOF);
  174.     else
  175.         {
  176.         res = bp->seekoff( 0, ios::cur, ios::in );
  177.         if( res == streampos(EOF) )
  178.             clear( ios::failbit );
  179.         }
  180.     return res;
  181. }
  182.  
  183. ipstream& ipstream::seekg( streampos pos )
  184. {
  185.     if( good() )
  186.         {
  187.         objs.RemoveAll();
  188.         if( bp->seekoff( pos, ios::beg, ios::in ) == streampos(EOF) )
  189.             clear( ios::failbit );
  190.         }
  191.     return *this;
  192. }
  193.  
  194. ipstream& ipstream::seekg( streamoff off, ios::seek_dir dir )
  195. {
  196.     if( good() )
  197.         {
  198.         objs.RemoveAll();
  199.         if( bp->seekoff( off, dir, ios::in ) == streampos(EOF) )
  200.             clear( ios::failbit );
  201.         }
  202.     return *this;
  203. }
  204.  
  205. uint8 ipstream::readByte()
  206. {
  207.     int res;
  208.     if( !good() )
  209.         res = uint8(0);
  210.     else
  211.         {
  212.         res = bp->sbumpc();
  213.         if( res == EOF )
  214.             clear( ios::failbit );
  215.         }
  216.     return uint8(res);
  217. }
  218.  
  219. void ipstream::readBytes( void *data, size_t sz )
  220. {
  221.     PRECONDITION( data != 0 );
  222.     if( good() && sz > 0 )
  223.         {
  224.         if( bp->sgetn( (char *)data, sz ) != sz )
  225.             clear( ios::failbit );
  226.         }
  227. }
  228.  
  229. void ipstream::freadBytes( void _BIDSFARDATA *data, size_t sz )
  230. {
  231.     PRECONDITION( data != 0 );
  232.  
  233.     if( good() && sz > 0 )
  234.         {
  235.         char *buf = new char[sz];
  236.  
  237.         if( bp->sgetn( buf, sz ) != sz )
  238.             clear( ios::failbit );
  239.         else
  240.             _fmemcpy( data, buf, sz);
  241.  
  242.         delete [] buf;
  243.         }
  244. }
  245.  
  246. uint32 ipstream::readWord()
  247. {
  248.     if( getVersion() > 0 )
  249.         return readWord32();
  250.     else
  251.         return readWord16();
  252. }
  253.  
  254. uint16 ipstream::readWord16()
  255. {
  256.     if( !good() )
  257.         return 0;
  258.     else
  259.         {
  260.         uint16 temp;
  261.         if( bp->sgetn( (char *)&temp, sizeof( temp ) ) != sizeof( temp ) )
  262.             clear( ios::failbit );
  263.         return temp;
  264.         }
  265. }
  266.  
  267. uint32 ipstream::readWord32()
  268. {
  269.     if( !good() )
  270.         return 0;
  271.     else
  272.         {
  273.         uint32 temp;
  274.         if( bp->sgetn( (char *)&temp, sizeof( temp ) ) != sizeof( temp ) )
  275.             clear( ios::failbit );
  276.         return temp;
  277.         }
  278. }
  279.  
  280. char *ipstream::readString()
  281. {
  282.     if( !good() )
  283.         return 0;
  284.     else
  285.         {
  286.         uint8 len = readByte();
  287.         if( len == nullStringLen )
  288.             return 0;
  289.         char *buf = new char[len+1];
  290.         if( buf == 0 )
  291.             return 0;
  292.         readBytes( buf, len );
  293.         buf[len] = EOS;
  294.         return buf;
  295.         }
  296. }
  297.  
  298. char *ipstream::readString( char *buf, unsigned maxLen )
  299. {
  300.     PRECONDITION( buf != 0 );
  301.  
  302.     if( !good() )
  303.         return 0;
  304.     else
  305.         {
  306.         uint8 len = readByte();
  307.         if( len > maxLen-1 )
  308.             return 0;
  309.         readBytes( buf, len );
  310.         buf[len] = EOS;
  311.         return buf;
  312.         }
  313. }
  314.  
  315. char _BIDSFARDATA *ipstream::freadString()
  316. {
  317.     if( !good() )
  318.         return 0;
  319.     else
  320.         {
  321.         uint8 len = readByte();
  322.         if( len == nullStringLen )
  323.             return 0;
  324.  
  325.         char _BIDSFARDATA *buf = new _BIDSFARDATA char[len+1];
  326.         freadBytes(buf, len);
  327.         buf[len] = EOS;
  328.         return buf;
  329.         }
  330. }
  331.  
  332. char _BIDSFARDATA *ipstream::freadString( char _BIDSFARDATA *buf, unsigned maxLen )
  333. {
  334.     PRECONDITION(buf != 0 );
  335.  
  336.     if( !good() )
  337.         return 0;
  338.     else
  339.         {
  340.         uint8 len = readByte();
  341.  
  342.         if( len > maxLen-1 )
  343.             return 0;
  344.  
  345.         freadBytes( buf, len);
  346.         buf[len] = EOS;
  347.         return buf;
  348.         }
  349. }
  350.  
  351. void ipstream::readVersion()
  352. {
  353.     if( !good() )
  354.         version = 0;
  355.     else
  356.         {
  357.         int res = bp->sgetc();
  358.         if( res == EOF )
  359.             {
  360.             clear( ios::eofbit );
  361.             version = 0;
  362.             return;
  363.             }
  364.         if( res != versionIndicator )
  365.             version = 0;
  366.         else
  367.             {
  368.             bp->sbumpc();
  369.             version = readWord32();
  370.             }
  371.         }
  372. }
  373.  
  374. TStreamableBase _FAR *ipstream::readObject( TStreamableBase _FAR *&mem,
  375.                                             ModuleId mid )
  376. {
  377.     if( good() )
  378.         {
  379.         const ObjectBuilder *pc = readPrefix( mid );
  380.         if( pc == 0 )
  381.             mem = 0;
  382.         else
  383.             {
  384.             readData( pc, mem );
  385.             readSuffix();
  386.             }
  387.         }
  388.     return mem;
  389. }
  390.  
  391. const ObjectBuilder *ipstream::readPrefix( ModuleId mid )
  392. {
  393.     char ch = readByte();
  394.     if( ch != '[' )
  395.         {
  396.         clear( ios::failbit );
  397.         return 0;
  398.         }
  399.  
  400.     char name[128];
  401.     name[0] = EOS;
  402.     readString( name, sizeof name );
  403.     if( name[0] == EOS )
  404.         {
  405.         clear( ios::failbit );
  406.         return 0;
  407.         }
  408.  
  409.     TRACEX(Objstrm,0,"Reading " << name);
  410.     const ObjectBuilder *res = types->Lookup( mid, name );
  411.     WARNX(Objstrm,res==0,0,"Unrecognized class identifier: " << name);
  412.     if( res == 0 )
  413.         {
  414.         clear( ios::failbit );
  415.         return 0;
  416.         }
  417.  
  418.     return res;
  419. }
  420.  
  421. void ipstream::readData( const ObjectBuilder *c, TStreamableBase _FAR *&mem )
  422. {
  423.     TStreamer *strmr = c->Builder(mem);
  424.     mem = strmr->GetObject();
  425.  
  426.     // register the address
  427.     registerObject( mem );
  428.  
  429.     uint32 classVer = 0;
  430.     if( getVersion() > 0 )
  431.         classVer = readWord32();
  432.  
  433.     strmr->Read( *this, classVer );
  434.     delete strmr;
  435. }
  436.  
  437. void ipstream::readSuffix()
  438. {
  439.     if( !good() )
  440.         return;
  441.     char ch = readByte();
  442.     if( ch != ']' )
  443.         clear( ios::failbit );
  444. }
  445.  
  446. TStreamableBase _FAR *ipstream::readObjectPointer( TStreamableBase _FAR *&mem,
  447.                                                    ModuleId mid )
  448. {
  449.     if( !good() )
  450.         return 0;
  451.  
  452.     char ch = readByte();
  453.     switch( ch )
  454.         {
  455.         case pstream::ptNull:
  456.             mem = 0;
  457.             break;
  458.         case pstream::ptIndexed:
  459.             {
  460.             P_id_type index = P_id_type(readWord());
  461.             mem = find( index );
  462.             CHECK( mem != 0 );
  463.             break;
  464.             }
  465.         case pstream::ptObject:
  466.             {
  467.             const ObjectBuilder *pc = readPrefix( mid );
  468.             readData( pc, mem );
  469.             readSuffix();
  470.             break;
  471.             }
  472.         default:
  473.             clear( ios::failbit );
  474.             break;
  475.         }
  476.     return mem;
  477. }
  478.  
  479. opstream::opstream()
  480. {
  481.     objs = new TPWrittenObjects;
  482.     if( bp != 0 )
  483.         writeVersion();
  484. }
  485.  
  486. opstream::opstream( streambuf * sb )
  487. {
  488.     objs = new TPWrittenObjects;
  489.     pstream::init( sb );
  490.     writeVersion();
  491. }
  492.  
  493. streampos opstream::tellp()
  494. {
  495.     streampos res;
  496.     if( !good() )
  497.         res = streampos(EOF);
  498.     else
  499.         {
  500.         res = bp->seekoff( 0, ios::cur, ios::out );
  501.         if( res == streampos(EOF) )
  502.             clear( ios::failbit );
  503.         }
  504.     return res;
  505. }
  506.  
  507. opstream& opstream::seekp( streampos pos )
  508. {
  509.     if( good() )
  510.         {
  511.         objs->RemoveAll();
  512.         if( bp->seekoff( pos, ios::beg, ios::out ) == streampos(EOF) )
  513.             clear( ios::failbit );
  514.         }
  515.     return *this;
  516. }
  517.  
  518. opstream& opstream::seekp( streamoff pos, ios::seek_dir dir )
  519. {
  520.     if( good() )
  521.         {
  522.         objs->RemoveAll();
  523.         if( bp->seekoff( pos, dir, ios::out ) == streampos(EOF) )
  524.             clear( ios::failbit );
  525.         }
  526.     return *this;
  527. }
  528.  
  529. void opstream::writeVersion()
  530. {
  531.     if( good() )
  532.         {
  533.         writeByte( versionIndicator );
  534.         writeWord32( streamVersion );
  535.         }
  536. }
  537.  
  538. opstream& opstream::flush()
  539. {
  540.     if( bp->sync() == EOF )
  541.         clear( ios::badbit );
  542.     return *this;
  543. }
  544.  
  545. void opstream::writeByte( uint8 ch )
  546. {
  547.     if( good() )
  548.         {
  549.         if( bp->sputc( ch ) == EOF )
  550.             clear( ios::failbit );
  551.         }
  552. }
  553.  
  554. void opstream::writeBytes( const void *data, size_t sz )
  555. {
  556.     PRECONDITION( data != 0 );
  557.  
  558.     if( good() && sz > 0 )
  559.         {
  560.         if( bp->sputn( (char *)data, sz ) != sz )
  561.             clear( ios::failbit );
  562.         }
  563. }
  564.  
  565. void opstream::writeWord16( uint16 word16 )
  566. {
  567.     if( good() )
  568.         {
  569.         if( bp->sputn( (char *)&word16, sizeof(word16) ) != sizeof(word16) )
  570.             clear( ios::failbit );
  571.         }
  572. }
  573.  
  574. void opstream::writeWord32( uint32 word32 )
  575. {
  576.     if( good() )
  577.         {
  578.         if( bp->sputn( (char *)&word32, sizeof(word32) ) != sizeof(word32) )
  579.             clear( ios::failbit );
  580.         }
  581. }
  582.  
  583. void opstream::fwriteBytes( const void _BIDSFARDATA *data, size_t sz )
  584. {
  585.     PRECONDITION( data != 0 );
  586.  
  587.     if( good() && sz > 0 )
  588.         {
  589.         char *buf = new char[sz];
  590.  
  591.         _fmemcpy( buf, data, sz );
  592.         if( bp->sputn( (char *)buf, sz ) != sz )
  593.             clear( ios::failbit );
  594.  
  595.         delete buf;
  596.         }
  597. }
  598.  
  599. void opstream::writeString( const char *str )
  600. {
  601.     if( !good() )
  602.         return;
  603.  
  604.     if( str == 0 )
  605.         {
  606.         writeByte( nullStringLen );
  607.         return;
  608.         }
  609.     int len = strlen( str );
  610.     writeByte( (uint8)len );
  611.     writeBytes( str, len );
  612. }
  613.  
  614. void opstream::fwriteString( const char _BIDSFARDATA * str )
  615. {
  616.     if( !good() )
  617.         return;
  618.  
  619.     if( str == 0 )
  620.         {
  621.         writeByte( nullStringLen );
  622.         return;
  623.         }
  624.     int len = _fstrlen( str );
  625.     writeByte( (uint8)len );
  626.     fwriteBytes(str, len);
  627. }
  628.  
  629. #pragma warn -par
  630. void opstream::writeObject( const TStreamableBase _FAR *mem, int isPtr, ModuleId mid )
  631. {
  632.     WARNX(Objstrm,
  633.           !isPtr && findObject( CONST_CAST(TStreamableBase *,mem) ),
  634.           0,
  635.           "Pointer written before object: "     \
  636.               << _TYPENAME(mem) << '(' << (void _FAR *)mem << ')' );
  637.     if( good() )
  638.         {
  639.         writePrefix( mem );
  640.         writeData( mem, mid );
  641.         writeSuffix( mem );
  642.         }
  643. }
  644. #pragma warn +par
  645.  
  646. void opstream::writeObjectPointer( const TStreamableBase *t, ModuleId mid )
  647. {
  648.     if( good() )
  649.         {
  650.         P_id_type index;
  651.         if( t == 0 )
  652.             writeByte( pstream::ptNull );
  653.         else if( (index = findObject( CONST_CAST(TStreamableBase *,t) )) != 0 )
  654.             {
  655.             writeByte( pstream::ptIndexed );
  656.             writeWord( index );
  657.             }
  658.         else
  659.             {
  660.             writeByte( pstream::ptObject );
  661.             writeObject( t, 1, mid );
  662.             }
  663.         }
  664. }
  665.  
  666. void opstream::writePrefix( const TStreamableBase *t )
  667. {
  668.     if( good() )
  669.         {
  670.         writeByte( '[' );
  671.         writeString( _TYPENAME(t) );
  672.         }
  673. }
  674.  
  675. void opstream::writeData( const TStreamableBase *t, ModuleId mid )
  676. {
  677.     if( good() )
  678.         {
  679.         registerObject( CONST_CAST(TStreamableBase *,t) );
  680.         const ObjectBuilder *res = types->Lookup( mid, _TYPENAME(t) );
  681.         CHECKX(res,_TYPENAME(t));
  682.         TStreamer *strmr = res->Builder(CONST_CAST(TStreamableBase *,t));
  683.         writeWord32( strmr->ClassVersion() );
  684.         strmr->Write( *this );
  685.         delete strmr;
  686.         }
  687. }
  688.  
  689. void fpbase::open( const char *b, int m, int prot )
  690. {
  691.     if( buf.is_open() )
  692.         clear(ios::failbit);        // fail - already open
  693.     else if( buf.open(b, m, prot) )
  694.         clear(ios::goodbit);        // successful open
  695.     else
  696.         clear(ios::badbit);         // open failed
  697. }
  698.  
  699. void fpbase::attach( int f )
  700. {
  701.     if( buf.is_open() )
  702.         clear(ios::failbit);
  703.     else if( buf.attach(f) )
  704.         clear(ios::goodbit);
  705.     else
  706.         clear(ios::badbit);
  707. }
  708.  
  709. void fpbase::close()
  710. {
  711.     if( buf.close() )
  712.         clear(ios::goodbit);
  713.     else
  714.         clear(ios::failbit);
  715. }
  716.  
  717. void fpbase::setbuf(char* b, int len)
  718. {
  719.     if( buf.setbuf(b, len) )
  720.         clear(ios::goodbit);
  721.     else
  722.         clear(ios::failbit);
  723. }
  724.  
  725. //
  726. //  These operators are not friends of string, so
  727. //  they must use only the public interface.
  728. //
  729. opstream _BIDSFAR& _BIDSENTRY _BIDSFUNC operator << ( opstream _BIDSFAR& os,
  730.                                                       const string _BIDSFAR& str )
  731. {
  732.     os.writeString( str.c_str() );
  733.     return os;
  734. }
  735.  
  736. ipstream _BIDSFAR& _BIDSENTRY _BIDSFUNC operator >> ( ipstream _BIDSFAR& is,
  737.                                                       string _BIDSFAR& str )
  738. {
  739.     if( is.good() )
  740.         {
  741.         uint8 len = is.readByte();
  742.         if( len == nullStringLen )
  743.             str = "";
  744.         else
  745.             {
  746.             char *temp = new char[len+1];
  747.             is.readBytes( temp, len );
  748.             temp[len] = EOS;
  749.             str = temp;
  750.             }
  751.         }
  752.     return is;
  753. }
  754.  
  755.  
  756.