AipsIO.h

Go to the documentation of this file.
00001 //# AipsIO.h: AipsIO is the object persistency mechanism of Casacore
00002 //# Copyright (C) 1993,1994,1995,1996,1998,2000,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$
00027 
00028 #ifndef CASA_AIPSIO_H
00029 #define CASA_AIPSIO_H
00030 
00031 
00032 //# Includes
00033 #include <casacore/casa/aips.h>
00034 #include <casacore/casa/Containers/Block.h>
00035 #include <casacore/casa/BasicSL/String.h>
00036 #include <casacore/casa/BasicSL/Complex.h>
00037 #include <casacore/casa/IO/ByteIO.h>
00038 #include <casacore/casa/vector.h>
00039 
00040 namespace casacore { //# NAMESPACE CASACORE - BEGIN
00041 
00042 //# Forward Declarations
00043 class TypeIO;
00044 class ByteIO;
00045 class RegularFileIO;
00046 class MultiFileBase;
00047 
00048 
00049 // <summary> 
00050 // AipsIO is the object persistency mechanism of Casacore
00051 // </summary>
00052 
00053 // <use visibility=export>
00054 
00055 // <reviewed reviewer="ghunt" date="95Feb21" tests="" demos="">
00056 
00057 // <etymology>
00058 // AipsIO is simply the conventional shorthand for "AIPS++ input/output".
00059 // Note that Casacore is the successor of the old AIPS++ project.
00060 // </etymology>
00061 
00062 // <synopsis> 
00063 // AipsIO is a class designed to do I/O for objects.
00064 // It reads/writes the data using a class derived from
00065 // <linkto class=TypeIO>TypeIO</linkto>. For instance, class
00066 // <linkto class=CanonicalIO>CanonicalIO</linkto> can be used
00067 // to read/write the data in canonical format.
00068 // <p>
00069 // The TypeIO class in its turn uses a class derived from
00070 // <linkto class=ByteIO>ByteIO</linkto> to determine where the data
00071 // has to be written.
00072 // <p>
00073 // An object is written by writing all its data members.  It will be
00074 // preceeded by a header containing type and version.
00075 // The I/O can be done via de overloaded << and >> operators to write or
00076 // read a single item (e.g., an int or an object).  These operators are
00077 // already defined for all built-in data types and for Complex, DComplex,
00078 // String, and Bool.
00079 // Since each enumeration is a specific type, it is hard to handle them.
00080 // Casting to Bool (which is also an enumerated type) is a possibility,
00081 // but that assumes that each enumerated type has the same size (which
00082 // is probably true for all compilers).
00083 // Another possibility is to store it in an int when writing.  Reading
00084 // can be done the opposite way, although the ARM says that an int
00085 // cannot be assigned to an enumerated type.
00086 // <p>
00087 // There are also functions put, get and getnew to write or read an
00088 // array of values.  These functions are defined for the same data types
00089 // as << and >> (so one can write, for example, an array of Strings).
00090 // AipsIO.put (nr, arr) writes nr values from the given array.
00091 // AipsIO.get (nr, arr) reads nr values into the given user-supplied array.
00092 // AipsIO.getnew (&nr, &arr) reads the number of values written into
00093 // a new array allocated on the heap.  It returns the nr of values read
00094 // and a pointer to the array.
00095 // The data must be read back in the same order as it was written.
00096 // <p>
00097 // The functions <src>putstart(type,version)</src>
00098 // and <src>putend()</src> must be called
00099 // before resp. after writing all values of the object.
00100 // It stores the given type and version of the object.
00101 // Similarly <src>getstart(type)</src> and <src>getend()</src> must be called.
00102 // getstart checks the type and returns the version.  By using the version
00103 // the read function of the object can convert older versions of the
00104 // object (which may still reside on disk) to the latest version.
00105 // The function getNextType is available to get the type of the next
00106 // object stored. This can be used to check the type or to open (i.e.
00107 // issue a getstart) in the correct way.
00108 // <p>
00109 // When implementing a class, one should also define the operators << and >>
00110 // for the class to allow users to write or read an object in this
00111 // simple way (e.g., as  io >> obj;  to read an object).
00112 // One has to define the friend functions:
00113 // <srcblock>
00114 //      friend AipsIO& operator<< (AipsIO&, const YourClass&);
00115 //      friend AipsIO& operator>> (AipsIO&, YourClass&);
00116 // </srcblock>
00117 // since they cannot be stored in the class itself.
00118 // The type of an object is usually passed as the class name.
00119 // <srcblock>
00120 //      AipsIO& operator<< (AipsIO& ios, const YourClass& object) {
00121 //          ios.putstart ("YourClass", version);
00122 //          ios << ....;
00123 //          ios.putend ();
00124 //      }
00125 // </srcblock>
00126 //
00127 // The functions getpos() and setpos(offset) can be used to get and set
00128 // the offset in the file to a given point.  They can be used to point
00129 // to a position in the file where an object must be written or read.
00130 // Obviously these functions are to be used by a storage manager and
00131 // are not for public use.  Someday they should be made private with
00132 // a friend defined.
00133 // </synopsis> 
00134 
00135 // <example>
00136 // <srcblock>
00137 //     MyClass myObject(...);                   // some object
00138 //     AipsIO ios("file.name", ByteIO::New);    // create new file
00139 //     ios << myObject;                         // write object
00140 //     MyClass myObject2;
00141 //     ios >> myObject2;                        // read it back
00142 // </srcblock>
00143 // This example creates an object, writes it to AipsIO and reads it
00144 // back into another object.
00145 // The shift functions for MyClass could be defined as follows:
00146 // <srcblock>
00147 // AipsIO& operator<< (AipsIO& ios, const MyClass& myObject)
00148 // {
00149 //     ios.putstart ("MyClass", 1);    // MyClass version 1
00150 //     ios << ...;                     // write all data members
00151 //     ios.putend();
00152 // }
00153 // AipsIO& operator>> (AipsIO& ios, const MyClass& myObject)
00154 // {
00155 //     // If needed, delete current data members first.
00156 //     // Now read in the object.
00157 //     uInt version = ios.getstart ("MyClass");
00158 //     ios >> ...;                     // read all data members
00159 //     ios.getend();
00160 // }
00161 // </srcblock>
00162 // In this example the version is not used. In more complex objects
00163 // it will probably be used when data members get added or changed
00164 // in future versions of a software system.
00165 // </example>
00166 
00167 
00168 class AipsIO
00169 {
00170 public:
00171     // No file attached yet
00172     AipsIO();
00173 
00174     // Construct and open/create a file with the given name.
00175     // The actual IO is done via a CanonicalIO object on a regular file
00176     // using buffered IO with a buffer of the given size.
00177     // <br>If the MultiFileBase pointer is not null, a virtual file in the
00178     // MultiFileBase will be used instead of a regular file.
00179     explicit AipsIO (const String& fileName,
00180                      ByteIO::OpenOption = ByteIO::Old,
00181                      uInt filebufSize=65536,
00183                      MultiFileBase* mfile=0);
00184 
00185     // Construct from a stream object derived from ByteIO.
00186     // This can for instance by used to use AipsIO on a file descriptor
00187     // for which a <linkto class=FilebufIO>FilebufIO</linkto>
00188     // object has been created.
00189     // The actual IO is done via a CanonicalIO object on top of it.
00190     explicit AipsIO (ByteIO*);
00191 
00192     // Construct from a stream object derived from TypeIO, thus from
00193     // a stream on top of ByteIOn doing the possible conversions.
00194     explicit AipsIO (TypeIO*);
00195 
00196     // Close if not done yet
00197     ~AipsIO();
00198 
00199     // Open/create file (either a regular file or a MultiFileBase virtual file).
00200     // An exception is thrown if the object contains an already open file.
00201     void open (const String& fileName, ByteIO::OpenOption = ByteIO::Old,
00202                uInt filebufSize=65536, MultiFileBase* mfile=0);
00203 
00204     // Open by connecting to the given byte stream.
00205     // This can for instance by used to use AipsIO on a file descriptor
00206     // for which a <linkto class=FilebufIO>FilebufIO</linkto>
00207     // object has been created.
00208     // The actual IO is done via a CanonicalIO object on top of it.
00209     // An exception is thrown if the object contains an already open file.
00210     void open (ByteIO*);
00211 
00212     // Open by connecting to the given typed byte stream.
00213     // An exception is thrown if the object contains an already open file.
00214     void open (TypeIO*);
00215 
00216     // Close file opened
00217     void close();
00218 
00219     // Return the file option.
00220     ByteIO::OpenOption fileOption() const;
00221 
00222     // Start putting an object.
00223     // This writes the object type and version. When reading back getstart
00224     // calls have to be done in the same way. Getstart
00225     // checks the type and returns the version. The user can use that to
00226     // correctly read back objects with different versions.
00227     // <br>
00228     // Data in the outermost object cannot be put before a putstart is done.
00229     // Data in nested objects can be put without an intermediate putstart.
00230     // However, for complex objects it is recommended to do a putstart
00231     // to have a better checking.
00232     // <br>
00233     // After all values (inclusing nested objects) of the object have
00234     // been put, a call to putend has to be done.
00235     // <group>
00236     uInt putstart (const String& objectType, uInt objectVersion);
00237     uInt putstart (const Char* objectType, uInt objectVersion);
00238     // </group>
00239 
00240     // Put a single value.
00241     // <group>
00242     AipsIO& operator<< (const Bool& value);
00243     AipsIO& operator<< (const Char& value);
00244     AipsIO& operator<< (const uChar& value);
00245     AipsIO& operator<< (const short& value);
00246     AipsIO& operator<< (const unsigned short& value);
00247     AipsIO& operator<< (const int& value);
00248     AipsIO& operator<< (const unsigned int& value);
00249     AipsIO& operator<< (const Int64& value);
00250     AipsIO& operator<< (const uInt64& value);
00251     AipsIO& operator<< (const float& value);
00252     AipsIO& operator<< (const double& value);
00253     AipsIO& operator<< (const Complex& value);
00254     AipsIO& operator<< (const DComplex& value);
00255     AipsIO& operator<< (const String& value);
00256     AipsIO& operator<< (const Char* value);
00257     // </group>
00258 
00259     // Put an array of values with the given number of values.
00260     // If the flag putNr is set, the number of values is put first.
00261     // <group>
00262     AipsIO& put (uInt nrval, const Bool* values, Bool putNR = True);
00263     AipsIO& put (uInt nrval, const Char* values, Bool putNR = True);
00264     AipsIO& put (uInt nrval, const uChar* values, Bool putNR = True);
00265     AipsIO& put (uInt nrval, const short* values, Bool putNR = True);
00266     AipsIO& put (uInt nrval, const unsigned short* values, Bool putNR = True);
00267     AipsIO& put (uInt nrval, const int* values, Bool putNR = True);
00268     AipsIO& put (uInt nrval, const unsigned int* values, Bool putNR = True);
00269     AipsIO& put (uInt nrval, const Int64* values, Bool putNR = True);
00270     AipsIO& put (uInt nrval, const uInt64* values, Bool putNR = True);
00271     AipsIO& put (uInt nrval, const float* values, Bool putNR = True);
00272     AipsIO& put (uInt nrval, const double* values, Bool putNR = True);
00273     AipsIO& put (uInt nrval, const Complex* values, Bool putNR = True);
00274     AipsIO& put (uInt nrval, const DComplex* values, Bool putNR = True);
00275     AipsIO& put (uInt nrval, const String* values, Bool putNR = True);
00276     // </group>
00277 
00278     // Put a vector as an array of values
00279     // For standard types it has the same result as put with putNR=True.
00280     template<typename T>
00281     AipsIO& put (const vector<T>& vec)
00282       { *this << uInt(vec.size());
00283         for (typename vector<T>::const_iterator iter=vec.begin();
00284              iter!=vec.end(); ++iter) {
00285           *this << *iter;
00286         }
00287         return *this;
00288       }
00289     //# Possibly specialize for standard types to make it faster.
00290     //# Specialize for a bool vector.
00291     AipsIO& put (const vector<Bool>& vec);
00292 
00293 
00294     // End putting an object. It returns the object length (including
00295     // possible nested objects).
00296     uInt putend();
00297 
00298     // Get and set file-offset.
00299     // <group>
00300     Int64 getpos ();
00301     Int64 setpos (Int64 offset);
00302     // </group>
00303 
00304     // Get the type of the next object stored.
00305     // This is not possible if a put is in progress.
00306     const String& getNextType();
00307 
00308     // Start reading an object. It will check if the given type matches
00309     // the one stored by putstart. It returns the object version which
00310     // can be used to read in older version of the object correctly.
00311     // <br>
00312     // After all values (inclusing nested objects) of the object have
00313     // been read, a call to getend has to be done.
00314     // <group>
00315     uInt getstart (const String& objectType);
00316     uInt getstart (const Char* objectType);
00317     // </group>
00318 
00319     // Get a single value.
00320     // <group>
00321     AipsIO& operator>> (Bool& value);
00322     AipsIO& operator>> (Char& value);
00323     AipsIO& operator>> (uChar& value);
00324     AipsIO& operator>> (short& value);
00325     AipsIO& operator>> (unsigned short& value);
00326     AipsIO& operator>> (int& value);
00327     AipsIO& operator>> (unsigned int& value);
00328     AipsIO& operator>> (Int64& value);
00329     AipsIO& operator>> (uInt64& value);
00330     AipsIO& operator>> (float& value);
00331     AipsIO& operator>> (double& value);
00332     AipsIO& operator>> (Complex& value);
00333     AipsIO& operator>> (DComplex& value);
00334     AipsIO& operator>> (String& value);
00335     // </group>
00336 
00337     // Read in nrval values into the user-supplied values buffer.
00338     // The buffer must be long enough.
00339     // <group>
00340     AipsIO& get (uInt nrval, Bool* values);
00341     AipsIO& get (uInt nrval, Char* values);
00342     AipsIO& get (uInt nrval, uChar* values);
00343     AipsIO& get (uInt nrval, short* values);
00344     AipsIO& get (uInt nrval, unsigned short* values);
00345     AipsIO& get (uInt nrval, int* values);
00346     AipsIO& get (uInt nrval, unsigned int* values);
00347     AipsIO& get (uInt nrval, Int64* values);
00348     AipsIO& get (uInt nrval, uInt64* values);
00349     AipsIO& get (uInt nrval, float* values);
00350     AipsIO& get (uInt nrval, double* values);
00351     AipsIO& get (uInt nrval, Complex* values);
00352     AipsIO& get (uInt nrval, DComplex* values);
00353     AipsIO& get (uInt nrval, String* values);
00354     // </group>
00355 
00356     // Get a vector as an array of values (similar to getnew).
00357     // It resizes the vector as needed.
00358     template<typename T>
00359     AipsIO& get (vector<T>& vec)
00360       { uInt sz;
00361         *this >> sz;
00362         vec.resize(sz);
00363         for (typename vector<T>::iterator iter=vec.begin();
00364              iter!=vec.end(); ++iter) {
00365           *this >> *iter;
00366         }
00367         return *this;
00368       }
00369     //# Specialize for a bool vector.
00370     AipsIO& get (vector<Bool>& vec);
00371 
00372 
00373     // Read in values as written by the function put.
00374     // It will read the number of values (into nrval), allocate a
00375     // values buffer of that length and read the values into that buffer.
00376     // A pointer to the buffer is returned into values.
00377     // <warn=caution> Although the buffer is allocated by this function,
00378     // the user has to delete it (using <src>delete [] values;</src>).
00379     // <group>
00380     AipsIO& getnew (uInt& nrval, Bool*& values);
00381     AipsIO& getnew (uInt& nrval, Char*& values);
00382     AipsIO& getnew (uInt& nrval, uChar*& values);
00383     AipsIO& getnew (uInt& nrval, short*& values);
00384     AipsIO& getnew (uInt& nrval, unsigned short*& values);
00385     AipsIO& getnew (uInt& nrval, int*& values);
00386     AipsIO& getnew (uInt& nrval, unsigned int*& values);
00387     AipsIO& getnew (uInt& nrval, Int64*& values);
00388     AipsIO& getnew (uInt& nrval, uInt64*& values);
00389     AipsIO& getnew (uInt& nrval, float*& values);
00390     AipsIO& getnew (uInt& nrval, double*& values);
00391     AipsIO& getnew (uInt& nrval, Complex*& values);
00392     AipsIO& getnew (uInt& nrval, DComplex*& values);
00393     AipsIO& getnew (uInt& nrval, String*& values);
00394     // </group>
00395 
00396     // End reading an object. It returns the object length (including
00397     // possible nested objects).
00398     // It checks if the entire object has been read (to keep the data
00399     // stream in sync). If not, an exception is thrown.
00400     uInt getend();
00401 
00402 private:
00403     // Initialize everything for the open.
00404     // It checks if there is no outstanding open file.
00405     void openInit (ByteIO::OpenOption);
00406 
00407     // Test if put is possible (throw exception if not).
00408     void testput();
00409 
00410     // Test if get is possible (throw exception if not).
00411     void testget();
00412 
00413     // Test if get did not exceed object.
00414     void testgetLength();
00415 
00416     // Throw exception for testput
00417     void testputerr();
00418 
00419     // Throw exception for testget
00420     void testgeterr();
00421 
00422     // Throw exception for testgetLength
00423     void testgeterrLength();
00424 
00425 
00426     //  1 = file was opened by AipsIO
00427     //  0 = file not opened
00428     // -1 = file opened by user (=fd passed)
00429     Int          opened_p;
00430     // File open option
00431     ByteIO::OpenOption fopt_p;
00432     // <0 = not opened for put
00433     //  0 = no putstart done
00434     // >0 = put is possible
00435     int          swput_p;
00436     // <0 = not opened for get
00437     //  0 = no getstart done
00438     // >0 = get is possible
00439     int          swget_p;
00440     // Nested object level
00441     uInt         level_p;
00442     // Current size of objlen and objptr
00443     uInt         maxlev_p;
00444     // Object length at each level
00445     Block<uInt>  objlen_p;
00446     // Object length to be read at each level
00447     Block<uInt>  objtln_p;
00448     // Offset of length at each level
00449     Block<Int64>  objptr_p;
00450     // True = the object type has already been read
00451     Bool         hasCachedType_p;
00452     // The cached object type.
00453     String       objectType_p;
00454     // The file object.
00455     ByteIO*      file_p;
00456     // The actual IO object.
00457     TypeIO*      io_p;
00458     // Is the file is seekable?
00459     Bool         seekable_p;
00460     // magic value to check sync.
00461     static const uInt magicval_p;
00462 };
00463 
00464 
00465 
00466 // Return the file option.
00467 inline ByteIO::OpenOption AipsIO::fileOption() const
00468 { return fopt_p; }
00469 
00470 
00471 // testput tests if a put can be done; ie. if putstart has been done.
00472 // It throws an exception if not.
00473 // testget is similar to test if a get can be done.
00474 inline void AipsIO::testput()
00475 {
00476     if (swput_p <= 0) {
00477         testputerr();
00478     }
00479 }
00480 inline void AipsIO::testget()
00481 {
00482     if (swget_p <= 0) {
00483         testgeterr();
00484     }
00485 }
00486 inline void AipsIO::testgetLength()
00487 {
00488     if (objlen_p[level_p] > objtln_p[level_p]) {
00489         testgeterrLength();
00490     }
00491 }
00492 
00493 
00494 
00495 } //# NAMESPACE CASACORE - END
00496 
00497 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 31 Aug 2016 for casa by  doxygen 1.6.1