home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 May / Pcwk5b98.iso / Borland / Cplus45 / BC45 / OWL1.PAK / OBJSTRM.CPP < prev    next >
C/C++ Source or Header  |  1995-08-29  |  19KB  |  811 lines

  1. // Borland C++ - (C) Copyright 1992 by Borland International
  2.  
  3. /*------------------------------------------------------------*/
  4. /* filename -       objstrm.cpp                              */
  5. /*                                                            */
  6. /* function(s)                                                */
  7. /*                  Member function(s) of following classes:  */
  8. /*                     TStreamable                            */
  9. /*                     TStreamableClass                       */
  10. /*                     TStreamableTypes                       */
  11. /*                     TPWrittenObjects                       */
  12. /*                     TPReadObjects                          */
  13. /*                     pstream                                */
  14. /*                     ipstream                               */
  15. /*                     opstream                               */
  16. /*                     iopstream                              */
  17. /*                     fpbase                                 */
  18. /*                     ifpstream                              */
  19. /*                     ofpstream                              */
  20. /*                     fpstream                               */
  21. /*------------------------------------------------------------*/
  22.  
  23. #if !defined( __OBJSTRM_H )
  24. #include <objstrm.h>
  25. #endif    // __OBJSTRM_H
  26.  
  27. #if !defined( __STRING_H )
  28. #include <string.h>
  29. #endif  // __STRING_H
  30.  
  31. #if !defined( __FSTREAM_H )
  32. #include <fstream.h>
  33. #endif  // __FSTREAM_H
  34.  
  35. #if !defined( __IO_H )
  36. #include <io.h>
  37. #endif  // __IO_H
  38.  
  39. #if !defined( __STAT_H )
  40. #include <sys\Stat.h>
  41. #endif  // __STAT_H
  42.  
  43. #if !defined( __FCNTL_H )
  44. #include <fcntl.h>
  45. #endif  // __FCNTL_H
  46.  
  47. #if !defined( __ASSERT_H )
  48. #include <assert.h>
  49. #endif  // __ASSERT_H
  50.  
  51. #if !defined(__ALLOC_H)
  52. #include <alloc.h>
  53. #endif // __ALLOC_H
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64. #if !defined(__APPLICAT_H)
  65. #include <applicat.h>
  66. #endif
  67.  
  68. #if !defined(__WINDOBJ_H)
  69. #include <windobj.h>
  70. #endif
  71.  
  72. #if defined(__DLL__)
  73. extern "C"
  74.     unsigned _WinAllocFlag;
  75. #endif
  76.  
  77. TStreamableTypes *pstream::types;
  78.  
  79. #if defined(__DLL__)
  80.  
  81. static unsigned short GetSegmentLimit(Pvoid pMem)
  82. {
  83.     unsigned short Temp = FP_SEG(pMem);     // Temp = selector
  84.     asm lsl ax, Temp;                       // ax = segment limit
  85.     asm mov Temp, ax;                       // Temp = segment limit
  86.     return Temp;
  87. }
  88.  
  89. static unsigned short GetChecksum(Pvoid pMem, unsigned short SegmentLimit)
  90. {
  91.     unsigned long TempChecksum = 0;     // intialize checksum
  92.  
  93.     SegmentLimit -= FP_OFF(pMem);       // adjust for starting offset
  94.  
  95.     // Use either 64 bytes (32 words) or the segment limit, whichever
  96.     // is smaller
  97.     int ChecksumLimit = (SegmentLimit < 64) ? (SegmentLimit>>1) : 32;
  98.  
  99.     unsigned short _FAR *p = (unsigned short _FAR *)pMem;
  100.  
  101.     for (int i = 0; i < ChecksumLimit; i++)
  102.              TempChecksum += *p++;
  103.  
  104.     return (unsigned short)TempChecksum;
  105. }
  106.  
  107. TObjStrmRegRecord::TObjStrmRegRecord(PTStreamableClass pTStreamableClass)
  108. {
  109.     this->pTStreamableClass = pTStreamableClass;
  110.     SegmentLimit = GetSegmentLimit(pTStreamableClass->build);
  111.     Checksum = GetChecksum(pTStreamableClass->build, SegmentLimit);
  112. }
  113.  
  114. Pvoid TObjStrmRegRecord::operator new (size_t s)
  115. {
  116.     return (Pvoid)LocalLock(LocalAlloc(LPTR, s));
  117. }
  118.  
  119. void TObjStrmRegRecord::operator delete(Pvoid ptr)
  120. {
  121.     HANDLE hMem =
  122. #ifdef STRICT    
  123.            LocalHandle( (void NEAR *)FP_OFF( ptr ) );    
  124. #else
  125.            LocalHandle( FP_OFF( ptr ) );
  126. #endif
  127.     if (LocalUnlock(hMem))
  128.         LocalFree(hMem);
  129. }
  130.  
  131. int TObjStrmRegRecord::Validate()
  132. {
  133.     WORD Temp = FP_SEG(pTStreamableClass);
  134.     asm lar ax, Temp;           // get access rights
  135.     asm jnz invalid;            // invalid segment
  136.  
  137.     asm and ax, 0x0800;         // code or data?
  138.     asm jnz invalid;            // code, invalid
  139.  
  140.     // We can access the pTStreamableClass pointer.  See if segment is
  141.     // big enough to contain a TStreamableClass object.
  142.  
  143.     long TempSegmentLimit = GetSegmentLimit(pTStreamableClass);
  144.     if (TempSegmentLimit-FP_OFF(pTStreamableClass) <=
  145.         sizeof(TStreamableClass)-1)
  146.         return 0;
  147.  
  148.     // We can access the TStreamableClass object and the segment in
  149.     // which it resides is big enough to hold a TStreamableClass
  150.  
  151.     Temp = FP_SEG(pTStreamableClass->build);
  152.     asm lar ax, Temp;           // get access rights
  153.     asm jnz invalid;            // invalid selector
  154.  
  155.     asm and ax, 0x0800;         // code or data
  156.     asm jz invalid;             // data, invalid
  157.  
  158.     unsigned short ActualSegmentLimit =
  159.         GetSegmentLimit(pTStreamableClass->build);
  160.  
  161.     if (ActualSegmentLimit != SegmentLimit)
  162.     {
  163.     invalid:
  164.         return 0;
  165.     }
  166.     else
  167.         return (GetChecksum(pTStreamableClass->build,
  168.                 ActualSegmentLimit) == Checksum);
  169. }
  170.  
  171. #endif // __DLL__
  172.  
  173. TStreamableClass::TStreamableClass( const char *n, BUILDER b, int d ) :
  174.     name( n ),
  175.     build( b ),
  176.     delta( d )
  177. {
  178.     pstream::initTypes();
  179.  
  180. #if defined(__DLL__)
  181.  
  182.     TObjStrmRegRecord * pTObjStrmRegRecord =
  183.         new TObjStrmRegRecord(this);
  184.  
  185.     pstream::types->registerType(pTObjStrmRegRecord);
  186. #else
  187.     pstream::types->registerType(this);
  188. #endif
  189. }
  190.  
  191. #if defined(__DLL__)
  192. void TStreamableTypes::registerType(TObjStrmRegRecord *pTObjStrmRegRecord)
  193. {
  194.     unsigned SavedWinAllocFlag = _WinAllocFlag;
  195.     _WinAllocFlag |= GMEM_DDESHARE;
  196.  
  197.     insert((void *)pTObjStrmRegRecord);
  198.  
  199.     _WinAllocFlag = SavedWinAllocFlag;
  200. }
  201. #endif
  202.  
  203. Boolean TStreamableTypes::search( void *key, ccIndex& index )
  204. {
  205.     ccIndex l = 0;
  206.     ccIndex h = count - 1;
  207.     while( l <= h )
  208.     {
  209.         ccIndex i = (l +  h) >> 1;
  210.         // i is our midpoint
  211. #if defined(__DLL__)
  212.  
  213.         TObjStrmRegRecord * pTObjStrmRegRecord =
  214.             (TObjStrmRegRecord *)items[i];
  215.  
  216.         if (!(pTObjStrmRegRecord->Validate()))
  217.         {
  218.             // remove this entry
  219.             count--;
  220.             memmove(&items[i], &items[i+1], (count-i)*sizeof(void *));
  221.             h--;
  222.             continue;           // do the while again
  223.         }
  224. #endif
  225.         ccIndex c = compare( keyOf( items[i] ), key );
  226.         if (c < 0)
  227.             l = i + 1;
  228.         else if (c > 0)
  229.             h = i - 1;
  230.         else
  231.         {
  232.             index = i;
  233.             return True;
  234.         }
  235.     }
  236.     index = l;
  237.     return False;
  238. }
  239.  
  240. const TStreamableClass *TStreamableTypes::lookup( const char *name )
  241. {
  242.     ccIndex loc;
  243.  
  244.     if (!search((void *)name, loc))
  245.         return NULL;
  246.  
  247. #if defined(__DLL__)
  248.     return ((TObjStrmRegRecord *)at(loc))->pTStreamableClass;
  249. #else
  250.     return (PTStreamableClass)at(loc);
  251. #endif
  252. }
  253.  
  254. Pvoid TStreamableTypes::keyOf(Pvoid d)
  255. {
  256. #if defined(__DLL__)
  257.     TObjStrmRegRecord * pTObjStrmRegRecord = (TObjStrmRegRecord *)d;
  258.     return (void *)((pTObjStrmRegRecord->pTStreamableClass)->name);
  259. #else
  260.     return (void *)((PTStreamableClass)d)->name;
  261. #endif
  262. }
  263.  
  264. int TStreamableTypes::compare( void *d1, void *d2 )
  265. {
  266.     return strcmp( (char *)d1, (char *)d2 );
  267. }
  268.  
  269. void TPWrittenObjects::registerObject( const void *adr )
  270. {
  271.     TPWObj *o = new TPWObj( adr, curId++ );
  272.     insert( o );
  273. }
  274.  
  275. P_id_type TPWrittenObjects::find( const void *d )
  276. {
  277.     ccIndex loc;
  278.     if( search( Pvoid( d ), loc ) )
  279.         return ((TPWObj *)at( loc ))->ident;
  280.     else
  281.         return 0;
  282. }
  283.  
  284. int TPWrittenObjects::compare( void *o1, void *o2 )
  285. {
  286.     if( o1 == o2 )
  287.         return 0;
  288.     else if( (void huge *)o1 < (void huge *)o2 )
  289.         return -1;
  290.     else
  291.         return 1;
  292. }
  293.  
  294. void TPReadObjects::registerObject( const void *adr )
  295. {
  296.     ccIndex loc = insert( Pvoid( adr ));
  297.     assert( loc == curId++ );   // to be sure that TNSCollection
  298.                                 // continues to work the way
  299.                                 // it does now...
  300. }
  301.  
  302. void _Cdecl pstream::error( StreamableError errorcondition )
  303. {
  304.   setstate( errorcondition );
  305.  
  306.   if(errorcondition == peNotRegistered)
  307.     MessageBox(    
  308.       GetApplicationObject()->MainWindow->HWindow,
  309.       "Type Not Registered", "PStream Error Condition",
  310.           MB_OK | MB_ICONEXCLAMATION);
  311.   else
  312.   {
  313.     assert(errorcondition == peInvalidType);
  314.     MessageBox(    
  315.       GetApplicationObject()->MainWindow->HWindow,
  316.       "Invalid Type Encountered", "PStream Error Condition",
  317.           MB_OK | MB_ICONEXCLAMATION);
  318.   }
  319.  
  320.   clear(ios::badbit);
  321. }
  322.  
  323. void _Cdecl pstream::error( StreamableError errorcondition, RCTStreamable )
  324. {
  325.   error( errorcondition );
  326. }
  327.  
  328. void pstream::initTypes()
  329. {
  330.     if( types == NULL )
  331.     {
  332. #if defined(__DLL__)
  333.     unsigned SavedWinAllocFlag = _WinAllocFlag;
  334.     _WinAllocFlag |= GMEM_DDESHARE;
  335. #endif
  336.  
  337.         types = new TStreamableTypes;
  338.  
  339. #if defined(__DLL__)
  340.     _WinAllocFlag = SavedWinAllocFlag;
  341. #endif
  342.     }
  343. }
  344.  
  345. ipstream& ipstream::seekg( streampos pos )
  346. {
  347.     objs.removeAll();
  348.     objs.insert( new TPWObj( 0, 0 ));
  349.     bp->seekoff( pos, ios::beg );
  350.     return *this;
  351. }
  352.  
  353. ipstream& ipstream::seekg( streamoff off, ios::seek_dir dir )
  354. {
  355.     objs.removeAll();
  356.     objs.insert( new TPWObj( 0, 0 ));
  357.     bp->seekoff( off, dir );
  358.     return *this;
  359. }
  360.  
  361. ushort ipstream::readWord()
  362. {
  363.     ushort temp;
  364.     bp->sgetn( (char *)&temp, sizeof( ushort ) );
  365.     return temp;
  366. }
  367.  
  368. void ipstream::freadBytes( void far *data, size_t sz )
  369. {
  370.     if (sz > 0)
  371.     {
  372.         char *buf = new char[sz+1];
  373.  
  374.         bp->sgetn( (char *)buf, sz );
  375.         _fstrncpy((char far *)data, buf, sz);
  376.  
  377.         delete buf;
  378.     }
  379. }
  380.  
  381. char *ipstream::readString()
  382. {
  383.     uchar len = readByte();
  384.  
  385.     char *buf = new char[len+1];
  386.  
  387.     if( buf != 0 )
  388.     {
  389.         readBytes( buf, len );
  390.         buf[len] = EOS;
  391.     }
  392.     return buf;
  393. }
  394.  
  395. char *ipstream::readString( char *buf, unsigned maxLen )
  396. {
  397.     assert( buf != 0 );
  398.  
  399.     uchar len = readByte();
  400.  
  401.     if( len > maxLen-1 )
  402.         len = maxLen;           // but see buf[len] = EOS;
  403.  
  404.     readBytes( buf, len );
  405.     buf[len] = EOS;
  406.     return buf;
  407. }
  408.  
  409. char far *ipstream::freadString( char far *buf, unsigned maxLen )
  410. {
  411.     assert (buf != 0 );
  412.  
  413.     uchar len = readByte();
  414.  
  415.     if( len > maxLen-1 )
  416.         len = maxLen;           // but see buf[len] = EOS;
  417.  
  418.     freadBytes( buf, len);
  419.     buf[len] = EOS;
  420.     return buf;
  421. }
  422.  
  423. char far *ipstream::freadString()
  424. {
  425.     uchar len = readByte();
  426.  
  427.     char far *buf = (char far *)farmalloc(len+1);
  428.  
  429.     freadBytes(buf, len);
  430.     buf[len] = EOS;
  431.     return buf;
  432. }
  433.  
  434. ipstream& operator >> ( ipstream& ps, signed char &ch )
  435. {
  436.     ch = ps.readByte();
  437.     return ps;
  438. }
  439.  
  440. ipstream& operator >> ( ipstream& ps, unsigned char &ch )
  441. {
  442.     ch = ps.readByte();
  443.     return ps;
  444. }
  445.  
  446. ipstream& operator >> ( ipstream& ps, signed short &sh )
  447. {
  448.     sh = ps.readWord();
  449.     return ps;
  450. }
  451.  
  452. ipstream& operator >> ( ipstream& ps, unsigned short &sh )
  453. {
  454.     sh = ps.readWord();
  455.     return ps;
  456. }
  457.  
  458. ipstream& operator >> ( ipstream& ps, signed int &i )
  459. {
  460.     i = ps.readWord();
  461.     return ps;
  462. }
  463.  
  464. ipstream& operator >> ( ipstream& ps, unsigned int &i )
  465. {
  466.     i = ps.readWord();
  467.     return ps;
  468. }
  469.  
  470. ipstream& operator >> ( ipstream& ps, signed long &l )
  471. {
  472.     ps.readBytes( &l, sizeof(l) );
  473.     return ps;
  474. }
  475.  
  476. ipstream& operator >> ( ipstream& ps, unsigned long &l )
  477. {
  478.     ps.readBytes( &l, sizeof(l) );
  479.     return ps;
  480. }
  481.  
  482. ipstream& operator >> ( ipstream& ps, float &l )
  483. {
  484.     ps.readBytes( &l, sizeof(l) );
  485.     return ps;
  486. }
  487.  
  488. ipstream& operator >> ( ipstream& ps, double &l )
  489. {
  490.     ps.readBytes( &l, sizeof(l) );
  491.     return ps;
  492. }
  493.  
  494. ipstream& operator >> ( ipstream& ps, long double &l )
  495. {
  496.     ps.readBytes( &l, sizeof(l) );
  497.     return ps;
  498. }
  499.  
  500. ipstream& operator >> ( ipstream& ps, TStreamable& t )
  501. {
  502.     const TStreamableClass *pc;
  503.  
  504.     if((pc = ps.readPrefix()) == NULL)
  505.       ps.error(pstream::peInvalidType );
  506.     ps.readData( pc, &t );
  507.     ps.readSuffix();
  508.     return ps;
  509. }
  510.  
  511. ipstream& operator >> ( ipstream& ps, void *&t )
  512. {
  513.     char ch = ps.readByte();
  514.     switch( ch )
  515.         {
  516.         case pstream::ptNull:
  517.             t = 0;
  518.             break;
  519.         case pstream::ptIndexed:
  520.             {
  521.             P_id_type index = ps.readWord();
  522.         t = Pvoid( ps.find( index ) );
  523.             assert( t != 0 );
  524.             break;
  525.             }
  526.         case pstream::ptObject:
  527.             {
  528.             const TStreamableClass *pc;
  529.     
  530.         if((pc = ps.readPrefix()) == NULL)
  531.               ps.error( pstream::peInvalidType );
  532.  
  533.             t = ps.readData( pc, 0 );
  534.             ps.readSuffix();
  535.             break;
  536.             }
  537.         default:
  538.             ps.error( pstream::peInvalidType );
  539.             break;
  540.         }
  541.     return ps;
  542. }
  543.  
  544. const TStreamableClass *ipstream::readPrefix()
  545. {
  546.     char ch = readByte();
  547.  
  548.     assert( ch == '[' );    // don't combine this with the previous line!
  549.                             // We must always do the read, even if we're
  550.                 // not checking assertions
  551.  
  552.     char name[125];
  553.     readString( name, sizeof name );
  554.     return types->lookup( name );
  555. }
  556.  
  557. void *ipstream::readData( const TStreamableClass *c, TStreamable *mem )
  558. {
  559.     if( mem == 0 )
  560.         mem = c->build();
  561.  
  562.     registerObject( (char *)mem - c->delta );   // register the actual address
  563.                                         // of the object, not the address
  564.                                         // of the TStreamable sub-object
  565.     return mem->read( *this );
  566. }
  567.  
  568. void ipstream::readSuffix()
  569. {
  570.     char ch = readByte();
  571.  
  572.     assert( ch == ']' );    // don't combine this with the previous line!
  573.                             // We must always do the write, even if we're
  574.                             // not checking assertions
  575. }
  576.  
  577. opstream& opstream::seekp( streampos pos )
  578. {
  579.     objs.removeAll();
  580.     objs.insert( new TPWObj( 0, 0 ));
  581.     bp->seekoff( pos, ios::beg );
  582.     return *this;
  583. }
  584.  
  585. opstream& opstream::seekp( streamoff pos, ios::seek_dir dir )
  586. {
  587.     objs.removeAll();
  588.     objs.insert( new TPWObj( 0, 0 ));
  589.     bp->seekoff( pos, dir );
  590.     return *this;
  591. }
  592.  
  593. opstream& opstream::flush()
  594. {
  595.     bp->sync();
  596.     return *this;
  597. }
  598.  
  599. void opstream::fwriteBytes( const void far *data, size_t sz )
  600. {
  601.     if (sz > 0)
  602.     {
  603.         char *buf = new char[sz+1];
  604.  
  605.         _fstrcpy(buf, (char far *)data);
  606.         bp->sputn( (char *)buf, sz );
  607.  
  608.         delete buf;
  609.     }
  610. }
  611.  
  612. void opstream::writeString( const char *str )
  613. {
  614.     int len = strlen( str );
  615.     writeByte( (uchar)len );
  616.     writeBytes( str, len );
  617. }
  618.  
  619. void opstream::fwriteString( const char far * str )
  620. {
  621.     int len = _fstrlen( str );
  622.     writeByte( (uchar)len );
  623.     fwriteBytes(str, len);
  624. }
  625.  
  626. opstream& operator << ( opstream& ps, signed char ch )
  627. {
  628.     ps.writeByte( ch );
  629.     return ps;
  630. }
  631.  
  632. opstream& operator << ( opstream& ps, unsigned char ch )
  633. {
  634.     ps.writeByte( ch );
  635.     return ps;
  636. }
  637.  
  638. opstream& operator << ( opstream& ps, signed short sh )
  639. {
  640.     ps.writeWord( sh );
  641.     return ps;
  642. }
  643.  
  644. opstream& operator << ( opstream& ps, unsigned short sh )
  645. {
  646.     ps.writeWord( sh );
  647.     return ps;
  648. }
  649.  
  650. opstream& operator << ( opstream& ps, signed int i )
  651. {
  652.     ps.writeWord( i );
  653.     return ps;
  654. }
  655.  
  656. opstream& operator << ( opstream& ps, unsigned int i )
  657. {
  658.     ps.writeWord( i );
  659.     return ps;
  660. }
  661.  
  662. opstream& operator << ( opstream& ps, signed long l )
  663. {
  664.     ps.writeBytes( &l, sizeof(l) );
  665.     return ps;
  666. }
  667.  
  668. opstream& operator << ( opstream& ps, unsigned long l )
  669. {
  670.     ps.writeBytes( &l, sizeof(l) );
  671.     return ps;
  672. }
  673.  
  674. opstream& operator << ( opstream& ps, float l )
  675. {
  676.     ps.writeBytes( &l, sizeof(l) );
  677.     return ps;
  678. }
  679.  
  680. opstream& operator << ( opstream& ps, double l )
  681. {
  682.     ps.writeBytes( &l, sizeof(l) );
  683.     return ps;
  684. }
  685.  
  686. opstream& operator << ( opstream& ps, long double l )
  687. {
  688.     ps.writeBytes( &l, sizeof(l) );
  689.     return ps;
  690. }
  691.  
  692. opstream& operator << ( opstream& ps, TStreamable& t )
  693. {
  694.     ps.writePrefix( t );
  695.     ps.writeData( t );
  696.     ps.writeSuffix( t );
  697.     return ps;
  698. }
  699.  
  700. opstream& operator << ( opstream& ps, TStreamable *t )
  701. {
  702.     P_id_type index;
  703.     if( t == 0 )
  704.         ps.writeByte( pstream::ptNull );
  705.     else if( (index = ps.find( t )) != 0 )
  706.         {
  707.         ps.writeByte( pstream::ptIndexed );
  708.         ps.writeWord( index );
  709.         }
  710.     else
  711.         {
  712.         ps.writeByte( pstream::ptObject );
  713.         ps << *t;
  714.         }
  715.     return ps;
  716. }
  717.  
  718. void opstream::writePrefix( const TStreamable& t )
  719. {
  720.     writeByte( '[' );
  721.     writeString( t.streamableName() );
  722. }
  723.  
  724. void opstream::writeData( TStreamable& t )
  725. {
  726.     if ( types->lookup( t.streamableName() ) == NULL )
  727.         error( peNotRegistered, t );
  728.     else
  729.     {
  730.         registerObject( &t );
  731.         t.write( *this );
  732.     }
  733. }
  734.  
  735. fpbase::fpbase( const char *name, int omode, int prot )
  736. {
  737.     pstream::init( &buf );
  738.     open( name, omode, prot );
  739. }
  740.  
  741. void fpbase::open( const char *b, int m, int prot )
  742. {
  743.     if( buf.is_open() )
  744.         clear(ios::failbit);        // fail - already open
  745.     else if( buf.open(b, m, prot) )
  746.     {
  747.       clear(ios::goodbit);
  748.     }
  749.     else
  750.         clear(ios::badbit);        // open failed
  751. }
  752.  
  753. void fpbase::attach( int f )
  754. {
  755.     if( buf.is_open() )
  756.         setstate(ios::failbit);
  757.     else if( buf.attach(f) )
  758.         clear(ios::goodbit);
  759.     else
  760.         clear(ios::badbit);
  761. }
  762.  
  763. void fpbase::close()
  764. {
  765.     if( buf.close() )
  766.         clear(ios::goodbit);
  767.     else
  768.         setstate(ios::failbit);
  769. }
  770.  
  771. void fpbase::setbuf(char* b, int len)
  772. {
  773.     if( buf.setbuf(b, len) )
  774.         clear(ios::goodbit);
  775.     else
  776.         setstate(ios::failbit);
  777. }
  778.  
  779. ifpstream::ifpstream( const char* name, int omode, int prot ) :
  780.         fpbase( name, omode | ios::in | ios::binary, prot )
  781. {
  782. }
  783.  
  784. void ifpstream::open( const char _FAR *name, int omode, int prot )
  785. {
  786.     fpbase::open( name, omode | ios::in | ios::binary, prot );
  787. }
  788.  
  789. ofpstream::ofpstream( const char* name, int omode, int prot ) :
  790.         fpbase( name, omode | ios::out | ios::binary, prot )
  791. {
  792. }
  793.  
  794. void ofpstream::open( const char _FAR *name, int omode, int prot )
  795. {
  796.     fpbase::open( name, omode | ios::out | ios::binary, prot );
  797. }
  798.  
  799. fpstream::fpstream( const char* name, int omode, int prot ) :
  800.         fpbase( name, omode | ios::out | ios::binary, prot )
  801. {
  802. }
  803.  
  804. void fpstream::open( const char _FAR *name, int omode, int prot )
  805. {
  806.     fpbase::open( name, omode | ios::in | ios::out | ios::binary, prot );
  807. }
  808.  
  809.  
  810.  
  811.