casacore
Loading...
Searching...
No Matches
Record.h
Go to the documentation of this file.
1//# Record.h: A hierarchical collection of named fields of various types
2//# Copyright (C) 1995,1996,1997,1998,2000,2001
3//# Associated Universities, Inc. Washington DC, USA.
4//#
5//# This library is free software; you can redistribute it and/or modify it
6//# under the terms of the GNU Library General Public License as published by
7//# the Free Software Foundation; either version 2 of the License, or (at your
8//# option) any later version.
9//#
10//# This library is distributed in the hope that it will be useful, but WITHOUT
11//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13//# License for more details.
14//#
15//# You should have received a copy of the GNU Library General Public License
16//# along with this library; if not, write to the Free Software Foundation,
17//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18//#
19//# Correspondence concerning AIPS++ should be addressed as follows:
20//# Internet email: aips2-request@nrao.edu.
21//# Postal address: AIPS++ Project Office
22//# National Radio Astronomy Observatory
23//# 520 Edgemont Road
24//# Charlottesville, VA 22903-2475 USA
25//#
26//#
27//# $Id$
28
29
30#ifndef CASA_RECORD_H
31#define CASA_RECORD_H
32
33//# Includes
34#include <casacore/casa/aips.h>
35#include <casacore/casa/Arrays/ArrayFwd.h>
36#include <casacore/casa/Containers/RecordInterface.h>
37#include <casacore/casa/Containers/RecordRep.h>
38#include <casacore/casa/Containers/RecordDesc.h>
39#include <casacore/casa/Utilities/COWPtr.h>
40
41namespace casacore { //# NAMESPACE CASACORE - BEGIN
42
43//# Forward Declarations
44class IPosition;
45class AipsIO;
46
47
48// <summary>
49// A hierarchical collection of named fields of various types
50// </summary>
51
52// <use visibility=export>
53// <reviewed reviewer="Mark Wieringa" date="1996/04/15" tests="tRecord">
54// </reviewed>
55
56// <prerequisite>
57// <li> <linkto class="RecordDesc">RecordDesc</linkto>.
58// <li> <linkto class="RecordInterface">RecordInterface</linkto>.
59// <li> <linkto class="RecordFieldPtr">RecordFieldPtr</linkto>.
60// </prerequisite>
61
62// <etymology>
63// ``Record'' is a widely used term in both programming languages and data
64// structures to denote an imhogeneous set of fields. An alternative would
65// have been to name it <em>struct</em>ure, which would have perhaps been
66// a clearer name for C++ programmers.
67// </etymology>
68
69// <synopsis>
70// Class <linkto class=RecordInterface>RecordInterface</linkto> decribes
71// the fundamental properties of records.
72// <br>
73// The Record class is a particular type of a record class.
74// The fields in Record may be of scalar type, array type, or a Record.
75// The types are chosen to be compatible with the native
76// types of the Table system, viz: Bool, uChar, Short, Int, uInt, float,
77// double, Complex, DComplex, String.
78// Arrays of all these types are also available.
79// Note that a Record is not a space-efficient way of storing small objects.
80// <p>
81// The structure of a Record is defined by the <linkto class="RecordDesc">
82// RecordDesc</linkto> class. The structure of the Record can be defined at
83// construction time. It can thereafter be restructured. This has the
84// effect, however, that any existing RecordFieldPtr objects become
85// invalid (using the <linkto file="Notice.h">Notice</linkto> classes).
86// <br>
87// It is possible to add or remove fields once a Record is constructed.
88// However, this is not possible when the Record is constructed with a
89// fixed structure (i.e. with the fixedStructure flag set).
90// <p>
91// A Record is an hierarchical structure, because it can have fields
92// containing Record's (as layed out in the RecordDesc). A subrecord
93// has a variable structure, when its RecordDesc is empty (i.e. contains
94// no fields). It is fixed when its RecordDesc contains fields.
95// <p>
96// A Record may be assigned to another only if they conform; that is if their
97// fields have the identical type in the identical order.
98// The field names do not need to be identical however, only the types.
99// That is, the structure needs to be identical, but
100// not the labels. Note that field order is significant,
101// <src>[ifield(type=Int),ffield(type=float)]</src>
102// is not the same as <src>[ffield(type=float),ifield(type=Int)]</src>
103// <br>
104// Conformance is checked recursively for fixed subrecords. That is, a
105// variable structured subrecord is not checked, because any record
106// can be assigned to it. A fixed structured subrecord has to
107// conform the corresponding subrecord in the source.
108// <p>
109// Record uses copy-on-write semantics. This means that when a Record
110// is copied, only the pointer to the underlying RecordRep object is copied.
111// Only when the Record gets changed (i.e. when a non-const Record member
112// function is called), the RecordRep object is copied.
113// This results in a cheap copy behaviour.
114// </synopsis>
115
116// <example>
117// Suppose we wanted to create a records that describe the favorite example
118// of the OO world - an employee:
119// <srcBlock>
120// RecordDesc employeeDesc;
121// employeeDesc.addField ("name", TpString);
122// employeeDesc.addField ("salary", TpDouble);
123// </srcBlock>
124// The above creates the description (structure) for some record objects.
125// <srcBlock>
126// Record employeeA(employeeDesc);
127// Record employeeB(employeeDesc, False);
128// </srcBlock>
129// And these two lines create Record objects which share this common structure.
130// The first Record has a fixed structure, the 2nd variable.
131// <srcBlock>
132// RecordFieldPtr<String> nameA(employeeA, 0);
133// RecordFieldPtr<String> nameB(employeeB, 0);
134// RecordFieldPtr<double> salaryA(employeeA, 1);
135// RecordFieldPtr<double> salaryB(employeeB, "salary");
136// </srcBlock>
137// This shows how we can get access to the individual fields. The fields are
138// fundamentally identified by number, but the number can be looked up through
139// the use of the fieldNumber member function.
140// <srcBlock>
141// nameA.define ("Tim");
142// nameB.define ("Brian");
143// salaryA.define (1.0e+8);
144// salaryB.define (1.0 / *salaryA);
145// </srcBlock>
146// Once obtained, the fields are readily manipulated, as shown above. Note
147// that the field values are obtained through the dereference (<src>*</src>)
148// operator. This is to identify that the field objects are <em>pointers</em>
149// to the values in the underlying Record; that is
150// <srcBlock>
151// salaryA = salaryB;
152// *salaryA = *salaryB;
153// </srcBlock>
154// Do very different things; the first line is a pointer copy; salaryA and
155// salaryB now point to the same field in salaryB. The second line is a value
156// copy.
157//
158// Whole records can be copied as long as their structures are compatible, so
159// that <src> employeeA = employeeB </src> is a legal statement. However, if
160// the structure is changed, assignment is no longer possible, and all of the
161// field pointers are invalidated:
162// <srcBlock>
163// employeeB.define ("age", (Int)40);
164// employeeA = employeeB; // exception - no longer conformant
165// </srcBlock>
166// </example>
167
168// <motivation>
169// Collections of data with different types are frequently needed.
170// Record makes it possible to hold such data in a flexible way.
171// </motivation>
172
173// <todo asof="1996/03/12">
174// <li> A record reference class, which contains some fields from another
175// record, would likely be useful. This would be analagous to a
176// subarray sliced from an existing array.
177// </todo>
178
179
181{
182friend class RecordRep;
183
184public:
185 // Create a record with no fields.
186 // The record has a variable structure.
188
189 // Create a record with no fields.
190 // The type determines if the record has a fixed or variable structure.
191 // The callback function is called when a field is added to the Record.
192 // That function can check the name and of data type of the new field
193 // (for instance, the Table system uses it to ensure that table columns
194 // and keywords have different names).
196 CheckFieldFunction* = 0, const void* checkArgument = 0);
197
198 // Create a record with the given description. If it is not possible to
199 // create all fields (for example, if a field with an unsupported data
200 // type is requested), an exception is thrown.
201 // The type determines if the record has a fixed or variable structure.
202 // All fields are checked by the field checking function (if defined)
203 // (for instance, the Table system uses it to ensure that table columns
204 // and keywords have different names).
206 CheckFieldFunction* = 0, const void* checkArgument = 0);
207
208 // Create a copy of other using copy semantics.
209 Record (const Record& other);
210
211 // Create a Record from another type of record using copy semantics.
212 // Subrecords are also converted to a Record.
213 Record (const RecordInterface& other);
214
215 // Copy the data in the other record to this record.
216 // It can operate in 2 ways depending on the Record structure flag.
217 // <ul>
218 // <li> For variable structured records the existing fields are
219 // thrown away and replaced by the new fields.
220 // This means that RecordFieldPtr's using this record get invalidated.
221 // Because copy-on-write semantics are used, this kind of
222 // assignment is a very efficient operation.
223 // <li> For fixed structured records the existing values are replaced
224 // by the new values. This means that RecordFieldPtr's using this
225 // record remain valid.
226 // The structure of the other record has to conform this record
227 // or this record has to be empty, otherwise an exception is thrown.
228 // This assignment is less efficient, because it has to check the
229 // conformance and because each value has to be copied.
230 // </ul>
231 // <note role=warning>
232 // Attributes like fixed structure flag and check function will not
233 // be copied.
234 // </note>
235 Record& operator= (const Record& other);
236
237 // Release resources associated with this object.
238 virtual ~Record();
239
240 // Make a copy of this object.
241 virtual RecordInterface* clone() const;
242
243 // Assign that RecordInterface object to this one.
244 // Unlike <src>operator=</src> it copies all data in the derived
245 // class.
246 virtual void assign (const RecordInterface& that);
247
248 // Get the comment for this field.
249 virtual const String& comment (const RecordFieldId&) const;
250
251 // Set the comment for this field.
252 virtual void setComment (const RecordFieldId&, const String& comment);
253
254 // Describes the current structure of this Record.
255 const RecordDesc& description() const;
256
257 // Change the structure of this Record to contain the fields in
258 // newDescription. After calling restructure, <src>description() ==
259 // newDescription</src>. Any existing RecordFieldPtr objects are
260 // invalidated (their <src>isAttached()</src> members return False) after
261 // this call.
262 // <br>When the new description contains subrecords, those subrecords
263 // will be restructured if <src>recursive=True</src> is given.
264 // Otherwise the subrecord is a variable empty record.
265 // Subrecords will be variable if their description is empty (i.e. does
266 // not contain any field), otherwise they are fixed. The 2nd form of
267 // the <src>restructure</src> function will overwrite those implicit
268 // record types with the given record type. The new type will also
269 // be given to this top record.
270 // <br>Restructuring is not possible and an exception is thrown
271 // if the Record has a fixed structure.
272 virtual void restructure (const RecordDesc& newDescription,
273 Bool recursive = True);
274
275 // Returns True if this and other have the same RecordDesc, other
276 // than different names for the fields. That is, the number, type and the
277 // order of the fields must be identical (recursively for fixed
278 // structured sub-Records in this).
279 // <note role=caution>
280 // <src>thisRecord.conform(thatRecord) == True</src> does not imply
281 // <br><src>thatRecord.conform(thisRecord) == True</src>, because
282 // a variable record in one conforms a fixed record in that, but
283 // not vice-versa.
284 // </note>
285 Bool conform (const Record& other) const;
286
287 // How many fields does this structure have? A convenient synonym for
288 // <src>description().nfields()</src>.
289 virtual uInt nfields() const;
290
291 // Get the field number from the field name.
292 // -1 is returned if the field name is unknown.
293 virtual Int fieldNumber (const String& fieldName) const;
294
295 // Get the data type of this field.
296 virtual DataType type (Int whichField) const;
297
298 // Remove a field from the record.
299 // <note role=caution>
300 // Removing a field means that the field number of the fields following
301 // it will be decremented. Only the RecordFieldPtr's
302 // pointing to the removed field will be invalidated.
303 // </note>
305
306 // Rename the given field.
307 void renameField (const String& newName, const RecordFieldId&);
308
309 // Define a value for the given field containing a subrecord.
310 // When the field is unknown, it will be added to the record.
311 // The second version is meant for any type of record (e.g. Record,
312 // TableRecord, GlishRecord). It is converted to a Record using the
313 // Record constructor taking a RecordInterface object.
314 // <group>
317 virtual void defineRecord (const RecordFieldId&,
318 const RecordInterface& value,
320 // </group>
321
322 // Get the subrecord from the given field.
323 // <note>
324 // The non-const version has a different name to prevent that the
325 // copy-on-write mechanism makes a copy when not necessary.
326 // </note>
327 // <group>
328 const Record& subRecord (const RecordFieldId&) const;
330 virtual const RecordInterface& asRecord (const RecordFieldId&) const;
332 // </group>
333
334 // Get or define the value as a ValueHolder.
335 // This is useful to pass around a value of any supported type.
336 // <group>
339 const ValueHolder&);
340 // </group>
341
342 // Merge a field from another record into this record.
343 // The DuplicatesFlag (as described in
344 // <linkto class=RecordInterface>RecordInterface</linkto>) determines
345 // what will be done in case the field name already exists.
346 void mergeField (const Record& other, const RecordFieldId&,
348
349 // Merge all fields from the other record into this record.
350 // The DuplicatesFlag (as described in
351 // <linkto class=RecordInterface>RecordInterface</linkto>) determines
352 // what will be done in case a field name already exists.
353 // An exception will be thrown if other is the same as this
354 // (i.e. if merging the record itself).
356
357 // Write the Record to an output stream.
358 friend AipsIO& operator<< (AipsIO& os, const Record& rec);
359
360 // Read the Record from an input stream.
361 friend AipsIO& operator>> (AipsIO& os, Record& rec);
362
363 // Write the Record to an output stream.
364 // This is used to write a subrecord, whose description has
365 // not been written.
366 void putRecord (AipsIO& os) const;
367
368 // Read the Record from an input stream.
369 // This is used to read a subrecord, whose description has
370 // not been read.
371 void getRecord (AipsIO& os);
372
373 // Put the data of a record.
374 // This is used to write a subrecord, whose description has
375 // already been written.
376 void putData (AipsIO& os) const;
377
378 // Read the data of a record.
379 // This is used to read a subrecord, whose description has
380 // already been read.
381 void getData (AipsIO& os, uInt version);
382
383 // Make a unique record representation
384 // (to do copy-on-write in RecordFieldPtr).
385 virtual void makeUnique();
386
387 // Print the contents of the record.
388 // Only the first <src>maxNrValues</src> of an array will be printed.
389 // A value < 0 means the entire array.
390 virtual void print (std::ostream&,
391 Int maxNrValues = 25,
392 const String& indent="") const;
393
394
395protected:
396 // Used by the RecordField classes to attach in a type-safe way to the
397 // correct field.
398 // <group>
399 virtual void* get_pointer (Int whichField, DataType type) const;
400 virtual void* get_pointer (Int whichField, DataType type,
401 const String& recordType) const;
402 // </group>
403
404 // Return a const reference to the underlying RecordRep.
405 const RecordRep& ref() const;
406
407 // Return a non-const reference to the underlying RecordRep.
408 // When needed, the RecordRep will be copied and all RecordField
409 // objects will be notified.
411
412 // Add a field to the record.
413 virtual void addDataField (const String& name, DataType type,
414 const IPosition& shape, Bool fixedShape,
415 const void* value);
416
417 // Define a value in the given field.
418 virtual void defineDataField (Int whichField, DataType type,
419 const void* value);
420
421private:
422 // Get the description of this record.
423 virtual RecordDesc getDescription() const;
424
425 // Create Record as a subrecord.
426 // When the description is empty, the record has a variable structure.
427 // Otherwise it is fixed.
428 // <group>
431 // </group>
432
433 // The Record representation.
435 // The parent Record.
437};
438
439
440
441inline const RecordRep& Record::ref() const
442{
443 return rep_p.ref();
444}
445inline const RecordDesc& Record::description() const
446{
447 return ref().description();
448}
449
450inline Bool Record::conform (const Record& other) const
451{
452 return ref().conform (other.ref());
453}
454
455inline AipsIO& operator<< (AipsIO& os, const Record& rec)
456{
457 rec.putRecord (os);
458 return os;
459}
460inline void Record::putData (AipsIO& os) const
461{
462 ref().putData (os);
463}
464
465inline AipsIO& operator>> (AipsIO& os, Record& rec)
466{
467 rec.getRecord (os);
468 return os;
469}
470inline void Record::getData (AipsIO& os, uInt version)
471{
472 rwRef().getData (os, version);
473}
474
475
476
477
478} //# NAMESPACE CASACORE - END
479
480#endif
RecordType & recordType()
Give access to the RecordType flag (write-access is needed when a record is read back).
String name(const RecordFieldId &) const
Get the name of this field.
IPosition shape(const RecordFieldId &) const
Get the actual shape of this field.
RecordType
Define the flag telling if a Record has a fixed or variable structure.
@ Variable
Record has a variable structure; after Record creation fields can be added or removed at will.
@ Fixed
Record has a fixed structure; that is, no fields can be added or removed once the Record is created.
Bool CheckFieldFunction(const String &fieldName, DataType dataType, const void *extraArgument, String &message)
Define the signature of the add callback function.
DuplicatesFlag
Define the Duplicates flag for the function merge in the various record classes.
@ ThrowOnDuplicates
Throw an exception.
Bool conform(const RecordRep &other) const
Returns True if this and other have the same RecordDesc, other than different names for the fields.
const RecordDesc & description() const
Describes the current structure of this Record.
Definition RecordRep.h:308
void getData(AipsIO &os, uInt version)
Read the data of a record.
void putData(AipsIO &os) const
Put the data of a record.
const Record & subRecord(const RecordFieldId &) const
Get the subrecord from the given field.
RecordRep * parent_p
The parent Record.
Definition Record.h:436
virtual void * get_pointer(Int whichField, DataType type) const
Used by the RecordField classes to attach in a type-safe way to the correct field.
virtual void makeUnique()
Make a unique record representation (to do copy-on-write in RecordFieldPtr).
void merge(const Record &other, DuplicatesFlag=ThrowOnDuplicates)
Merge all fields from the other record into this record.
void renameField(const String &newName, const RecordFieldId &)
Rename the given field.
RecordRep & rwRef()
Return a non-const reference to the underlying RecordRep.
virtual void defineRecord(const RecordFieldId &, const RecordInterface &value, RecordType=Variable)
Bool conform(const Record &other) const
Returns True if this and other have the same RecordDesc, other than different names for the fields.
Definition Record.h:450
virtual void setComment(const RecordFieldId &, const String &comment)
Set the comment for this field.
friend AipsIO & operator<<(AipsIO &os, const Record &rec)
Write the Record to an output stream.
Definition Record.h:455
void defineRecord(const RecordFieldId &, const Record &value, RecordType type=Variable)
Define a value for the given field containing a subrecord.
virtual ValueHolder asValueHolder(const RecordFieldId &) const
Get or define the value as a ValueHolder.
Record(const RecordDesc &description, RecordType type=Fixed, CheckFieldFunction *=0, const void *checkArgument=0)
Create a record with the given description.
void getData(AipsIO &os, uInt version)
Read the data of a record.
Definition Record.h:470
virtual void * get_pointer(Int whichField, DataType type, const String &recordType) const
virtual RecordInterface * clone() const
Make a copy of this object.
virtual void defineFromValueHolder(const RecordFieldId &, const ValueHolder &)
Record & rwSubRecord(const RecordFieldId &)
void getRecord(AipsIO &os)
Read the Record from an input stream.
Record(const RecordInterface &other)
Create a Record from another type of record using copy semantics.
friend AipsIO & operator>>(AipsIO &os, Record &rec)
Read the Record from an input stream.
Definition Record.h:465
virtual void restructure(const RecordDesc &newDescription, Bool recursive=True)
Change the structure of this Record to contain the fields in newDescription.
void mergeField(const Record &other, const RecordFieldId &, DuplicatesFlag=ThrowOnDuplicates)
Merge a field from another record into this record.
Record(RecordRep *parent, RecordType type)
virtual const String & comment(const RecordFieldId &) const
Get the comment for this field.
virtual void addDataField(const String &name, DataType type, const IPosition &shape, Bool fixedShape, const void *value)
Add a field to the record.
COWPtr< RecordRep > rep_p
The Record representation.
Definition Record.h:434
virtual const RecordInterface & asRecord(const RecordFieldId &) const
Record & operator=(const Record &other)
Copy the data in the other record to this record.
virtual uInt nfields() const
How many fields does this structure have? A convenient synonym for description().nfields().
virtual Int fieldNumber(const String &fieldName) const
Get the field number from the field name.
virtual ~Record()
Release resources associated with this object.
void removeField(const RecordFieldId &)
Remove a field from the record.
virtual DataType type(Int whichField) const
Get the data type of this field.
Record()
Create a record with no fields.
virtual void assign(const RecordInterface &that)
Assign that RecordInterface object to this one.
Record(RecordRep *parent, const RecordDesc &description)
Create Record as a subrecord.
virtual RecordDesc getDescription() const
Get the description of this record.
virtual RecordInterface & asrwRecord(const RecordFieldId &)
Record(RecordType type, CheckFieldFunction *=0, const void *checkArgument=0)
Create a record with no fields.
virtual void defineDataField(Int whichField, DataType type, const void *value)
Define a value in the given field.
void putRecord(AipsIO &os) const
Write the Record to an output stream.
void putData(AipsIO &os) const
Put the data of a record.
Definition Record.h:460
const RecordDesc & description() const
Describes the current structure of this Record.
Definition Record.h:445
virtual void print(std::ostream &, Int maxNrValues=25, const String &indent="") const
Print the contents of the record.
const RecordRep & ref() const
Return a const reference to the underlying RecordRep.
Definition Record.h:441
Record(const Record &other)
Create a copy of other using copy semantics.
String: the storage and methods of handling collections of characters.
Definition String.h:225
this file contains all the compiler specific defines
Definition mainpage.dox:28
AipsIO & operator>>(AipsIO &os, Record &rec)
Definition Record.h:465
ostream & operator<<(ostream &os, const IComplex &)
Show on ostream.
unsigned int uInt
Definition aipstype.h:51
int Int
Definition aipstype.h:50
bool Bool
Define the standard types used by Casacore.
Definition aipstype.h:42
LatticeExprNode value(const LatticeExprNode &expr)
This function returns the value of the expression without a mask.
const Bool True
Definition aipstype.h:43