home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c065 / 2.ddi / CLIB2.ZIP / FSTREAM.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-07  |  10.8 KB  |  510 lines

  1. /*-----------------------------------------------------------------------*
  2.  * filename - fstream.cpp
  3.  * Class filebuf and fstream member functions
  4.  *-----------------------------------------------------------------------*/
  5.  
  6. /*[]------------------------------------------------------------[]*/
  7. /*|                                                              |*/
  8. /*|     Turbo C++ Run Time Library - Version 1.0                 |*/
  9. /*|                                                              |*/
  10. /*|                                                              |*/
  11. /*|     Copyright (c) 1990 by Borland International              |*/
  12. /*|     All Rights Reserved.                                     |*/
  13. /*|                                                              |*/
  14. /*[]------------------------------------------------------------[]*/
  15.  
  16. #include "filesys.h"
  17. #include <fstream.h>
  18.  
  19.  
  20. const int filebuf::openprot = P_default;
  21.  
  22.  
  23. // make a closed filebuf
  24. filebuf::filebuf()
  25. {
  26.     xfd = EOF;
  27.     mode = 0;
  28.     opened = 0;
  29.     last_seek = 0;
  30.     char* p = new char[B_size];
  31.     if( p ) {
  32.     setb(p, p+B_size, 1);    // ~streambuf() will delete buffer
  33.     setp(p+4, p+4);
  34.     setg(p, p+4, p+4);
  35.     }
  36. }
  37.  
  38.  
  39. // make a filebuf attached to an open fd -- assume fd is actually open
  40. filebuf::filebuf(int f)
  41. {
  42.     xfd = f;        // assumed to be valid
  43.     opened = 1;        // unless we can find out otherwise
  44.     mode = 0;        // unless we can find out otherwise
  45.     last_seek = 0;
  46.     char* p = new char[B_size];
  47.     if( p ) {
  48.     setb(p, p+B_size, 1);    // ~streambuf() will delete buffer
  49.     setp(p+4, p+4);
  50.     setg(p, p+4, p+4);
  51.     }
  52. }
  53.  
  54.  
  55. // make a filebuf attached to an open fd -- assume fd is actually open
  56. // use buf as the buffer area
  57. filebuf::filebuf(int f, char* buf, int len)
  58. {
  59.     xfd = f;        // assumed to be valid
  60.     opened = 1;        // unless we can find out otherwise
  61.     mode = 0;        // unless we can find out otherwise
  62.     last_seek = 0;
  63.     setbuf(buf, len);
  64. }
  65.  
  66.  
  67. // We assume that mode==0 means that we attached to an already-open file,
  68. // and should not now close it.  We do flush it in any case.
  69. filebuf::~filebuf()
  70. {
  71.     if( mode )
  72.     close();
  73.     else
  74.     overflow(EOF);
  75. }
  76.  
  77.  
  78. /*
  79.  * Open named file with mode and protection, attach to this filebuf.
  80.  * We make no assumptions about the mode bits and what ::open() wants to
  81.  * see, except we assume that some mapping is possible.
  82.  * "prot" is supplied by user, assumed consistent with operating system.
  83.  * Note checks against OS_err, assumed to be operating system error return.
  84.  */
  85. filebuf* filebuf::open(const char* name, int m, int prot)
  86. {
  87.     if( opened  || ! m )
  88.     return 0;
  89.  
  90.     // set up "how" parameter to system ::open()
  91.     // we let the OS decide whether the combination is legal
  92.     int how;
  93.     if( m & ios::out ) {
  94.     if( m & ios::in ) how = O_rdwr;
  95.     else how = O_wronly;
  96.     if( ! (m & ios::nocreate) ) {
  97.         how |= O_create;
  98.         if( m & ios::noreplace ) how |= O_excl;
  99.     }
  100.     if( m & ios::trunc ) how |= O_trunc;
  101.     }
  102.     else if( m & ios::in )
  103.     how = O_rdonly;
  104.     else
  105.     return 0;    // must specfify in, out, or in/out
  106.     if( m & ios::binary ) how |= O_BINARY;
  107.     else how |= O_TEXT;
  108.     if( m & ios::app ) how |= O_append;
  109.  
  110.     // now try to open
  111.     int f = ::open(name, how, prot);
  112.     if( f == OS_err )
  113.     return 0;
  114.  
  115.     // finish up
  116.     xfd = f;
  117.     opened = 1;
  118.     mode = m;
  119.     last_seek = ::lseek(f, 0L, (m & ios::ate) ? L_end : L_set);
  120.     if( last_seek == long(OS_err) )
  121.     return 0;
  122.  
  123.     char *b = base();        // buffer address
  124.     int pb = b ? ((blen() > 8) ? 4 : 1) : 0;    // putback area size
  125.     setp(b+pb, b+pb);
  126.     setg(b, b+pb, b+pb);
  127.  
  128.     return this;
  129. }
  130.  
  131.  
  132. // flush and close file
  133. filebuf* filebuf::close()
  134. {
  135.     if( xfd == EOF )
  136.     opened = 0;        // consistency check
  137.  
  138.     if( ! opened )
  139.     return 0;        // nothing to do
  140.  
  141.     int ores = 0;        // result of overflow()
  142.     if( out_waiting() )
  143.     ores = (overflow(EOF) == EOF) ? 1 : 0;
  144.     int cres = ::close(xfd);    // result of system ::close()
  145.     
  146.     xfd = EOF;
  147.     opened = 0;
  148.     return (ores | cres) ? 0 : this;
  149. }
  150.  
  151.  
  152. streambuf* filebuf::setbuf(char* b, int len)
  153. {
  154.     if( opened  &&  base() )
  155.     return 0;        // already open with a buffer -- no change
  156.     
  157.     int pb;            // putback area size
  158.     if( b  &&  len > 0 )    // use b as the new buffer
  159.     pb = (len > 8) ? 4 : 1;    // guard against tiny buffers
  160.     else  {            // unbuffered
  161.     len = pb = 0;
  162.     b = 0;
  163.     }
  164.     setb(b, b+len, 0);        // will delete old buffer if needed
  165.     setp(b+pb, b+pb);
  166.     setg(b, b+pb, b+pb);
  167.     return this;
  168. }
  169.  
  170.  
  171. // attach this filebuf to open file descriptor -- assume fd is actually open
  172. filebuf* filebuf::attach(int f)
  173. {
  174.     if( opened )
  175.     return 0;
  176.  
  177.     xfd = f;        // assumed to be valid
  178.     opened = 1;        // unless we can find out otherwise
  179.     mode = 0;        // unless we can find out otherwise
  180.     char *b = base();        // buffer address
  181.     if( ! b ) {
  182.     b = new char[B_size];
  183.     if( b )
  184.         setb(b, b+B_size, 1);    // ~streambuf() will delete buffer
  185.     }
  186.     int pb = b ? ((blen() > 8) ? 4 : 1) : 0;    // putback area size
  187.     setp(b+pb, b+pb);
  188.     setg(b, b+pb, b+pb);
  189.     return this;
  190. }
  191.  
  192.  
  193. // always flush
  194. int filebuf::overflow(int c)
  195. {
  196.     if( ! opened  ||  (mode & (ios::in | ios::out)) == ios::in )
  197.     return EOF;
  198.  
  199.     if( unbuffered()  ||  ! base() ) {
  200.     if( c != EOF ) {
  201.         char b = c;
  202.         if( ::write(xfd, &b, 1) != 1 )
  203.         return EOF;
  204.     }
  205.     }
  206.     else {
  207.     // now we know this is buffered and state is not bad
  208.     int count = out_waiting();
  209.     if( count )
  210.         if( ::write(xfd, pbase(), count) != count )
  211.         return EOF;
  212.  
  213.     // reset get and put areas
  214.     int pb = (blen() > 8) ? 4 : 1;    // putback area size
  215.     char *b = base();
  216.     setp(b+pb, b+blen());
  217.     setg(b, b+pb, b+pb);
  218.     if( c != EOF ) {
  219.         sputc(c);
  220.         gbump(1);        // pptr and gptr must be the same
  221.     }
  222.     }
  223.     return 1;
  224. }
  225.  
  226.  
  227. // return the next available character, reading in a buffer if needed
  228. int filebuf::underflow()
  229. {
  230.     if( ! opened  ||  (mode & (ios::in | ios::out)) == ios::out )
  231.     return EOF;
  232.  
  233.     if( in_avail() )    // no action needed
  234.     return (unsigned char) *gptr();
  235.  
  236.     int c;    // the return value
  237.     int count;    // input character count
  238.  
  239.     if ( ! unbuffered()  &&  base() ) {        // this is buffered
  240.     // flush any output buffer
  241.     count = out_waiting();
  242.     if( count )
  243.         if( ::write(xfd, pbase(), count) != count )
  244.         return EOF;
  245.  
  246.     // find buffer data
  247.     int pb = (blen() > 8) ? 4 : 1;    // putback area size
  248.     char *b = base();
  249.  
  250.     // read in a new buffer
  251.     count = ::read(xfd, b+pb, blen()-pb);
  252.     if( count == OS_err )
  253.         return EOF;
  254.  
  255.     // set up get and put areas
  256.     setg(b, b+pb, b+pb+count);
  257.     setp(b+pb, b+pb);
  258.  
  259.     if( count )
  260.         c = (unsigned char) *gptr();
  261.     }
  262.     else {        // this is not buffered
  263.     count = ::read(xfd, lahead, 1);
  264.     if( count == OS_err) {
  265.         c = EOF;
  266.         setg(0, 0, 0);
  267.     }
  268.     else {
  269.         c = (unsigned char)lahead[0];
  270.         setg(lahead, lahead, lahead+1);
  271.     }
  272.     }
  273.  
  274.     if( ! count )
  275.     c = EOF;    // end of file
  276.  
  277.     return c;
  278. }
  279.  
  280.  
  281. // Seek file to position.
  282. // We take a simple approach, and don't check for small position changes
  283. // within the current buffer.
  284. streampos filebuf::seekoff(streamoff off, seek_dir dir, int /* mode ignored */)
  285. {
  286.     long loff = off;
  287.     int count = out_waiting();
  288.     if( count ) {        // flush the output
  289.     if( ::write(xfd, pbase(), count) != count )
  290.         return EOF;
  291.     }
  292.     else if( dir == ios::cur )
  293.     if( (count = in_avail()) != 0)
  294.         loff -= count;
  295.     int w = (dir == ios::beg) ? L_set : ((dir == ios::cur) ? L_cur : L_end);
  296.     last_seek = ::lseek(xfd, loff, w);
  297.     if( ! unbuffered()  &&  base() ) {        // set up get and put areas
  298.     int pb = (blen() > 8) ? 4 : 1;    // putback area size
  299.     char *b = base();
  300.     setp(b+pb, b+pb);
  301.     setg(b, b+pb, b+pb);
  302.     }
  303.     return (last_seek == long(OS_err)) ? EOF : last_seek;
  304. }
  305.  
  306.  
  307. int filebuf::sync()
  308. {
  309.     if( out_waiting() ) {
  310.     if( overflow(EOF) == EOF )
  311.         return EOF;
  312.     }
  313.     else if( in_avail() ) {
  314.     last_seek = ::lseek(xfd, long(-in_avail()), L_cur);
  315.     setg(eback(), gptr(), gptr());
  316.     setp(gptr(), gptr());
  317.     if( last_seek == long(OS_err) )
  318.         return EOF;
  319.     }
  320.     return 0;
  321. }
  322.  
  323.  
  324. // we have no data on what this is supposed to return
  325. // it is not used in this implementation
  326. // int filebuf::last_op() { }    ???
  327.  
  328.  
  329. fstreambase::fstreambase()
  330.         : buf()
  331. {
  332.     ios::init(&buf);
  333. }
  334.  
  335.  
  336. fstreambase::fstreambase(const char* name, int omode, int prot)
  337.         : buf()
  338. {
  339.     ios::init(&buf);
  340.     open(name, omode, prot);
  341. }
  342.  
  343.  
  344. fstreambase::fstreambase(int f)
  345.         : buf(f)
  346. {
  347.     ios::init(&buf);
  348. }
  349.  
  350.  
  351. fstreambase::fstreambase(int f, char* b, int len)
  352.         : buf(f, b, len)
  353. {
  354.     ios::init(&buf);
  355. }
  356.  
  357.  
  358. fstreambase::~fstreambase()
  359. {
  360. }
  361.  
  362.  
  363. void fstreambase::open(const char* b, int m, int prot)
  364. {
  365.     if( m & ios::app )
  366.     m |= ios::out;    // append implies output
  367.     else if( (m & (ios::out | ios::ate | ios::app | ios::in)) == ios::out )
  368.     m |= ios::trunc; // output implies truncate unless in, app, or ate
  369.  
  370.     if( buf.is_open() )
  371.     clear(ios::failbit);        // fail - already open
  372.     else if( buf.open(b, m, prot) )
  373.     clear(ios::goodbit);        // successful open
  374.     else
  375.     clear(ios::badbit);        // open failed
  376. }
  377.  
  378.  
  379. void fstreambase::attach(int f)
  380. {
  381.     if( buf.is_open() )
  382.     setstate(ios::failbit);
  383.     else if( buf.attach(f) )
  384.     clear(ios::goodbit);
  385.     else
  386.     clear(ios::badbit);
  387. }
  388.  
  389.  
  390. void fstreambase::close()
  391. {
  392.     if( buf.close() )
  393.     clear(ios::goodbit);
  394.     else
  395.     setstate(ios::failbit);
  396. }
  397.  
  398.  
  399. void fstreambase::setbuf(char* b, int len)
  400. {
  401.     if( buf.setbuf(b, len) )
  402.     clear(ios::goodbit);
  403.     else
  404.     setstate(ios::failbit);
  405. }
  406.  
  407.  
  408. // we have no data on what this is supposed to do
  409. // it is not used in this implementation
  410. //    void fstreambase::verify(int) { }    ???
  411.  
  412.  
  413. ifstream::ifstream() :
  414.         fstreambase(),
  415.         istream()
  416. {
  417. }
  418.  
  419.  
  420. ifstream::ifstream(const char* name, int omode, int prot) :
  421.         fstreambase(name, omode, prot),
  422.         istream()
  423. {
  424. }
  425.  
  426.  
  427. ifstream::ifstream(int f) :
  428.         fstreambase(f),
  429.         istream()
  430. {
  431. }
  432.  
  433.  
  434. ifstream::ifstream(int f, char* b, int len) :
  435.         fstreambase(f, b, len),
  436.         istream()
  437. {
  438. }
  439.  
  440.  
  441. ifstream::~ifstream()
  442. {
  443. }
  444.  
  445.  
  446. ofstream::ofstream() :
  447.         fstreambase(),
  448.         ostream()
  449. {
  450. }
  451.  
  452.  
  453. ofstream::ofstream(const char* name, int omode, int prot) :
  454.         fstreambase(name, omode, prot),
  455.         ostream()
  456. {
  457. }
  458.  
  459.  
  460. ofstream::ofstream(int f) :
  461.         fstreambase(f),
  462.         ostream()
  463. {
  464. }
  465.  
  466.  
  467. ofstream::ofstream(int f, char* b, int len) :
  468.         fstreambase(f, b, len),
  469.         ostream()
  470. {
  471. }
  472.  
  473.  
  474. ofstream::~ofstream()
  475. {
  476. }
  477.  
  478.  
  479. fstream::fstream() :
  480.         fstreambase(),
  481.         iostream()
  482. {
  483. }
  484.  
  485.  
  486. fstream::fstream(const char* name, int omode, int prot) :
  487.         fstreambase(name, omode, prot),
  488.         iostream()
  489. {
  490. }
  491.  
  492.  
  493. fstream::fstream(int f) :
  494.         fstreambase(f),
  495.         iostream()
  496. {
  497. }
  498.  
  499.  
  500. fstream::fstream(int f, char* b, int len) :
  501.         fstreambase(f, b, len),
  502.         iostream()
  503. {
  504. }
  505.  
  506.  
  507. fstream::~fstream()
  508. {
  509. }
  510.