lib/fdbuf/fdobuf.cc
changeset 0 6f7a81934006
equal deleted inserted replaced
-1:000000000000 0:6f7a81934006
       
     1 // Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
       
     2 //
       
     3 // This program is free software; you can redistribute it and/or modify
       
     4 // it under the terms of the GNU General Public License as published by
       
     5 // the Free Software Foundation; either version 2 of the License, or
       
     6 // (at your option) any later version.
       
     7 //
       
     8 // This program is distributed in the hope that it will be useful,
       
     9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    11 // GNU General Public License for more details.
       
    12 //
       
    13 // You should have received a copy of the GNU General Public License
       
    14 // along with this program; if not, write to the Free Software
       
    15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    16 
       
    17 #include "fdbuf.h"
       
    18 #include <errno.h>
       
    19 #include <fcntl.h>
       
    20 #include <string.h>
       
    21 #include <unistd.h>
       
    22 
       
    23 ///////////////////////////////////////////////////////////////////////////////
       
    24 // Globals
       
    25 ///////////////////////////////////////////////////////////////////////////////
       
    26 fdobuf fout(1);
       
    27 fdobuf ferr(2);
       
    28 
       
    29 ///////////////////////////////////////////////////////////////////////////////
       
    30 // Class fdobuf
       
    31 ///////////////////////////////////////////////////////////////////////////////
       
    32 fdobuf::fdobuf(int fdesc, bool dc, unsigned bufsz)
       
    33   : fdbuf(fdesc, dc, bufsz),
       
    34     bufpos(0)
       
    35 {
       
    36 }
       
    37 
       
    38 fdobuf::fdobuf(const char* filename, int f, int mode, unsigned bufsz)
       
    39   : fdbuf(open(filename, O_WRONLY | f, mode), true, bufsz),
       
    40     bufpos(0)
       
    41 {
       
    42   if(fd == -1) {
       
    43     flags = flag_error;
       
    44     errnum = errno;
       
    45   }
       
    46 }
       
    47 
       
    48 fdobuf::~fdobuf()
       
    49 {
       
    50   flush();
       
    51 }
       
    52 
       
    53 bool fdobuf::close()
       
    54 {
       
    55   if(!flush())
       
    56     return false;
       
    57   lock();
       
    58   bool r = fdbuf::close();
       
    59   unlock();
       
    60   return r;
       
    61 }
       
    62 
       
    63 bool fdobuf::operator!() const
       
    64 {
       
    65   return error() || closed();
       
    66 }
       
    67 
       
    68 bool fdobuf::nflush(bool withsync)
       
    69 {
       
    70   if(flags)
       
    71     return false;
       
    72   while(bufstart < buflength) {
       
    73     ssize_t written = ::write(fd, buf+bufstart, buflength-bufstart);
       
    74     if(written == -1) {
       
    75       flags |= flag_error;
       
    76       errnum = errno;
       
    77       return false;
       
    78     }
       
    79     else {
       
    80       bufstart += written;
       
    81       offset += written;
       
    82     }
       
    83   }
       
    84   buflength = 0;
       
    85   bufstart = 0;
       
    86   bufpos = 0;
       
    87   if(withsync && (fsync(fd) == -1)) {
       
    88     flags |= flag_error;
       
    89     errnum = errno;
       
    90     return false;
       
    91   }
       
    92   return true;
       
    93 }
       
    94 
       
    95 bool fdobuf::flush()
       
    96 {
       
    97   lock();
       
    98   bool r = nflush(false);
       
    99   unlock();
       
   100   return r;
       
   101 }
       
   102 
       
   103 bool fdobuf::sync()
       
   104 {
       
   105   lock();
       
   106   bool r = nflush(true);
       
   107   unlock();
       
   108   return r;
       
   109 }
       
   110 
       
   111 bool fdobuf::write(char ch)
       
   112 {
       
   113   if(flags)
       
   114     return false;
       
   115 
       
   116   lock();
       
   117   count = 0;
       
   118   buf[bufpos++] = ch;
       
   119   //if(buflength >= bufsize && !nflush(false)) {
       
   120   //  unlock();
       
   121   //  return false;
       
   122   //}
       
   123   if(bufpos >= buflength)
       
   124     buflength = bufpos;
       
   125   if(buflength >= bufsize && !nflush(false)) {
       
   126     unlock();
       
   127     return false;
       
   128   }
       
   129   count = 1;
       
   130   unlock();
       
   131   return true;
       
   132 }
       
   133 
       
   134 bool fdobuf::write_large(const char* data, unsigned datalen)
       
   135 {
       
   136   if(flags)
       
   137     return false;
       
   138 
       
   139   lock();
       
   140   count = 0;
       
   141 
       
   142   if(!nflush(false)) {
       
   143     unlock();
       
   144     return false;
       
   145   }
       
   146 
       
   147   while(datalen > 0) {
       
   148     ssize_t written = ::write(fd, data, datalen);
       
   149     if(written == -1) {
       
   150       flags |= flag_error;
       
   151       errnum = errno;
       
   152       unlock();
       
   153       return false;
       
   154     }
       
   155     datalen -= written;
       
   156     data += written;
       
   157     offset += written;
       
   158     count += written;
       
   159   }
       
   160   unlock();
       
   161   return true;
       
   162 }
       
   163 
       
   164 bool fdobuf::write(const char* data, unsigned datalen)
       
   165 {
       
   166   if(datalen >= bufsize)
       
   167     return write_large(data, datalen);
       
   168   
       
   169   if(flags)
       
   170     return false;
       
   171 
       
   172   lock();
       
   173   const char* ptr = data;
       
   174   count = 0;
       
   175   // Amount is the number of bytes available in the buffer
       
   176   unsigned amount = bufsize-bufpos;
       
   177   while(datalen >= amount) {
       
   178     // If we get here, this copy will completely fill the buffer,
       
   179     // requiring a flush
       
   180     memcpy(buf+bufpos, ptr, amount);
       
   181     bufpos = bufsize;
       
   182     buflength = bufsize;
       
   183     datalen -= amount;
       
   184     ptr += amount;
       
   185     if(!nflush(false)) {
       
   186       unlock();
       
   187       return false;
       
   188     }
       
   189     count += amount;
       
   190     amount = bufsize-bufpos;
       
   191   }
       
   192   // At this point, the remaining data will fit into the buffer
       
   193   memcpy(buf+bufpos, ptr, datalen);
       
   194   count += datalen;
       
   195   bufpos += datalen;
       
   196   if(bufpos > buflength) buflength = bufpos;
       
   197   unlock();
       
   198   return true;
       
   199 }
       
   200 
       
   201 ///////////////////////////////////////////////////////////////////////////////
       
   202 // Manipulators
       
   203 ///////////////////////////////////////////////////////////////////////////////
       
   204 fdobuf& endl(fdobuf& fd)
       
   205 {
       
   206   fd.write("\n", 1);
       
   207   fd.flush();
       
   208   return fd;
       
   209 }