casa
$Rev:20696$
|
00001 //# RecordDesc.h: Description of the fields in a record object 00002 //# Copyright (C) 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 //# 00027 //# $Id: RecordDesc.h 20551 2009-03-25 00:11:33Z Malte.Marquarding $ 00028 00029 00030 #ifndef CASA_RECORDDESC_H 00031 #define CASA_RECORDDESC_H 00032 00033 00034 //# Includes 00035 #include <casa/Containers/RecordDescRep.h> 00036 #include <casa/Containers/RecordInterface.h> 00037 #include <casa/Utilities/COWPtr.h> 00038 #include <casa/iosfwd.h> 00039 00040 namespace casa { //# NAMESPACE CASA - BEGIN 00041 00042 //# Forward Declarations 00043 class AipsIO; 00044 00045 00046 // <summary> 00047 // Description of the fields in a record object 00048 // </summary> 00049 00050 // <use visibility=export> 00051 // <reviewed reviewer="Mark Wieringa" date="1996/04/15" tests="tRecordDesc"> 00052 // </reviewed> 00053 00054 // <prerequisite> 00055 // <li> <linkto group="DataType.h#DataType">DataType</linkto> 00056 // <li> <linkto class="Record">Record</linkto> 00057 // </prerequisite> 00058 // 00059 // <etymology> 00060 // RecordStructure would perhaps have been the clearest possible name. However 00061 // it was decided to name it ``RecordDesc'' to use a compatible naming 00062 // convention with other classes in the system, such as TableDesc. This class 00063 // <em>Desc</em>ribes the structure of a Record. 00064 // </etymology> 00065 // 00066 // <synopsis> 00067 // RecordDesc describes the structure of <linkto class="Record">Record</linkto> 00068 // objects. A Record consists of a number of fields. A RecordDesc describes 00069 // those fields by assigning to each one: 00070 // <ul> 00071 // <li> A name for the field. 00072 // <li> A type from the <linkto group="DataType.h#DataType">DataType</linkto> 00073 // enum. 00074 // <li> A shape if the field is an array. 00075 // <li> A RecordDesc if the field is itself a Record (the Record is an 00076 // hierarchical structure). 00077 // </ul> 00078 // Only one field with a given name is allowed (although fields in subrecords 00079 // may have the same name as a field in a parent or child Record). 00080 // 00081 // Field indices are zero relative, i.e. they range from 0 to 00082 // <src>nfields()-1</src>. 00083 // </synopsis> 00084 // 00085 // <example> 00086 // See the example in the description of the 00087 // <linkto class="Record:example">Record</linkto> class. 00088 // </example> 00089 // 00090 // <motivation> 00091 // It is useful to be able to create many new objects with the same structure 00092 // as some other, without necessarily cloning it by copying all the values. 00093 // A ``Description'' type is necessary to do this (e.g., shape for an Array). 00094 // </motivation> 00095 // 00096 // 00097 // <todo asof="1995/06/01"> 00098 // <li> Should the strategy wrt. field names be changed (not used in 00099 // field description equality, must be unique at a given level?). 00100 // <li> Perhaps we should be able to more conveniently change the description 00101 // of an existing field. 00102 // </todo> 00103 00104 class RecordDesc 00105 { 00106 public: 00107 // Writes/reads the RecordDesc to/from an output stream. 00108 // <group name=io> 00109 friend ostream& operator<< (ostream& os, const RecordDesc& desc); 00110 friend AipsIO& operator<< (AipsIO& os, const RecordDesc& desc); 00111 friend AipsIO& operator>> (AipsIO& os, RecordDesc& desc); 00112 // </group> 00113 00114 // Create a description with no fields. 00115 RecordDesc(); 00116 00117 // Create a description which is a copy of other. 00118 RecordDesc (const RecordDesc& other); 00119 00120 // Replace this description with other. 00121 RecordDesc& operator= (const RecordDesc& other); 00122 00123 ~RecordDesc(); 00124 00125 // Add scalar, array, sub-record, or table field. 00126 // If of array type, the shape is set to [-1], which indicates a 00127 // variable sized array. 00128 // If of sub-record type, the sub-record is free format. 00129 // Returns the number of fields in the description. 00130 uInt addField (const String& fieldName, DataType dataType); 00131 00132 // Add an array field of the indicated type. The DataType is promoted 00133 // from a scalar type to an array type if necessary, e.g., 00134 // <src>TpInt ->TpArrayInt</src>. Returns the number of fields in 00135 // the description. 00136 // A shape of [-1] indicates a variable shape. 00137 uInt addField (const String& fieldName, DataType scalarOrArrayType, 00138 const IPosition& shape); 00139 00140 // Add a Record field to the description. This allows hierarchical 00141 // descriptions to be developed. Returns the number of fields in the 00142 // description. 00143 uInt addField (const String& fieldName, const RecordDesc& subDesc); 00144 00145 // Add a Table field to the description. The Table description has the 00146 // given name. Returns the number of fields in the description. 00147 // <br> 00148 // When a table is put in a record field, it is checked if the name 00149 // of its description matches this name. If this name is empty, it 00150 // matches any table description. 00151 // <note role=warning> 00152 // Note that not all record types are able to instantiate a table field. 00153 // E.g. <linkto class=TableRecord>TableRecord</linkto> can instantiate 00154 // it, while <linkto class=Record>Record</linkto> cannot and throws an 00155 // exception when a record description containing a table field is used. 00156 // </note> 00157 uInt addTable (const String& fieldName, const String& tableDescName); 00158 00159 // Get the comment for this field. 00160 const String& comment (Int whichField) const; 00161 00162 // Set the comment for this field. 00163 void setComment (Int whichField, const String& comment); 00164 00165 // Set the shape for this field. 00166 // An exception will be thrown if the field is no array. 00167 void setShape (Int whichField, const IPosition& shape); 00168 00169 // Merge a single field from other. If allowDuplicates is True, silently 00170 // throw away fields if one with the same name and type already exists, 00171 // otherwise an exception is thrown. Conflicting types always cause an 00172 // exception. Returns the number of fields in the description. 00173 uInt mergeField (const RecordDesc& other, Int whichFieldFromOther, 00174 RecordInterface::DuplicatesFlag DuplicateAction 00175 = RecordInterface::ThrowOnDuplicates); 00176 00177 // Add all the fields from another RecordDesc to the current objects. 00178 // It returns the new number of fields. 00179 uInt merge (const RecordDesc& other, 00180 RecordInterface::DuplicatesFlag DuplicateAction 00181 = RecordInterface::ThrowOnDuplicates); 00182 00183 // Remove the given field from the description. 00184 // It returns the new number of fields. 00185 uInt removeField (Int whichField); 00186 00187 // Rename the given field. 00188 void renameField (const String& newName, Int whichField); 00189 00190 // Returns the index of the field named fieldName. Returns -1 if fieldName 00191 // does not exist. 00192 Int fieldNumber (const String& fieldName) const; 00193 00194 // Number of fields in the description. 00195 uInt nfields() const; 00196 00197 // What is the type of the given field. Returns TpRecord if the field is 00198 // a sub-Record. 00199 DataType type (Int whichField) const; 00200 00201 // What is the name of the given field. 00202 const String& name (Int whichField) const; 00203 00204 // Create a name for a field defined by index as *i (similar to glish). 00205 // It takes care that the resulting name is unique by adding a suffix _j 00206 // when needed. 00207 String makeName (Int whichField) const; 00208 00209 // Make the given name unique by adding a suffix _j when needed. 00210 // j is the minimal number needed to make it unique. 00211 String uniqueName (const String& name) const; 00212 00213 // Returns True if whichField is an array. 00214 Bool isArray (Int whichField) const; 00215 00216 // Returns True if whichField is a scalar. 00217 Bool isScalar (Int whichField) const; 00218 00219 // Returns True if whichField is a sub-record. 00220 Bool isSubRecord (Int whichField) const; 00221 00222 // Returns True if whichField is a table. 00223 Bool isTable (Int whichField) const; 00224 00225 // What is the shape of the given field. Returns [1] if the field is a 00226 // scalar, table or, sub-record, [-1] if it is a variable length array, 00227 // and the actual shape for a fixed length array. 00228 const IPosition& shape (Int whichField) const; 00229 00230 // What is the name of the table description. 00231 // Returns an empty string when the field is no table. 00232 const String& tableDescName (Int whichField) const; 00233 00234 // If whichField is a sub-record return its description. 00235 // Otherwise an exception is thrown. 00236 // The non-const version is named differently to prevent accidental 00237 // use of the non-const version. 00238 // <group> 00239 const RecordDesc& subRecord (Int whichField) const; 00240 RecordDesc& rwSubRecord (Int whichField); 00241 // </group> 00242 00243 // This and other compare equal if the field types and shapes are identical 00244 // (recursively if there are described sub-records). 00245 // The field names are not used. 00246 // <br>Use function isEqual if names are important, but order is not. 00247 // <group> 00248 Bool operator== (const RecordDesc& other) const; 00249 Bool operator!= (const RecordDesc& other) const; 00250 // </group> 00251 00252 // Test if this description conforms the other. 00253 // It is NOT doing it recursively, thus is does not check if 00254 // sub-records are conforming. 00255 // <br>This is used by Record, to see if another record can be assigned 00256 // to this record. 00257 Bool conform (const RecordDesc& other) const; 00258 00259 // Test if this description equals another one. 00260 // It is equal if the number of fields is equal and all field names in 00261 // this description occur in the other too. The order of the fields 00262 // is not important. 00263 // <br>The flag equalDataTypes is set to True if the data types 00264 // of all fields match. 00265 // <br>Use function operator== if order and types are important, 00266 // but names are not. 00267 Bool isEqual (const RecordDesc& other, Bool& equalDataTypes) const; 00268 00269 // Test if this description is a subset of another one. 00270 // It is similar to isEqual above. 00271 Bool isSubset (const RecordDesc& other, Bool& equalDataTypes) const; 00272 00273 // Test if this description is a strict subset of another one, thus 00274 // if it is a subset and not equal. 00275 Bool isStrictSubset (const RecordDesc& other, Bool& equalDataTypes) const; 00276 00277 // Test if this description is a superset of another one. 00278 Bool isSuperset (const RecordDesc& other, Bool& equalDataTypes) const; 00279 00280 // Test if this description is a strict superset of another one, thus 00281 // if it is a superset and not equal. 00282 Bool isStrictSuperset (const RecordDesc& other, 00283 Bool& equalDataTypes) const; 00284 00285 // Test if the set of field names in this and other record description 00286 // is disjoint (i.e. if they do not share names). 00287 Bool isDisjoint (const RecordDesc& other) const; 00288 00289 00290 private: 00291 // Writes/reads the RecordDesc to/from an output stream. 00292 // <group> 00293 ostream& put (ostream& os) const; 00294 AipsIO& put (AipsIO& os) const; 00295 AipsIO& get (AipsIO& os); 00296 // </group> 00297 00298 // Use a copy-on-write pointer to the RecordDescRep. 00299 COWPtr<RecordDescRep> desc_p; 00300 }; 00301 00302 00303 00304 inline RecordDesc::RecordDesc() 00305 : desc_p (new RecordDescRep) 00306 {} 00307 00308 inline RecordDesc::RecordDesc (const RecordDesc& other) 00309 : desc_p (other.desc_p) 00310 {} 00311 00312 inline RecordDesc& RecordDesc::operator= (const RecordDesc& other) 00313 { 00314 if (this != &other) { 00315 desc_p = other.desc_p; 00316 } 00317 return *this; 00318 } 00319 00320 inline RecordDesc::~RecordDesc() 00321 {} 00322 00323 inline uInt RecordDesc::addField (const String& fieldName, DataType dataType) 00324 { 00325 return desc_p.rwRef().addField (fieldName, dataType); 00326 } 00327 00328 inline uInt RecordDesc::addField (const String& fieldName, 00329 DataType scalarOrArrayType, 00330 const IPosition& shape) 00331 { 00332 return desc_p.rwRef().addArray (fieldName, scalarOrArrayType, shape); 00333 } 00334 00335 inline uInt RecordDesc::addField (const String& fieldName, 00336 const RecordDesc& subDesc) 00337 { 00338 return desc_p.rwRef().addRecord (fieldName, subDesc); 00339 } 00340 00341 inline uInt RecordDesc::addTable (const String& fieldName, 00342 const String& tableDescName) 00343 { 00344 return desc_p.rwRef().addTable (fieldName, tableDescName); 00345 } 00346 00347 inline const String& RecordDesc::comment (Int whichField) const 00348 { 00349 return desc_p.ref().comment (whichField); 00350 } 00351 00352 inline void RecordDesc::setComment (Int whichField, const String& comment) 00353 { 00354 desc_p.rwRef().setComment (whichField, comment); 00355 } 00356 00357 inline void RecordDesc::setShape (Int whichField, const IPosition& shape) 00358 { 00359 desc_p.rwRef().setShape (whichField, shape); 00360 } 00361 00362 inline uInt RecordDesc::mergeField (const RecordDesc& other, 00363 Int whichFieldFromOther, 00364 RecordInterface::DuplicatesFlag duplicateAction) 00365 { 00366 return desc_p.rwRef().mergeField (other.desc_p.ref(), whichFieldFromOther, 00367 duplicateAction); 00368 } 00369 00370 inline uInt RecordDesc::merge (const RecordDesc& other, 00371 RecordInterface::DuplicatesFlag duplicateAction) 00372 { 00373 return desc_p.rwRef().merge (other.desc_p.ref(), duplicateAction); 00374 } 00375 00376 inline uInt RecordDesc::removeField (Int whichField) 00377 { 00378 return desc_p.rwRef().removeField (whichField); 00379 } 00380 00381 inline void RecordDesc::renameField (const String& newName, Int whichField) 00382 { 00383 desc_p.rwRef().renameField (newName, whichField); 00384 } 00385 00386 inline Int RecordDesc::fieldNumber (const String& fieldName) const 00387 { 00388 return desc_p.ref().fieldNumber (fieldName); 00389 } 00390 00391 inline uInt RecordDesc::nfields() const 00392 { 00393 return desc_p.ref().nfields(); 00394 } 00395 00396 inline DataType RecordDesc::type (Int whichField) const 00397 { 00398 return desc_p.ref().type (whichField); 00399 } 00400 00401 inline String RecordDesc::uniqueName (const String& name) const 00402 { 00403 return desc_p.ref().uniqueName (name); 00404 } 00405 00406 inline String RecordDesc::makeName (Int whichField) const 00407 { 00408 return desc_p.ref().makeName (whichField); 00409 } 00410 00411 inline const String& RecordDesc::name (Int whichField) const 00412 { 00413 return desc_p.ref().name (whichField); 00414 } 00415 00416 inline Bool RecordDesc::isArray (Int whichField) const 00417 { 00418 return desc_p.ref().isArray (whichField); 00419 } 00420 00421 inline Bool RecordDesc::isScalar (Int whichField) const 00422 { 00423 return desc_p.ref().isScalar (whichField); 00424 } 00425 00426 inline Bool RecordDesc::isSubRecord (Int whichField) const 00427 { 00428 return desc_p.ref().isSubRecord (whichField); 00429 } 00430 00431 inline Bool RecordDesc::isTable (Int whichField) const 00432 { 00433 return desc_p.ref().isTable (whichField); 00434 } 00435 00436 inline const IPosition& RecordDesc::shape (Int whichField) const 00437 { 00438 return desc_p.ref().shape (whichField); 00439 } 00440 00441 inline const String& RecordDesc::tableDescName (Int whichField) const 00442 { 00443 return desc_p.ref().tableDescName (whichField); 00444 } 00445 00446 inline const RecordDesc& RecordDesc::subRecord (Int whichField) const 00447 { 00448 return desc_p.ref().subRecord (whichField); 00449 } 00450 00451 inline RecordDesc& RecordDesc::rwSubRecord (Int whichField) 00452 { 00453 return desc_p.rwRef().subRecord (whichField); 00454 } 00455 00456 inline Bool RecordDesc::operator== (const RecordDesc& other) const 00457 { 00458 return desc_p.ref() == other.desc_p.ref(); 00459 } 00460 00461 inline Bool RecordDesc::operator!= (const RecordDesc& other) const 00462 { 00463 return desc_p.ref() != other.desc_p.ref(); 00464 } 00465 inline Bool RecordDesc::conform (const RecordDesc& other) const 00466 { 00467 return desc_p.ref().conform (other.desc_p.ref()); 00468 } 00469 00470 inline Bool RecordDesc::isEqual (const RecordDesc& other, 00471 Bool& equalDataTypes) const 00472 { 00473 return desc_p.ref().isEqual (other.desc_p.ref(), equalDataTypes); 00474 } 00475 inline Bool RecordDesc::isSubset (const RecordDesc& other, 00476 Bool& equalDataTypes) const 00477 { 00478 return desc_p.ref().isSubset (other.desc_p.ref(), equalDataTypes); 00479 } 00480 inline Bool RecordDesc::isStrictSubset (const RecordDesc& other, 00481 Bool& equalDataTypes) const 00482 { 00483 return desc_p.ref().isStrictSubset (other.desc_p.ref(), equalDataTypes); 00484 } 00485 inline Bool RecordDesc::isSuperset (const RecordDesc& other, 00486 Bool& equalDataTypes) const 00487 { 00488 return other.desc_p.ref().isSubset (desc_p.ref(), equalDataTypes); 00489 } 00490 inline Bool RecordDesc::isStrictSuperset (const RecordDesc& other, 00491 Bool& equalDataTypes) const 00492 { 00493 return other.desc_p.ref().isStrictSubset (desc_p.ref(), equalDataTypes); 00494 } 00495 inline Bool RecordDesc::isDisjoint (const RecordDesc& other) const 00496 { 00497 return desc_p.ref().isDisjoint (other.desc_p.ref()); 00498 } 00499 00500 00501 inline ostream& operator<< (ostream& os, const RecordDesc& desc) 00502 { 00503 return desc.put (os); 00504 } 00505 inline AipsIO& operator<< (AipsIO& os, const RecordDesc& desc) 00506 { 00507 return desc.put (os); 00508 } 00509 inline AipsIO& operator>> (AipsIO& os, RecordDesc& desc) 00510 { 00511 return desc.get (os); 00512 } 00513 00514 00515 00516 00517 00518 } //# NAMESPACE CASA - END 00519 00520 #endif