AipsIO.h

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

Generated on Mon Sep 1 22:33:49 2008 for NRAOCASA by  doxygen 1.5.1