sprint 1-alpha
sprint/io/bufferize.h
Go to the documentation of this file.
00001 /******************************************************************************
00002 *   SPRINT::bufferize
00003 *
00004 *   Copyright (C) 2005-2011  Paolo Medici <www.pmx.it>
00005 *
00006 *  This library is free software; you can redistribute it and/or
00007 *  modify it under the terms of the GNU Lesser General Public
00008 *  License as published by the Free Software Foundation; either
00009 *  version 2.1 of the License, or (at your option) any later version.
00010 *
00011 *  This library is distributed in the hope that it will be useful,
00012 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 *  Lesser General Public License for more details.
00015 *
00016 *  You should have received a copy of the GNU Lesser General Public
00017 *  License along with this library; if not, write to the Free Software
00018 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00019 *
00020 *******************************************************************************/
00021 
00025 #ifndef _BUFFERIZE_H
00026 #define _BUFFERIZE_H
00027 
00028 namespace sprint {
00029 
00031 class data_buffer {
00032 
00034         struct _Rep {
00035       int m_size;       
00036       int m_capacity;   
00037       int m_pos;                
00038     };
00039 
00041     inline _Rep *_M_rep() const
00042       { 
00043                         return reinterpret_cast<_Rep*>(m_data); 
00044           }
00045 
00047         unsigned char *m_data;
00048 
00049 private:
00051         data_buffer(const data_buffer & src) { }
00052 
00053 public:
00054         data_buffer(int capacity) { 
00055                 m_data = new unsigned char[ sizeof(_Rep) + capacity ];  
00056                 _M_rep()->m_capacity = capacity;
00057                 _M_rep()->m_pos = 0;
00058                 _M_rep()->m_size = 0;
00059                 }
00060 
00061         ~data_buffer() { delete [] m_data; }
00062         
00064         inline int capacity() const { return _M_rep()->m_capacity; }
00065 
00067         inline int size() const { return _M_rep()->m_size; }
00069         inline void size(int s) { _M_rep()->m_size = s; }
00070 
00072         inline int pos() const { return _M_rep()->m_pos; }
00073         inline void pos(int p) { _M_rep()->m_pos = p; }
00074         
00076         inline void skip(int s) { _M_rep()->m_pos += s; }
00078         inline int remain() const { return _M_rep()->m_size - _M_rep()->m_pos; }
00079 
00081         inline unsigned char *data() const { return m_data + sizeof(_Rep); }
00083         inline unsigned char *cur() const { return m_data + sizeof(_Rep) + _M_rep()->m_pos; }
00084 
00086         inline unsigned char peek()     {
00087                 return m_data[sizeof(_Rep) + _M_rep()->m_pos];
00088         }
00089 
00091         inline unsigned char get()      {
00092                 return m_data[sizeof(_Rep) + _M_rep()->m_pos++];
00093         }
00095         inline void put(unsigned char c)        {
00096                 m_data[sizeof(_Rep) + _M_rep()->m_pos] = c;
00097                 _M_rep()->m_pos++;
00098         }
00099 
00101     inline bool full() const { return _M_rep()->m_pos == _M_rep()->m_capacity; }
00102     
00104         inline bool avail() const { return _M_rep()->m_pos<_M_rep()->m_size; }
00105         
00107         int write(const unsigned char *src, int len)
00108         {
00109         int r = _M_rep()->m_capacity - _M_rep()->m_pos;
00110         if(r>0)
00111         {
00112                         int copiable = std::min(len, r);
00113                         ::memcpy(cur(), src, copiable);
00114                         _M_rep()->m_pos += copiable;
00115                         _M_rep()->m_size = _M_rep()->m_pos; // volendo si potrebbe scrivere ovunque nel buffer
00116                         return copiable;
00117         }
00118         else
00119         return 0;
00120     }
00121     
00123     int put(char c) 
00124     {
00125         int r = _M_rep()->m_capacity - _M_rep()->m_pos;
00126         if(r>0)
00127         {
00128             *cur() = c;
00129 
00130                         _M_rep()->m_pos ++;
00131                         _M_rep()->m_size = _M_rep()->m_pos; // volendo si potrebbe scrivere ovunque nel buffer
00132                         return 1;
00133         }
00134         else
00135         return 0;
00136     }
00137 
00141         int read(unsigned char *dst, int len)
00142         {
00143                 int r = remain();
00144                 if( r>0 )
00145                         {
00146                         int copiable = std::min(len, r);
00147                         ::memcpy(dst, cur(), copiable);
00148                         skip(copiable);
00149                         return copiable;
00150                         }
00151                 else
00152                         return 0;
00153         }
00154 
00155 
00156 
00157 };
00158 
00169 template<class T>
00170 class read_buffer : public T {
00175         data_buffer m_buf;
00176         
00178         bool m_valid;
00179 
00180 private:
00181         
00185         bool underrun()
00186         {
00187         int len = T::read( (char *) m_buf.data(), m_buf.capacity() );
00188         if(len <=0 )
00189          {
00190          m_valid = false;
00191          return false;
00192          }
00193          
00194                 m_buf.size (len);
00195                 m_buf.pos(0);
00196                 return true;
00197         }
00198 
00202         int direct_read(unsigned char *dst, int len)
00203         {
00204                 int readed = 0;
00205                 while(len>0)
00206                         {
00207                                 int read = T::read((char *) dst, len);
00208                                 if(read == -1)
00209                                         return -1;
00210                                 len -= read;
00211                                 dst += read;
00212                                 readed += read;
00213                         }
00214                 return readed;
00215         }
00216 
00218     inline bool check_underrun()
00219     {
00220                 while(!m_buf.avail())
00221                         {
00222                         if(!valid())
00223                                         return false;
00224                         underrun();
00225                         }
00226     return true;
00227     }
00228 public:
00230     template<class P>
00231         read_buffer(const P & p, int capacity) : T(p), m_buf(capacity), m_valid(true) { }
00233         read_buffer(int capacity) : m_buf(capacity), m_valid(true) { }
00234 
00236         inline bool valid() const { return m_valid && m_buf.size()!=-1; }
00237         
00239         int remain() const { return m_buf.remain(); }
00240         
00243         int readsome(unsigned char *dst, int len)
00244         {
00245                 return check_underrun() ? m_buf.read(dst,len) : -1;
00246         }
00247 
00249         int read(unsigned char *dst, int len)
00250         {
00251                 int r;
00252                 int p = 0;
00253                 if(!valid())
00254                                 return -1;
00255                 // leggo intanto dal buffer quanto è presente
00256                 r = m_buf.read(dst, len);
00257                 p += r;
00258                 
00259                 if(p<len)
00260                         {
00261                         // se sono qua read ha finito il buffer
00262 
00263                         // il dato rimanente da leggere è più piccolo dell'eventuale capacità?
00264                         if((p-len)<m_buf.capacity())
00265                                 {
00266                                 // underrun non garantisce però che il dato caricato sia esattamente size
00267                                 while(p<len)
00268                                         {
00269                                         if(!underrun())
00270                                                        return p;
00271                                                        
00272                                         p += m_buf.read(dst+p,len-p);
00273                                         }
00274                                 }
00275                         else
00276                                 {
00277                                 // uso direttamente il buffer fornito dall'utente. 
00278                                 //  E' comunque più grande del buffer interno e risparmio un memcpy
00279                                 p += direct_read(dst+p, len-p);
00280                                 }
00281                         }
00282                 return p;
00283         }
00284         
00285         // read and disband data
00286         inline int skip(int n)
00287     {
00288            // TODO:
00289     }
00290         
00292         inline int peek()
00293         {
00294         return check_underrun() ? m_buf.peek() : -1;        
00295     }
00296 
00298         inline int get()
00299         {
00300         return check_underrun() ? m_buf.get() : -1;        
00301     }
00302 };
00303 
00308 template<class T>
00309 class write_buffer: public T {
00310       
00314           data_buffer m_buf; 
00315           
00317           bool m_valid;
00318       
00319       public:
00320              
00321       write_buffer(const T & t, int capacity) : T(t), m_buf(capacity), m_valid(true) { }
00322       ~write_buffer() { 
00323                       // empty buffer on exit
00324                       flush(); 
00325                       }
00326       
00328       bool good() const { return m_valid; }
00329       
00331       bool write(const unsigned char *ptr, int n)
00332       {
00333           int p=0;
00334            // if the size of data is greater of buffer capacity buffer will be
00335            //  bypassed
00336            if(n > m_buf.capacity())
00337            {
00338                 flush();
00339                 T::write(ptr, n);
00340            }
00341            else
00342            {
00343            // sposta i dati nel data_buffer, incrementando
00344            while(n>0)
00345             {
00346             int w = m_buf.write(ptr, n);
00347             n-=w;
00348             if(m_buf.full())
00349              flush();      
00350             }
00351            }
00352           return true;
00353       }
00354       
00356       bool flush()
00357       {
00358         if(!m_valid)
00359             return false;
00360         if(m_buf.size() > 0)
00361             {
00362             int n = m_buf.size();
00363             unsigned char *src = m_buf.data();
00365             while(n>0)
00366                 {
00367                 int r = T::write( src, n );
00368                 if(r<=0)
00369                   {
00370                   m_valid = false;
00371                   return false;
00372                   }
00373                 n -=r;
00374                 src+=r;
00375                 }
00376             m_buf.size(0);
00377                 m_buf.pos(0);           
00378             }
00379          return true;
00380       }
00381       
00383       inline bool put(unsigned char c)
00384       {
00385            m_buf.put(c);
00386            if(m_buf.full())
00387              flush();      
00388            return true;
00389       }       
00390              
00391       };
00392 
00393 }
00394 
00395 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines