casa
$Rev:20696$
|
00001 //# RecordDescRep.h: Representation of a RecordDesc 00002 //# Copyright (C) 1996,1997,1998,1999,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: RecordDescRep.h 20551 2009-03-25 00:11:33Z Malte.Marquarding $ 00028 00029 00030 #ifndef CASA_RECORDDESCREP_H 00031 #define CASA_RECORDDESCREP_H 00032 00033 //# Includes 00034 #include <casa/aips.h> 00035 #include <casa/Utilities/DataType.h> 00036 #include <casa/Containers/Block.h> 00037 #include <casa/Containers/SimOrdMap.h> 00038 #include <casa/Arrays/IPosition.h> 00039 #include <casa/iosfwd.h> 00040 00041 namespace casa { //# NAMESPACE CASA - BEGIN 00042 00043 //# Forward Declarations 00044 class RecordDesc; 00045 class AipsIO; 00046 00047 00048 // <summary> 00049 // Representation of a RecordDesc 00050 // </summary> 00051 00052 // <use visibility=local> 00053 // <reviewed reviewer="Mark Wieringa" date="1996/04/15" tests="tRecordDesc"> 00054 // </reviewed> 00055 00056 // <prerequisite> 00057 // <li> <linkto group="DataType.h#DataType">DataType</linkto> 00058 // <li> <linkto class="RecordDesc">RecordDesc</linkto> 00059 // </prerequisite> 00060 00061 // <etymology> 00062 // Rep is an often used abbreviation for representation. 00063 // Thus RecordDescRep is the representation of a RecordDesc. 00064 // </etymology> 00065 00066 // <synopsis> 00067 // RecordDescRep is used by RecordDesc 00068 // to implement its copy-on-write semantics. RecordDesc is the interface 00069 // to the user, while RecordDescRep contains the actual implementation. 00070 // See <linkto class=RecordDesc>RecordDesc</linkto> for a more detailed 00071 // description of a record description. 00072 // </synopsis> 00073 00074 // <example> 00075 // See the example in the description of the 00076 // <linkto class="Record:example">Record</linkto> class. 00077 // </example> 00078 00079 // <motivation> 00080 // RecordDescRep is needed to make copy-on-write semantics possible in 00081 // class RecordDesc. 00082 // </motivation> 00083 00084 // <todo asof="1995/06/01"> 00085 // <li> Should the strategy wrt. field names be changed (not used in 00086 // field description equality, must be unique at a given level?). 00087 // <li> Perhaps we should be able to more conveniently change the description 00088 // of an existing field. 00089 // </todo> 00090 00091 class RecordDescRep 00092 { 00093 public: 00094 // Create a description with no fields. 00095 RecordDescRep(); 00096 00097 // Create a description which is a copy of other. 00098 RecordDescRep (const RecordDescRep& other); 00099 00100 // Replace this description with other. 00101 RecordDescRep& operator= (const RecordDescRep& other); 00102 00103 virtual ~RecordDescRep(); 00104 00105 // Add scalar or array field. If of array type, the shape is set to [-1], 00106 // which indicates a variable sized array. Returns the number of fields in 00107 // the description. 00108 uInt addField (const String& fieldName, DataType scalarOrArrayType); 00109 00110 // Add an array field of the indicated type. The DataType is promoted 00111 // from a scalar type to an array type if necessary, e.g., 00112 // <src>TpInt ->TpArrayInt</src>. Returns the number of fields in 00113 // the description. 00114 uInt addArray (const String& fieldName, DataType scalarOrArrayType, 00115 const IPosition& shape); 00116 00117 // Add a Record field to the description. This allows hierarchical 00118 // descriptions to be developed. Returns the number of fields in the 00119 // description. 00120 uInt addRecord (const String& fieldName, const RecordDesc& subDesc); 00121 00122 // Add a Table field to the description. The Table description has the 00123 // given name. Returns the number of fields in the description. 00124 uInt addTable (const String& fieldName, const String& tableDescName); 00125 00126 // Get the comment for this field. 00127 const String& comment (Int whichField) const; 00128 00129 // Set the comment for this field. 00130 void setComment (Int whichField, const String& comment); 00131 00132 // Set the shape for this field. 00133 // An exception will be thrown if the field is no array. 00134 void setShape (Int whichField, const IPosition& shape); 00135 00136 // Merge a single field from other. If allowDuplicates is True, silently 00137 // throw away fields if one with the same name and type already exists, 00138 // otherwise an exception is thrown. Conflicting types always cause an 00139 // exception. Returns the number of fields in the description. 00140 uInt mergeField (const RecordDescRep& other, Int whichFieldFromOther, 00141 int duplicateAction); 00142 00143 // Add all the fields from another RecordDescRep to the current objects. 00144 uInt merge (const RecordDescRep& other, int duplicateAction); 00145 00146 // Remove the given field from the description. 00147 virtual uInt removeField (Int whichField); 00148 00149 // Rename the given field. 00150 virtual void renameField (const String& newName, Int whichField); 00151 00152 // Returns the index of the field named fieldName. Returns -1 if fieldName 00153 // does not exist. 00154 Int fieldNumber (const String& fieldName) const; 00155 00156 // Number of fields in the description. 00157 uInt nfields() const; 00158 00159 // What is the type of the given field. Returns TpRecord if the field is 00160 // a sub-Record. 00161 DataType type (Int whichField) const; 00162 00163 // What is the name of the given field. 00164 const String& name (Int whichField) const; 00165 00166 // Create a name for a field defined by index as *i (similar to glish). 00167 // It takes care that the resulting name is unique by adding a suffix _j 00168 // when needed. 00169 String makeName (Int whichField) const; 00170 00171 // Make the given name unique by adding a suffix _j when needed. 00172 // j is the minimal number needed to make it unique. 00173 String uniqueName (const String& name) const; 00174 00175 // Returns True if whichField is an array. 00176 Bool isArray (Int whichField) const; 00177 00178 // Returns True if whichField is a scalar. 00179 Bool isScalar (Int whichField) const; 00180 00181 // Returns True if whichField is a sub-record. 00182 Bool isSubRecord (Int whichField) const; 00183 00184 // Returns True if whichField is a table. 00185 Bool isTable (Int whichField) const; 00186 00187 // What is the shape of the given field. Returns [1] if the field is a 00188 // scalar, table or, sub-record, [-1] if it is a variable length array, 00189 // and the actual shape for a fixed length array. 00190 const IPosition& shape (Int whichField) const; 00191 00192 // What is the name of the table description associated with a table. 00193 const String& tableDescName (Int whichField) const; 00194 00195 // If whichField is a sub-record with a description, 00196 // return its description. Otherwise an exception is thrown. 00197 // <group> 00198 const RecordDesc& subRecord (Int whichField) const; 00199 RecordDesc& subRecord (Int whichField); 00200 // </group> 00201 00202 // <group> 00203 // This and other compare equal if the field types and shapes are identical 00204 // (recursively if there are described sub-records or tables). 00205 // The field names are not used. 00206 Bool operator== (const RecordDescRep& other) const; 00207 Bool operator!= (const RecordDescRep& other) const; 00208 // </group> 00209 00210 // Test if this description conforms the other. 00211 // It is similar to operator==. However, a subrecord in that description 00212 // always conforms an arbitrary (i.e. empty) subrecord in this 00213 // description. 00214 // <br>This is used by Record, to see if another record can be assigned 00215 // to this record. 00216 Bool conform (const RecordDescRep& other) const; 00217 00218 // Test if this description equals another one. 00219 // It is equal if the number of fields is equal and all field names in 00220 // this description occur in the other too. The order of the fields 00221 // is not important. 00222 // <br>The flag equalDataTypes is set to True if the data types 00223 // of all fields match. 00224 // <br>Use function operator== if order and types are important, 00225 // but names are not. 00226 Bool isEqual (const RecordDescRep& other, Bool& equalDataTypes) const; 00227 00228 // Test if this description is a subset of another one. 00229 // It is similar to isEqual above. 00230 Bool isSubset (const RecordDescRep& other, Bool& equalDataTypes) const; 00231 00232 // Test if this description is a strict subset of another one, thus 00233 // if it is a subset and not equal. 00234 Bool isStrictSubset (const RecordDescRep& other, 00235 Bool& equalDataTypes) const; 00236 00237 // Test if the set of field names in this and other record description 00238 // is disjoint (i.e. if they do not share names). 00239 Bool isDisjoint (const RecordDescRep& other) const; 00240 00241 protected: 00242 // Add a field name and its type. 00243 // It checks if the name is unique and it extends the various blocks 00244 // using increment_length. 00245 void addFieldName (const String& fieldName, DataType type); 00246 00247 // Add a field from another Record description. 00248 // This is used by the merge functions. 00249 virtual void addRepField (const RecordDescRep& other, 00250 const String& newName, Int whichField); 00251 00252 // Add the field info. These are helper functions for the add functions 00253 // and can be used in derived classes too. 00254 // <group> 00255 void addFieldAny (DataType scalarOrArrayType); 00256 void addFieldArray (DataType scalarOrArrayType, const IPosition& shape); 00257 // </group> 00258 00259 // Set the shape (for a derived class). 00260 void setShape (const IPosition& shape, Int whichField); 00261 00262 // Helper functions 00263 // <group> 00264 virtual void increment_length(); 00265 void copy_other (const RecordDescRep& other); 00266 // </group> 00267 00268 private: 00269 // Test if all fields are part of the other description. 00270 // The flag equalDataTypes is set to True if the data types of the 00271 // fields in both descriptions are the same. 00272 Bool allExist (const RecordDescRep&, Bool& equalDataTypes) const; 00273 00274 // Number of fields in the description. 00275 uInt n_p; 00276 // The DataType of each field. 00277 Block<Int> types_p; 00278 // The name of each field. 00279 Block<String> names_p; 00280 // The description of the subrecords. Null if the field is not a subrecord. 00281 // This isn't the most efficient representation. If this is ever an issue 00282 // we could calculate these, or store them in one Block, or implement 00283 // copy-on-write semantics. 00284 PtrBlock<RecordDesc*> sub_records_p; 00285 // The shape of the field [1] for scalars and sub-records. 00286 Block<IPosition> shapes_p; 00287 // True if the corresponding field is an array. 00288 Block<Bool> is_array_p; 00289 // Table description name for table fields. 00290 Block<String> tableDescNames_p; 00291 // Comments for each field. 00292 Block<String> comments_p; 00293 // Mapping of field name to field number. 00294 SimpleOrderedMap<String,Int> name_map_p; 00295 }; 00296 00297 inline uInt RecordDescRep::nfields() const 00298 { 00299 return n_p; 00300 } 00301 00302 inline DataType RecordDescRep::type (Int whichField) const 00303 { 00304 return DataType(types_p[whichField]); 00305 } 00306 00307 inline const String& RecordDescRep::name (Int whichField) const 00308 { 00309 return names_p[whichField]; 00310 } 00311 00312 inline const IPosition& RecordDescRep::shape (Int whichField) const 00313 { 00314 return shapes_p[whichField]; 00315 } 00316 00317 inline Bool RecordDescRep::isArray (Int whichField) const 00318 { 00319 return is_array_p[whichField]; 00320 } 00321 00322 inline Bool RecordDescRep::isScalar (Int whichField) const 00323 { 00324 return isScalarFun (DataType(types_p[whichField])); 00325 } 00326 00327 inline Bool RecordDescRep::isSubRecord (Int whichField) const 00328 { 00329 return (types_p[whichField] == TpRecord); 00330 } 00331 00332 inline Bool RecordDescRep::isTable (Int whichField) const 00333 { 00334 return (types_p[whichField] == TpTable); 00335 } 00336 00337 inline const RecordDesc& RecordDescRep::subRecord (Int whichField) const 00338 { 00339 //# The cast to non-const is completely safe. 00340 return ((RecordDescRep*)this)->subRecord (whichField); 00341 } 00342 00343 inline const String& RecordDescRep::tableDescName (Int whichField) const 00344 { 00345 return tableDescNames_p[whichField]; 00346 } 00347 00348 00349 00350 } //# NAMESPACE CASA - END 00351 00352 #endif