casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
RecordRep.h
Go to the documentation of this file.
00001 //# RecordRep.h: The representation of a Record
00002 //# Copyright (C) 1996,1997,2000,2001,2005
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: RecordRep.h 20969 2010-09-27 12:45:04Z gervandiepen $
00028 
00029 
00030 #ifndef CASA_RECORDREP_H
00031 #define CASA_RECORDREP_H
00032 
00033 //# Includes
00034 #include <casa/aips.h>
00035 #include <casa/Containers/Block.h>
00036 #include <casa/Containers/RecordDesc.h>
00037 #include <casa/Containers/RecordInterface.h>
00038 
00039 namespace casa { //# NAMESPACE CASA - BEGIN
00040 
00041 //# Forward Declarations
00042 class AipsIO;
00043 class IPosition;
00044 class String;
00045 
00046 
00047 // <summary>
00048 // The representation of a  Record
00049 // </summary>
00050 
00051 // <use visibility=local>
00052 // <reviewed reviewer="Mark Wieringa" date="1996/04/15" tests="tRecord">
00053 // </reviewed>
00054 
00055 // <prerequisite>
00056 //   <li> <linkto class="Record">Record</linkto>.
00057 // </prerequisite>
00058 //
00059 // <etymology>
00060 // RecordRep is the REPresentation of a Record.
00061 // </etymology>
00062 //
00063 // <synopsis>
00064 // RecordRep is the actual implementation of a Record object.
00065 // It contains the description and the data. The data is stored as
00066 // a collection of void* pointers to the actual data. By storing
00067 // it in this indirect way, it is easier to extend the data block.
00068 // It also means that RecordFieldPtr objects always have the correct
00069 // pointer and do not need to be adjusted when the data block is extended.
00070 // <p>
00071 // Despite the fact that the data pointers have type void*, the
00072 // functions are completely type safe. This is done by passing the
00073 // type around using the DataType enumeration. The downpart is that
00074 // only types from that enumeration are supported (but that is also
00075 // required by the RecordDesc mechanics).
00076 // <p>
00077 // Note that RecordRep does not know anything about RecordFieldPtr
00078 // objects pointing to its data. Only its mother class Record
00079 // knows about them and handles all cases where the RecordFieldPtr's
00080 // have to be notified.
00081 // </synopsis>
00082 //
00083 // <example>
00084 // RecordRep mirrors all functions in Record.
00085 // </example>
00086 //
00087 // <motivation>
00088 // Having a separate RecordRep class makes copy-on-write possible.
00089 // It also allows derivation of other RecordRep classes (like TableRecordRep),
00090 // while their mother classes are not derived from each other.
00091 // </motivation>
00092 //
00093 // <todo asof="1996/03/12">
00094 //   <li> An implementation where arrays are stored as T*'s would cut down on
00095 //        instantiations (the Arrayness would come back through the creation
00096 //        of the <src>RecordFieldPtr<Array<T> ></src>).
00097 // </todo>
00098 
00099 
00100 class RecordRep
00101 {
00102 public:
00103     // Create a record with no fields.
00104     RecordRep();
00105 
00106     // Create a record with the given description. If it is not possible to 
00107     // create all fields (for example, if a field of an unsupported type is
00108     // requested), an exception is thrown.
00109     // All fields are checked by the field checking function (if defined).
00110     RecordRep (const RecordDesc& description);
00111 
00112     // Create a copy of other using copy semantics.
00113     RecordRep (const RecordRep& other);
00114 
00115     // Copy all the data over.
00116     RecordRep& operator= (const RecordRep& other);
00117     
00118     // Delete all data.
00119     virtual ~RecordRep();
00120 
00121     // Get the comment for this field.
00122     const String& comment (Int whichField) const;
00123 
00124     // Set the comment for this field.
00125     void setComment (Int whichField, const String& comment);
00126 
00127     // Describes the current structure of this Record.
00128     const RecordDesc& description() const;
00129 
00130     // Change the structure of this Record to contain the fields in
00131     // newDescription. After calling restructure, <src>description() ==
00132     // newDescription</src>.
00133     void restructure (const RecordDesc& newDescription, Bool recursive);
00134 
00135     // Returns True if this and other have the same RecordDesc, other
00136     // than different names for the fields. That is, the number, type and the
00137     // order of the fields must be identical (recursively for fixed
00138     // structured sub-Records in this).
00139     // <note role=caution>
00140     // <src>thisRecord.conform(thatRecord) == True</src> does not imply
00141     // <br><src>thatRecord.conform(thisRecord) == True</src>, because
00142     // a variable record in one conforms a fixed record in that, but
00143     // not vice-versa.
00144     // </note>
00145     Bool conform (const RecordRep& other) const;
00146 
00147     // Copy all data of the Record.
00148     void copyData (const RecordRep& other);
00149 
00150     // Copy a data field.
00151     // This can only handle scalars and arrays.
00152     void copyDataField (DataType type, Int whichField, const void* that) const;
00153 
00154     // Remove a field from the record.
00155     void removeField (Int whichField);
00156 
00157     // Rename the given field.
00158     void renameField (const String& newName, Int whichField);
00159 
00160     // Add a field with the given name and value to the record.
00161     // The data type of the field is determined by the data type of the value.
00162     // For arrays it is possible to define if the shape is fixed.
00163     // <group>
00164     void addDataField (const String& name, DataType type,
00165                        const IPosition& shape, Bool fixedShape,
00166                        const void* data);
00167     void addField (const String& name, const Record& value,
00168                    RecordInterface::RecordType type);
00169     // </group>
00170 
00171     // Define a value for the given field.
00172     // Array conformance rules will not be applied for variable shaped arrays.
00173     // When the field and value data type mismatch, type promotion
00174     // of scalars will be done if possible. If not possible, an exception
00175     // is thrown.
00176     void defineDataField (Int whichField, DataType type, const void* value);
00177 
00178     // Put the description and data of the Record.
00179     // It also puts the fixedFlag attribute (of the mother object).
00180     void putRecord (AipsIO& os, int recordType) const;
00181 
00182     // Get the description and data of the Record.
00183     // It also gets the fixedFlag attribute (of the mother object).
00184     void getRecord (AipsIO& os, Int& recordType);
00185 
00186     // Put the data of a record.
00187     // This is used to write a subrecord, whose description has
00188     // already been written.
00189     void putData (AipsIO& os) const;
00190 
00191     // Read the data of a record.
00192     // This is used to read a subrecord, whose description has
00193     // already been read.
00194     void getData (AipsIO& os, uInt version);
00195 
00196     // Used by the RecordFieldPtr classes to attach in a type-safe way to the
00197     // correct field.
00198     // <group>
00199     void* get_pointer (Int whichField, DataType type) const;
00200     void* get_pointer (Int whichField, DataType type,
00201                        const String& recordType) const;
00202     // </group>
00203 
00204     // Merge a field from another record into this record.
00205     void mergeField (const RecordRep& other, Int whichFieldFromOther,
00206                      RecordInterface::DuplicatesFlag);
00207 
00208     // Merge all fields from the other record into this record.
00209     void merge (const RecordRep& other, RecordInterface::DuplicatesFlag);
00210     
00211     // Print a record.
00212     // Print the contents of the record.
00213     // Only the first <src>maxNrValues</src> of an array will be printed.
00214     // A value < 0 means the entire array.
00215     void print (std::ostream&,
00216                 Int maxNrValues = 25,
00217                 const String& indent="") const;
00218 
00219 protected:
00220     // Utility functions to avoid code duplication in the public member 
00221     // functions.
00222     // <group>
00223     void delete_myself (uInt nfields);
00224     void copy_other (const RecordRep& other);
00225     // </group>
00226 
00227     // Get the field number for a given name.
00228     virtual Int fieldNumber (const String& name) const;
00229 
00230     // Add the data pointer to the data block.
00231     // The block is extended when needed.
00232     void addDataPtr (void* ptr);
00233 
00234     // Remove a data pointer add the given index.
00235     void removeDataPtr (Int index);
00236 
00237     // Check if the shape of the data array matches the shape of a
00238     // fixed-shaped array in the description.
00239     void checkShape (DataType type, const IPosition& shape,
00240                      const void* value, const String& fieldName);
00241 
00242     // Add a field to the description.
00243     virtual void addFieldToDesc (const String& name, DataType type,
00244                                  const IPosition& shape, Bool fixedShape);
00245 
00246     // Remove a data field.
00247     virtual void removeData (Int whichField, void* ptr, void* vecptr);
00248 
00249     // Remove a field from the description.
00250     virtual void removeFieldFromDesc (Int whichField);
00251 
00252     // Create a data field for the given type and shape.
00253     // This can only handle scalars and arrays.
00254     void* createDataField (DataType type, const IPosition& shape);
00255 
00256     // Delete a data field.
00257     // This can only handle scalars and arrays.
00258     void deleteDataField (DataType type, void* ptr, void* vecptr);
00259 
00260     // Copy a data field.
00261     // This can only handle scalars and arrays.
00262     void copyDataField (DataType type, void* ptr, const void* that) const;
00263 
00264     // Print a data field.
00265     // This can only handle scalars and arrays.
00266     void printDataField (std::ostream& os, DataType type,
00267                          const String& indent, Int maxNrValues,
00268                          const void* ptr) const;
00269 
00270     // Put a data field.
00271     // This can only handle scalars and arrays.
00272     void putDataField (AipsIO& os, DataType type, const void* ptr) const;
00273 
00274     // Get a data field.
00275     // This can only handle scalars and arrays.
00276     void getDataField (AipsIO& os, DataType type, void* ptr);
00277 
00278     // Make an array for a scalar data field.
00279     // It shares the data, so a change in the data is reflected in the array.
00280     // It is used to be able to access a scalar as an 1D array.
00281     void makeDataVec (Int whichField, DataType type);
00282 
00283     // Get a Scalar/ArrayKeywordSet object as a Record.
00284     // (type 0 = ScalarKeywordSet;  type 1 = ArrayKeywordSet).
00285     void getKeySet (AipsIO& os, uInt version, uInt type);
00286 
00287     // Get the description of a keyword set as a RecordDesc.
00288     void getKeyDesc (AipsIO& os, RecordDesc& desc);
00289 
00290     // Get the scalar values of a keyword set.
00291     void getScalarKeys (AipsIO& os);
00292 
00293     // Get the array values of a keyword set.
00294     void getArrayKeys (AipsIO& os);
00295 
00296 
00297     // Holds the structure of this Record.
00298     RecordDesc   desc_p;
00299     // Pointers to data values.
00300     Block<void*> data_p;
00301     // Pointers to a vector of a scalar (to access a scalar as an array).
00302     Block<void*> datavec_p;
00303     // #Entries used in data_p.
00304     uInt         nused_p;
00305 };
00306 
00307 
00308 inline const RecordDesc& RecordRep::description() const
00309 {
00310     return desc_p;
00311 }
00312 
00313 inline const String& RecordRep::comment (Int whichField) const
00314 {
00315     return desc_p.comment (whichField);
00316 }
00317 
00318 inline void RecordRep::setComment (Int whichField, const String& comment)
00319 {
00320     desc_p.setComment (whichField, comment);
00321 }
00322 
00323 inline void RecordRep::renameField (const String& newName, Int whichField)
00324 {
00325     desc_p.renameField (newName, whichField);
00326 }
00327 
00328 
00329 
00330 } //# NAMESPACE CASA - END
00331 
00332 #endif