casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
DynBuffer.h
Go to the documentation of this file.
00001 //# DynBuffer.h: Store data in dynamically allocated buffers
00002 //# Copyright (C) 1993,1994,1995,1996
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //#
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //#
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //#
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //#
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //# $Id: DynBuffer.h 21090 2011-06-01 10:01:28Z gervandiepen $
00027 
00028 #ifndef CASA_DYNBUFFER_H
00029 #define CASA_DYNBUFFER_H
00030 
00031 //# Includes
00032 #include <casa/aips.h>
00033 #include <casa/Containers/Block.h>
00034 
00035 
00036 namespace casa { //# NAMESPACE CASA - BEGIN
00037 
00038 // <summary>
00039 // Store data in dynamically allocated buffers
00040 // </summary>
00041 
00042 // <use visibility=export>
00043 // <reviewed reviewer="Friso Olnon" date="1995/03/16" tests="tDynBuffer" demos="">
00044 // </reviewed>
00045 
00046 // <synopsis> 
00047 // DynBuffer allows one to store data in dynamically allocated buffers.
00048 // When a buffer is full, an additional buffer can be allocated and
00049 // "linked" to the existing one; so, the data may not be stored contiguously
00050 // You can loop through all the linked buffers and get their individual
00051 // addresses and sizes, so that you can access the data.
00052 // </synopsis> 
00053 
00054 // <example>
00055 // Example (without exception handling):
00056 // <srcblock>
00057 // uInt nrOfValues, nrNeeded, nrAvailable;// nr of data values
00058 // float* pData = floatarr;               // ptr to data to be handled
00059 // Char* pBuffer;                         // ptr to buffer
00060 //
00061 // DynBuffer buffer;                      // create buffer
00062 // buffer.allocstart();                   // prepare for storing
00063 // nrNeeded = nrOfValues;                 // nr of values to store
00064 // // copy data into dynamic buffer
00065 // while (nrNeeded > 0) {
00066 //     nrAvailable = buffer.alloc (nrNeeded, sizeof(float), pBuffer);
00067 //                                        // get buffer space:
00068 //                                        // room for nrAvailable values
00069 //     memcpy (pBuffer, pData, nrAvailable*sizeof(float));
00070 //                                        // copy that many data values
00071 //     nrNeeded -= nrAvailable;           // how much more needed?
00072 //     pData += nrAvailable;              // pointer to as yet unstored data
00073 // }
00074 // // Maybe store more values
00075 //     .
00076 //     .
00077 // // Retrieve all the data values from the buffers and write them
00078 // buffer.nextstart();                    // goto buffer start
00079 // while (buffer.next (nrAvailable, pBuffer)) {
00080 //                                        // get next buffer
00081 //     write (fd, nrAvailable, pBuffer);  // write data from that buffer
00082 // }
00083 // </srcblock>
00084 // </example>
00085 
00086 // <motivation>
00087 // This class is developed as an intermediate buffer for
00088 // class <linkto class=AipsIO>AipsIO</linkto>,
00089 // but it may serve other purposes as well.
00090 // </motivation>
00091 
00092 class DynBuffer
00093 {
00094 public:
00095 
00096     // Allocate a first buffer of the specified number of bytes
00097     // (default 4096). When the allocation fails, an exception is thrown.
00098     DynBuffer (uInt nrOfBytes=4096);
00099 
00100     // Remove the whole buffer, i.e. the first buffer and all the 
00101     // buffers appended to it.
00102     ~DynBuffer ();
00103 
00104     // Prepare for storing data (re-initialize the buffer)
00105     void allocstart ();
00106 
00107     // Allocate buffer space for <src>nrOfValues</src> values of size
00108     // <src>valueSize</src> bytes, and return the pointer <src>ptr</src>
00109     // to the buffer and the number of values that fit in the buffer.
00110     // 
00111     // When not all values fit in the current buffer, new buffer space
00112     // is added (probably non-contiguous). If that allocation fails an
00113     // exception is thrown.
00114     uInt alloc (uInt nrOfValues, uInt valueSize, Char*& ptr);
00115 
00116     // Remove buffer <src>nrOfBuffer</src> and the buffers appended to it,
00117     // and re-initialize the current buffer. By default we keep the first
00118     // buffer (i.e. the one numbered 0).
00119     //
00120     // The idea is that you may want to free intermediate storage
00121     // space taken up by data that you no longer need, and that the
00122     // first buffer is often big enough to hold further data. So, you
00123     // only remove the first buffer in special cases.
00124     void remove (uInt nrOfBuffer=1);
00125 
00126     // Prepare for data retrieval (set up for looping through the buffers).
00127     void nextstart ();
00128 
00129     // Get the pointer to the next buffer and its used length in bytes.
00130     // The function returns a <src>False</src> value if there are no more
00131     // buffers.
00132     Bool next (uInt& usedLength, Char*& ptr);
00133 
00134 private:
00135     // Get the next buffer for storing <src>nrOfValues</src> values of
00136     // size <src>valueSize</src> bytes, and return the number of values
00137     // that can be stored in the free space of that buffer (maybe less
00138     // than <src>nrOfValues</src>).
00139     //
00140     // The new current buffer can be the present one (if it has free
00141     // space), the next buffer already allocated (if there is one), or
00142     // a newly allocated and linked-in buffer. If, in the last case,
00143     // the allocation fails an exception is thrown.
00144     uInt newbuf (uInt nrOfValues, uInt valueSize);
00145 
00146 
00147     // size of 1st buffer and min. bufsize
00148     uInt         bufsz_p;
00149     // buffernr for next function
00150     Int          nextbuf_p;
00151     // current buffernr
00152     Int          curbuf_p;
00153     // nr of buffers allocated
00154     Int          nrbuf_p;
00155     // size of Blocks
00156     Int          maxnrbuf_p;
00157     // used length per buffer
00158     Block<uInt>  uselen_p;     
00159     // total length per buffer
00160     Block<uInt>  totlen_p;      
00161     // pointer to buffer
00162     PtrBlock<Char*> bufptr_p;     
00163     // used length of current buffer
00164     uInt         curuselen_p;      
00165     // total length of current buffer
00166     uInt         curtotlen_p;      
00167     // pointer to current buffer
00168     Char*        curbufptr_p;      
00169 };
00170 
00171 
00172 //# Allocate buffer space for the nrOfValues values.
00173 //# Return pointer to the buffer and nr of values that fit in it.
00174 //# Use a more specialized function if not all values fit.
00175 //# In this way the function can be kept small and thus used inline.
00176 //# newbuf will seldom be required, unless large vectors are stored.
00177 inline uInt DynBuffer::alloc (uInt nrOfValues, uInt valueSize, Char*& ptr)
00178 {
00179     uInt n = nrOfValues;
00180     if (n*valueSize > curtotlen_p-curuselen_p) {
00181         n = newbuf (nrOfValues, valueSize);
00182     }
00183     ptr = curbufptr_p + curuselen_p;
00184     curuselen_p += n*valueSize;
00185     return n;
00186 }
00187 
00188 
00189 
00190 } //# NAMESPACE CASA - END
00191 
00192 #endif