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