casa
$Rev:20696$
|
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