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
1.5.1