casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
MemoryIO.h
Go to the documentation of this file.
00001 //# MemoryIO.h: Class for IO in memory
00002 //# Copyright (C) 1996,1999,2001
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: MemoryIO.h 20551 2009-03-25 00:11:33Z Malte.Marquarding $
00027 
00028 #ifndef CASA_MEMORYIO_H
00029 #define CASA_MEMORYIO_H
00030 
00031 //# Includes
00032 #include <casa/aips.h>
00033 #include <casa/IO/ByteIO.h>
00034 
00035 namespace casa { //# NAMESPACE CASA - BEGIN
00036 
00037 // <summary>Class for IO to a memory buffer.</summary>
00038 
00039 // <use visibility=export>
00040 
00041 // <reviewed reviewer="Friso Olnon" date="1996/11/06" tests="tByteIO" demos="">
00042 // </reviewed>
00043 
00044 // <prerequisite> 
00045 //  <li> <linkto class=ByteIO>ByteIO</linkto>
00046 // </prerequisite>
00047 
00048 // <synopsis>
00049 // This class is doing IO in a buffer in memory.
00050 // It is part of the entire IO framework. It can for
00051 // instance be used to store data in canonical format in a
00052 // memory string and obtain it later.
00053 // <p>
00054 // The memory buffer can be dynamic, so it will be expanded when needed.
00055 // This is done by allocating a larger buffer, copy the contents and
00056 // throw the old buffer away.
00057 // <br>
00058 // The memory buffer can also be static to be sure that the pointer to
00059 // the buffer will not change.
00060 // The expand size determines if the memory buffer is static or dynamic.
00061 // An expand size zero indicates a static buffer.
00062 // <p>
00063 // The memory buffer is seekable and readable. It depends on the
00064 // constructor whether it is writable.
00065 // <p>
00066 // There are several ways in which the buffer can be created/passed:
00067 // <ul>
00068 //  <li> Dynamic by passing an initial size and an expand size.
00069 //       However, an expand size zero can be used to assure that no more
00070 //       data is written than fits in the initial buffer (so once the
00071 //       buffer is created it gets static).
00072 //       In this way the buffer is readable and writable.
00073 //  <li> Static by passing a const buffer and its length.
00074 //       In this way the buffer is not writable.
00075 //  <li> Dynamic or static by passing a non-const buffer, its length,
00076 //       and an expand size (zero = static, >0 = dynamic)
00077 //     . The OpenOption indicates whether the buffer will be writable.
00078 //       Only for ByteIO::Old it will not be writable.
00079 //       The OpenOption also determines the initial seek position.
00080 //       Usually it is 0, but for ByteIO::Append it is the end of the buffer.
00081 // </ul>
00082 // The user can obtain a pointer to the buffer to extract the
00083 // stored data from it. The length of the data can also be obtained.
00084 // <p>
00085 // Usually this class will be used in combination with, say, CanonicalIO
00086 // and AipsIO.
00087 
00088 // <example>
00089 // <srcblock>
00090 //    // Create dynamic (expandable) memory buffer of length 100.
00091 //    // Use that as the sink of RawIO in AipsIO.
00092 //    MemoryIO membuf (100);
00093 //    RawIO rawio (&membuf);
00094 //    AipsIO stream (&rawio);
00095 //    // Write values.
00096 //    stream << (Int)10;
00097 //    stream << True;
00098 //    // Seek to beginning of buffer and read data in.
00099 //    stream.setpos (0);
00100 //    Int vali;
00101 //    Bool valb;
00102 //    stream >> vali >> valb;
00103 //
00104 //    // One can obtain the buffer and its length and use it later.
00105 //    // (e.g. to write it in a non-AipsIO file).
00106 //    uChar* bufptr = membuf.getBuffer();
00107 //    uInt64 length = membuf.length();
00108 //
00109 //    // It can also used to construct another MemoryIO object from it.
00110 //    // The following memory buffer is static and readonly.
00111 //    MemoryIO membuf2 (bufptr, length);
00112 //    membuf2.read (sizeof(vali), vali);
00113 //    membuf2.read (sizeof(valb), valb);
00114 // </srcblock>
00115 // </example>
00116 
00117 // <motivation> 
00118 // Make it possible to do IO in a memory buffer.
00119 // The first implementation used strstreambuf from the iostream package.
00120 // However, that did not allow seeking and it was hard to get the length.
00121 // </motivation>
00122 
00123 
00124 class MemoryIO: public ByteIO
00125 {
00126 public:
00127     // Construct a dynamic object with the given initial length.
00128     explicit MemoryIO (uInt64 initialSize=65536, uInt64 expandSize=32768);
00129 
00130     // Construct from a buffer with the given length.
00131     // The buffer is readonly and cannot be expanded.
00132     MemoryIO (const void* buffer, uInt64 size);
00133 
00134     // Construct from the given buffer with the given length.
00135     // The Byte::Option determines how the buffer will be used.
00136     // The seek pointer is set to the beginning of the buffer, unless
00137     // told otherwise below.
00138     // <dl>
00139     //  <dt> New, NewNoReplace and Scratch
00140     //  <dd> The buffer is empty and is read/write.
00141     //  <dt> Old
00142     //  <dd> The buffer contains <src>size</src> bytes and is readonly.
00143     //  <dt> Update, Delete
00144     //  <dd> The buffer contains <src>size</src> bytes and is read/write.
00145     //  <dt> Append
00146     //  <dd> The buffer contains <src>size</src> bytes and is read/write.
00147     //       The seek pointer is set to the end of the buffer.
00148     // </dl>
00149     // When the buffer is writable, it will be expanded if needed.
00150     // This means that <src>buffer</src> does not point to the data
00151     // anymore. However, when <src>expandSize==0</src>, the buffer
00152     // cannot be expanded and the pointer is always valid.
00153     // <br>When canDelete is True, buffer expansion means that the
00154     // old buffer gets deleted.
00155     MemoryIO (void* buffer, uInt64 size, ByteIO::OpenOption,
00156               uInt64 expandSize=0, Bool canDelete=False);
00157 
00158     // Delete the Memory object.
00159     // The data buffer is not deleted when constructed with the
00160     // constructor taking a buffer pointer.
00161     ~MemoryIO();
00162 
00163     // Write the number of bytes.
00164     // When needed it expands the buffer.
00165     // An exception is thrown when the buffer is not writable or
00166     // when buffer expansion fails or is not possible.
00167     virtual void write (uInt size, const void* buf);
00168 
00169     // Read <src>size</src> bytes from the memory buffer. Returns the number of
00170     // bytes actually read. Will throw an Exception (AipsError) if the
00171     // requested number of bytes could not be read unless throwException is set
00172     // to False. Will always throw an exception if the buffer is not readable
00173     // or the buffer pointer is at an invalid position.
00174     virtual Int read (uInt size, void* buf, Bool throwException=True);    
00175 
00176     // Clear the buffer; i.e. set the data length and seek pointer to zero.
00177     void clear();
00178 
00179     // Get the buffer containing the data.
00180     // <br>The length of the data in the buffer can be obtained using the
00181     // length() function.
00182     const uChar* getBuffer() const;
00183 
00184     // Get the length of the data in the buffer.
00185     virtual Int64 length();
00186 
00187     // Get the allocated length of the buffer.
00188     uInt64 allocated() const;
00189        
00190     // Get the expand size (0 = not expandable).
00191     uInt64 expandSize() const;
00192        
00193     // Is the IO stream readable?
00194     virtual Bool isReadable() const;
00195 
00196     // Is the IO stream writable?
00197     virtual Bool isWritable() const;
00198 
00199     // Is the IO stream seekable?
00200     virtual Bool isSeekable() const;
00201 
00202     // resize the internal buffer (if necessary) so that it is big enough
00203     // to hold the specified number of bytes. Returns a non-const pointer
00204     // to the buffer that can be used to write up to the specified number
00205     // of bytes into the buffer. If less data is written into the buffer
00206     // then the setUsed member funtion should be used to indicate how much
00207     // of the buffer is valid. Throws an exception if the MemoryIO object
00208     // is not writable or if it needs to increase the size of the internal
00209     // buffer and the MemoryIO object is not expandable.
00210     // <note role=warning> You should not use the supplied pointer to write
00211     // more than length data points to the buffer</note>
00212     uChar* setBuffer(uInt64 length);
00213 
00214     // tell the MemoryIO object how much of its internal buffer is valid
00215     // data. You only need to use this function if you are directly writing to
00216     // the buffer using the pointer returned by the non-const getBuffer
00217     // function. This function throws an exception if the number of bytes used
00218     // is greater than the number allocated or if the MemoryIO object is not
00219     // writeable.
00220     void setUsed(uInt64 bytesUsed);
00221 
00222 private:
00223     //# Copy constructor, should not be used.
00224     MemoryIO (const MemoryIO& that);
00225 
00226     //# Assignment, should not be used.
00227     MemoryIO& operator= (const MemoryIO& that);
00228 
00229     // Reset the position pointer to the given value. It returns the
00230     // new position.
00231     // An exception is thrown when seeking before the start of the
00232     // buffer or when seeking past the end of a readonly buffer.
00233     // When seeking past the end of a writable buffer, the required
00234     // amount of bytes is added and initialized to zero.
00235     virtual Int64 doSeek (Int64 offset, ByteIO::SeekOption);
00236 
00237     //# Expand the buffer to at least the given size. The specified size
00238     //# will be used if it results in a larger buffer size. In this way the
00239     //# buffer does not get reallocated too often.  It returns a false status
00240     //# when the buffer cannot be expanded. 
00241     Bool expand (uInt64 minSize);
00242 
00243 
00244     uChar* itsBuffer;
00245     Int64  itsAlloc;
00246     Int64  itsExpandSize;
00247     Int64  itsUsed;
00248     Int64  itsPosition;
00249     Bool   itsReadable;
00250     Bool   itsWritable;
00251     Bool   itsCanDelete;
00252 };
00253 
00254 
00255 inline void MemoryIO::clear()
00256 {
00257     itsUsed = itsPosition = 0;
00258 }
00259 inline const uChar* MemoryIO::getBuffer() const
00260 {
00261     return itsBuffer;
00262 }
00263 inline uInt64 MemoryIO::allocated() const
00264 {
00265     return itsAlloc;
00266 }
00267 inline uInt64 MemoryIO::expandSize() const
00268 {
00269     return itsExpandSize;
00270 }
00271 
00272 
00273 
00274 } //# NAMESPACE CASA - END
00275 
00276 #endif