Logo Search packages:      
Sourcecode: u++ version File versions

uFilebuf.cc

//                              -*- Mode: C++ -*- 
// 
// uC++ Version 5.0.1, Copyright (C) Peter A. Buhr 1994
// 
// uFilebuf.cc -- nonblocking stream buffer
// 
// Author           : Peter Buhr
// Created On       : Tue Mar 29 16:46:30 1994
// Last Modified By : Peter A. Buhr
// Last Modified On : Wed Aug 11 14:11:50 2004
// Update Count     : 55
//
// This  library is free  software; you  can redistribute  it and/or  modify it
// under the terms of the GNU Lesser General Public License as published by the
// Free Software  Foundation; either  version 2.1 of  the License, or  (at your
// option) any later version.
// 
// This library is distributed in the  hope that it will be useful, but WITHOUT
// ANY  WARRANTY;  without even  the  implied  warranty  of MERCHANTABILITY  or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
// for more details.
// 
// You should  have received a  copy of the  GNU Lesser General  Public License
// along  with this library.
// 


#define __U_KERNEL__
#include <uC++.h>
#include <uFilebuf.h>
//#include <uDebug.h>


// I would like to make it known that I have no idea what half this code does.
// I think this stream stuff is someone's idea of a bad joke.


int uFilebuf::IosToUnixMode( std::ios_base::openmode mode ) {
    int m;

    if ( (mode & (std::ios_base::in | std::ios_base::out)) == (std::ios_base::in | std::ios_base::out) ) {
      m = O_RDWR;
    } else if ( mode & (std::ios_base::out | std::ios_base::app) ) {
      m = O_WRONLY;
    } else if ( mode & (int)std::ios_base::in ) {
      m = O_RDONLY;
    } else {
      uAbort( "IosToUnixMode( %d ) : invalid I/O mode", mode );
    } // if

    if ( (mode & std::ios_base::trunc) || mode == std::ios_base::out ) {
      m |= O_TRUNC;
    } // if
    if ( mode & std::ios_base::app ) {
      m |= O_APPEND;
    } // if
    if ( mode != std::ios_base::in ) {
      m |= O_CREAT;
    } // if

    return m;
} // uFilebuf::IosToUnixMode

int uFilebuf::CharToUnixMode( const char *mode ) {
    int m;

    if ( strcmp( mode, "r" ) == 0 ) {                 // convert
      m = O_RDONLY;
    } else if ( strcmp( mode, "w" ) == 0 ) {
      m = O_WRONLY | O_CREAT;
    } else if ( strcmp( mode, "a" ) == 0 ) {
      m = O_WRONLY | O_APPEND | O_CREAT;
    } else if ( strcmp( mode, "r+" ) == 0 ) {
      m = O_RDWR;
    } else if ( strcmp( mode, "w+" ) == 0 ) {
      m = O_RDWR | O_TRUNC | O_CREAT;
    } else if ( strcmp( mode, "a+" ) == 0 ) {
      m = O_RDWR | O_APPEND | O_CREAT;
    } else {
      uAbort( "CharToUnixMode( %s ) : invalid I/O mode (r,w,r+,a+,w+)", mode );
    } // if

    return m;
} // uFilebuf::CharToUnixMode


uFilebuf::uFilebuf( std::ios_base::openmode mode ) {
    _M_mode = mode;
    ufile = 0;
    ufileacc = 0;
    setbuf( buffer, __U_BUFFER_SIZE__ );        // reset all buffer pointers
    setp( buffer, buffer + __U_BUFFER_SIZE__ );       // reset output buffer pointers
    setg( buffer, buffer + __U_BUFFER_SIZE__, buffer + __U_BUFFER_SIZE__ ); // reset input buffer pointers
    endOfFile = 0;
} // uFilebuf::uFilebuf


uFilebuf::uFilebuf( int fd, std::ios_base::openmode mode, int bufsize ) {
    _M_mode = mode;
    ufile = new uFile( "/dev/tty" );
    ufileacc = new uFileAccess( fd, *ufile );
    setbuf( buffer, bufsize );                        // reset all buffer pointers
    setp( buffer, buffer + bufsize );                 // reset output buffer pointers
    setg( buffer, buffer + bufsize, buffer + bufsize );     // reset input buffer pointers
    endOfFile = 0;
} // uFilebuf::uFilebuf


uFilebuf::uFilebuf( int fd, std::ios_base::openmode mode, char *buf, int bufsize ) {
    _M_mode = mode;
    ufile = new uFile( "unknown" );
    ufileacc = new uFileAccess( fd, *ufile );
    setbuf( buf, bufsize );                     // reset all buffer pointers
    setp( buffer, buffer + bufsize );                 // reset output buffer pointers
    setg( buffer, buffer + bufsize, buffer + bufsize );     // reset input buffer pointers
    endOfFile = 0;
} // uFilebuf::uFilebuf


uFilebuf::~uFilebuf() {
    close();
} // uFilebuf::~uFilebuf


bool uFilebuf::is_open() const {
    return ufileacc != 0;
} // uFilebuf::is_open


uFilebuf *uFilebuf::open( const char *filename, std::ios_base::openmode mode ) {
    if ( is_open() ) close();
    ufile = new uFile( filename );
    ufileacc = new uFileAccess( *ufile, IosToUnixMode( mode ) );
    if ( mode & std::ios_base::ate ) {                // seek to the end of the file
      seekoff( 0, std::ios_base::end );
    } // if
    return this;
} // uFilebuf::open


uFilebuf *uFilebuf::close() {
    if ( is_open() ) {
      delete ufileacc;
      ufileacc = 0;
    } // if
    if ( ufile != 0 ) {
      delete ufile;
      ufile = 0;
    } // if
    return 0;
} // uFilebuf::close


int uFilebuf::fd() {
    return is_open() ? ufileacc->access.fd : EOF;
} // uFilebuf::fd


int uFilebuf::overflow( int c ) {
  if ( ! is_open() ) return EOF;                // file open ?

    int len, wbytes;
    char *pos;

    for ( pos = pbase(), len = pptr() - pbase(); len != 0; pos += wbytes, len -= wbytes ) {
      wbytes = ufileacc->write( pos, len );
    } // for

#ifdef __U_DEBUG_H__
    uDebugPrt( "overflow( %c ), eback:0x%p, gptr:0x%p, egptr:0x%p, pbase:0x%p, pptr:0x%p, epptr:0x%p, len:%d\n", c, eback(), gptr(), egptr(), pbase(), pptr(), epptr(), pptr() - pbase() );
#endif // __U_DEBUG_H__

    setp( pbase(), epptr() );                   // reset output buffer pointers
    if ( c != EOF ) {                           // character passed ?
      sputc( c );                         // insert into empty buffer
    } // if

    return 0;
} // uFilebuf::overflow


int uFilebuf::underflow() {
  if ( ! is_open() ) return EOF;                // file open ?

    int rbytes;
    int c;

    // There are times (getline) when underflow is called after EOF has already
    // been returned. To prevent having to enter multiple C-ds from stdin,
    // additional reads must not be done.

    if ( ! endOfFile ) {
      rbytes = ufileacc->read( eback(), _M_buf_size );
    } else {
      rbytes = 0;
    } // if
    setg( eback(), eback(), eback() + rbytes );       // reset input buffer pointers
    if ( rbytes == 0 ) {                        // zero bytes read ?
      endOfFile = 1;
      c = EOF;
    } else {
      c = sgetc();                              // get the next character from the buffer
    } // if

#ifdef __U_DEBUG_H__
    uDebugPrt( "c:%c = underflow(), rbytes:%d, eback:0x%p, gptr:0x%p, egptr:0x%p, pbase:0x%p, pptr:0x%p, epptr:0x%p, _M_buf_size:%d\n", c, rbytes, eback(), gptr(), egptr(), pbase(), pptr(), epptr(), _M_buf_size );
#endif // __U_DEBUG_H__

    return c;
} // uFilebuf::underflow


int uFilebuf::uflow() {
    int c = underflow();
    if ( c != EOF ) gbump( 1 );
    return c;
} // uFilebuf::uflow


std::streamsize uFilebuf::xsputn(const char* __s, std::streamsize __n) {
    return std::streambuf::xsputn(__s, __n);
}


int uFilebuf::sync() {
    if ( pptr() > pbase() ) {
      overflow();                         // empty output buffer
    } // if
    return 0;
} // uFilebuf::sync


std::streambuf::pos_type uFilebuf::seekoff( off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which ) {
  if ( ! is_open() ) return EOF;                // file open ?
    std::streambuf::pos_type pos;

    sync();                               // empty output buffer
    if ( dir == std::ios_base::beg ) {
      ufileacc->lseek( 0, SEEK_SET );                 // seek to origin
      pos = ufileacc->lseek( off, SEEK_SET );
    } else if ( dir == std::ios_base::cur ) {
      pos = ufileacc->lseek( off, SEEK_CUR );
    } else {
      pos = ufileacc->lseek( off, SEEK_END );
    } // if

#if __GNUC__ > 3 || __GNUC_MINOR__ > 3
    _M_set_buffer(-1);                          // reset all buffer pointers
#else
    // TEMPORARY: protected interface change in gcc 3.4
    _M_set_indeterminate();
#endif
    return pos;
} // uFilebuf::seekoff


std::streambuf::pos_type uFilebuf::seekpos( std::streambuf::pos_type sp, std::ios_base::openmode which ) {
    return seekoff( sp, std::ios_base::beg, which );
} // uFilebuf::seekpos


// Local Variables: //
// compile-command: "gmake install" //
// End: //

Generated by  Doxygen 1.6.0   Back to index