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