File indexing completed on 2024-05-19 15:27:49

0001 /* The following code declares classes to read from and write to
0002  * file descriptore or file handles.
0003  *
0004  * See
0005  *      http://www.josuttis.com/cppcode
0006  * for details and the latest version.
0007  *
0008  * - open:
0009  *      - integrating BUFSIZ on some systems?
0010  *      - optimized reading of multiple characters
0011  *      - stream for reading AND writing
0012  *      - i18n
0013  *
0014  * (C) Copyright Nicolai M. Josuttis 2001.
0015  * Permission to copy, use, modify, sell and distribute this software
0016  * is granted provided this copyright notice appears in all copies.
0017  * This software is provided "as is" without express or implied
0018  * warranty, and with no claim as to its suitability for any purpose.
0019  *
0020  * Version: Jul 28, 2002
0021  * History:
0022  *  Jul 28, 2002: bugfix memcpy() => memmove()
0023  *                fdinbuf::underflow(): cast for return statements
0024  *  Aug 05, 2001: first public version
0025  */
0026 #ifndef BOOST_FDSTREAM_HPP
0027 #define BOOST_FDSTREAM_HPP
0028 
0029 #include <istream>
0030 #include <ostream>
0031 #include <streambuf>
0032 // for EOF:
0033 #include <cstdio>
0034 // for memmove():
0035 #include <cstring>
0036 
0037 
0038 // low-level read and write functions
0039 #ifdef _MSC_VER
0040 # include <io.h>
0041 #else
0042 # include <unistd.h>
0043 //extern "C" {
0044 //    int write (int fd, const char* buf, int num);
0045 //    int read (int fd, char* buf, int num);
0046 //}
0047 #endif
0048 
0049 
0050 // BEGIN namespace BOOST
0051 namespace boost {
0052 
0053 
0054 /************************************************************
0055  * fdostream
0056  * - a stream that writes on a file descriptor
0057  ************************************************************/
0058 
0059 
0060 class fdoutbuf : public std::streambuf {
0061   protected:
0062     int fd;    // file descriptor
0063   public:
0064     // constructor
0065     fdoutbuf (int _fd) : fd(_fd) {
0066     }
0067   protected:
0068     // write one character
0069     virtual int_type overflow (int_type c) {
0070         if (c != EOF) {
0071             char z = c;
0072             if (write (fd, &z, 1) != 1) {
0073                 return EOF;
0074             }
0075         }
0076         return c;
0077     }
0078     // write multiple characters
0079     virtual
0080     std::streamsize xsputn (const char* s,
0081                             std::streamsize num) {
0082         return write(fd,s,num);
0083     }
0084 };
0085 
0086 class fdostream : public std::ostream {
0087   protected:
0088     fdoutbuf buf;
0089   public:
0090     fdostream (int fd) : std::ostream(0), buf(fd) {
0091         rdbuf(&buf);
0092     }
0093 };
0094 
0095 
0096 /************************************************************
0097  * fdistream
0098  * - a stream that reads on a file descriptor
0099  ************************************************************/
0100 
0101 class fdinbuf : public std::streambuf {
0102   protected:
0103     int fd;    // file descriptor
0104   protected:
0105     /* data buffer:
0106      * - at most, pbSize characters in putback area plus
0107      * - at most, bufSize characters in ordinary read buffer
0108      */
0109     static const int pbSize = 4;        // size of putback area
0110     static const int bufSize = 1024;    // size of the data buffer
0111     char buffer[bufSize+pbSize];        // data buffer
0112 
0113   public:
0114     /* constructor
0115      * - initialize file descriptor
0116      * - initialize empty data buffer
0117      * - no putback area
0118      * => force underflow()
0119      */
0120     fdinbuf (int _fd) : fd(_fd) {
0121         setg (buffer+pbSize,     // beginning of putback area
0122               buffer+pbSize,     // read position
0123               buffer+pbSize);    // end position
0124     }
0125 
0126   protected:
0127     // insert new characters into the buffer
0128     virtual int_type underflow () {
0129 #ifndef _MSC_VER
0130         using std::memmove;
0131 #endif
0132 
0133         // is read position before end of buffer?
0134         if (gptr() < egptr()) {
0135             return traits_type::to_int_type(*gptr());
0136         }
0137 
0138         /* process size of putback area
0139          * - use number of characters read
0140          * - but at most size of putback area
0141          */
0142         int numPutback;
0143         numPutback = gptr() - eback();
0144         if (numPutback > pbSize) {
0145             numPutback = pbSize;
0146         }
0147 
0148         /* copy up to pbSize characters previously read into
0149          * the putback area
0150          */
0151         memmove (buffer+(pbSize-numPutback), gptr()-numPutback,
0152                 numPutback);
0153 
0154         // read at most bufSize new characters
0155         int num;
0156         num = read (fd, buffer+pbSize, bufSize);
0157         if (num <= 0) {
0158             // ERROR or EOF
0159             return EOF;
0160         }
0161 
0162         // reset buffer pointers
0163         setg (buffer+(pbSize-numPutback),   // beginning of putback area
0164               buffer+pbSize,                // read position
0165               buffer+pbSize+num);           // end of buffer
0166 
0167         // return next character
0168         return traits_type::to_int_type(*gptr());
0169     }
0170 };
0171 
0172 class fdistream : public std::istream {
0173   protected:
0174     fdinbuf buf;
0175   public:
0176     fdistream (int fd) : std::istream(0), buf(fd) {
0177         rdbuf(&buf);
0178     }
0179 };
0180 
0181 
0182 } // END namespace boost
0183 
0184 #endif /*BOOST_FDSTREAM_HPP*/