iostream.h

00001 /*
00002  *  Copyright (C) 2006  Helmut Grohne
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 #ifndef LIBMUTH_IOSTREAM_H
00020 #define LIBMUTH_IOSTREAM_H
00021 
00022 #include <assert.h>
00023 #include "compiler.h"
00024 #include "iostream_decls.h"
00025 
00026 template<class C, class T>
00027                 BasicScheduledStreambuf<C, T>::BasicScheduledStreambuf(int f,
00028                 BaseScheduler &s, std::ios_base::openmode m,
00029                 std::streamsize insize, std::streamsize outsize) : fd(f),
00030                 sched(s), mode(m) {
00031         // Do not allow opening a stream neither for reading nor for writing.
00032         assert(this->mode & (std::ios_base::in|std::ios_base::out));
00033         this->ibufsize = insize;
00034         if(this->mode & std::ios_base::in)
00035                 this->ibuf = new char_type[insize];
00036         else
00037                 this->ibuf = NULL;
00038         this->setg(this->ibuf, this->ibuf, this->ibuf);
00039         if(this->mode & std::ios_base::out) {
00040                 this->obuf = new char_type[outsize];
00041                 this->setp(this->obuf, this->obuf + outsize);
00042         } else {
00043                 this->obuf = NULL;
00044                 this->setp(NULL, NULL);
00045         }
00046 }
00047 
00048 template<class C, class T>
00049                 BasicScheduledStreambuf<C, T>::~BasicScheduledStreambuf() {
00050         if(this->mode & std::ios_base::in)
00051                 delete[] this->ibuf;
00052         if(this->mode & std::ios_base::out) {
00053                 this->sync();
00054                 delete[] this->obuf;
00055         }
00056 }
00057 
00058 template<class C, class T> typename BasicScheduledStreambuf<C, T>::int_type
00059                 BasicScheduledStreambuf<C, T>::underflow() {
00060         assert(this->mode & std::ios_base::in);
00061         if(this->gptr() < this->egptr())
00062                 return traits_type::to_int_type(*this->gptr());
00063         assert(this->ibufsize > 0);
00064         const int r(this->sched.read(this->fd, this->ibuf,
00065                         this->ibufsize * sizeof(char_type)));
00066         if(unlikely(r <= 0))
00067                 return traits_type::eof();
00068         /* FIXME: this will result in problems showed by assertions: */
00069         assert(r % sizeof(char_type) == 0);
00070         this->setg(this->ibuf, this->ibuf, static_cast<char_type*>(
00071                         static_cast<char*>(this->ibuf) + r));
00072         return traits_type::to_int_type(*this->gptr());
00073 }
00074 
00075 template<class C, class T> typename BasicScheduledStreambuf<C, T>::int_type
00076                 BasicScheduledStreambuf<C, T>::pbackfail(int_type ch) {
00077         assert(this->mode & std::ios_base::in);
00078         if(likely(this->gptr() != this->eback())) {
00079                 this->gbump(-1);
00080                 if(!traits_type::eq_int_type(ch, traits_type::eof()))
00081                         *this->gptr() = traits_type::not_eof(ch);
00082                 return traits_type::not_eof(ch);
00083         }
00084         return traits_type::eof();
00085 }
00086 
00087 template<class C, class T> int BasicScheduledStreambuf<C, T>::sync() {
00088         assert(this->mode & std::ios_base::out);
00089         const int bump(static_cast<int>(this->pptr() - this->pbase()));
00090         char *data(static_cast<char*>(this->pbase()));
00091         size_t n(static_cast<size_t>(static_cast<char*>(this->pptr()) - data));
00092         if(n == 0)
00093                 return 0;
00094         int r(this->sched.write(this->fd, data, n));
00095         if(unlikely(r <= 0))
00096                 return -1;
00097         assert(n >= (size_t)r);
00098         while((size_t)r != n) {
00099                 r = this->sched.write(this->fd, data, n);
00100                 if(unlikely(r <= 0))
00101                         return -1;
00102                 assert(n >= (size_t)r);
00103                 data += r;
00104                 n -= r;
00105         }
00106         this->pbump(-bump);
00107         return 0;
00108 }
00109 
00110 template<class C, class T> typename BasicScheduledStreambuf<C, T>::int_type
00111                 BasicScheduledStreambuf<C, T>::overflow(int_type ch) {
00112         assert(this->mode & std::ios_base::out);
00113         /* FIXME: maybe not really sync but write parts of the buffer. */
00114         if(unlikely(this->sync() < 0))
00115                 return traits_type::eof();
00116         if(traits_type::eq_int_type(ch, traits_type::eof()))
00117                 /* FIXME: find out why we return not_eof(eof()). */
00118                 return traits_type::not_eof(ch);
00119         return this->sputc(traits_type::to_char_type(ch));
00120 }
00121 
00122 #if 0
00123 template<class C, class T> std::streamsize
00124                 BasicScheduledStreambuf<C, T>::xsputn(const char_type *str,
00125                 std::streamsize n) {
00126         assert(this->mode & std::ios_base::out);
00127         if(this->sync() < 0)
00128                 return 0;
00129         const int r(this->sched.write(this->fd, str, n * sizeof(char_type)));
00130         if(r < 0)
00131                 return 0;
00132         return r / sizeof(char_type);
00133 }
00134 #endif
00135 
00136 template<class C, class T> inline BasicScheduledStreambuf<C, T>::operator int()
00137                 const {
00138         return this->fd;
00139 }
00140 
00141 template<class C, class T> BasicScheduledIStream<C, T>::BasicScheduledIStream(
00142                 int f, BaseScheduler &s, std::streamsize size)
00143                 : std::basic_istream<C, T>(NULL),
00144                 streambuf(f, s, std::ios_base::in, size) {
00145         this->init(&this->streambuf);
00146 }
00147 
00148 template<class C, class T> inline BasicScheduledIStream<C, T>::operator int()
00149                 const {
00150         return (int)this->streambuf;
00151 }
00152 
00153 template<class C, class T> BasicScheduledOStream<C, T>::BasicScheduledOStream(
00154                 int f, BaseScheduler &s, std::streamsize size)
00155                 : std::basic_ostream<C, T>(NULL),
00156                 streambuf(f, s, std::ios_base::out, 0, size) {
00157         this->init(&this->streambuf);
00158 }
00159 
00160 template<class C, class T> inline BasicScheduledOStream<C, T>::operator int()
00161                 const {
00162         return (int)this->streambuf;
00163 }
00164 
00165 template<class C, class T> BasicScheduledIOStream<C, T>::BasicScheduledIOStream(
00166                 int f, BaseScheduler &s, std::streamsize insize,
00167                 std::streamsize outsize) : std::basic_iostream<C, T>(NULL),
00168                 streambuf(f, s, std::ios_base::in | std::ios_base::out, insize,
00169                 outsize) {
00170         this->init(&this->streambuf);
00171 }
00172 
00173 template<class C, class T> inline BasicScheduledIOStream<C, T>::operator int()
00174                 const {
00175         return (int)this->streambuf;
00176 }
00177 
00178 #endif

Generated on Sat Feb 7 01:26:50 2009 by  doxygen 1.5.1