home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / classsrc.pak / OBJSTRM.CPP < prev    next >
C/C++ Source or Header  |  1997-07-23  |  18KB  |  787 lines

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