casacore
Loading...
Searching...
No Matches
RecordDesc.h
Go to the documentation of this file.
1// # RecordDesc.h: Description of the fields in a record object
2// # Copyright (C) 1995,1996,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#ifndef CASA_RECORDDESC_H
27#define CASA_RECORDDESC_H
28
29// # Includes
30#include <casacore/casa/aips.h>
31#include <casacore/casa/Containers/RecordDescRep.h>
32#include <casacore/casa/Containers/RecordInterface.h>
33#include <casacore/casa/Utilities/COWPtr.h>
34#include <casacore/casa/iosfwd.h>
35
36namespace casacore { // # NAMESPACE CASACORE - BEGIN
37
38// # Forward Declarations
39class AipsIO;
40
41// <summary>
42// Description of the fields in a record object
43// </summary>
44
45// <use visibility=export>
46// <reviewed reviewer="Mark Wieringa" date="1996/04/15" tests="tRecordDesc">
47// </reviewed>
48
49// <prerequisite>
50// <li> <linkto group="DataType.h#DataType">DataType</linkto>
51// <li> <linkto class="Record">Record</linkto>
52// </prerequisite>
53//
54// <etymology>
55// RecordStructure would perhaps have been the clearest possible name. However
56// it was decided to name it ``RecordDesc'' to use a compatible naming
57// convention with other classes in the system, such as TableDesc. This class
58// <em>Desc</em>ribes the structure of a Record.
59// </etymology>
60//
61// <synopsis>
62// RecordDesc describes the structure of <linkto class="Record">Record</linkto>
63// objects. A Record consists of a number of fields. A RecordDesc describes
64// those fields by assigning to each one:
65// <ul>
66// <li> A name for the field.
67// <li> A type from the <linkto group="DataType.h#DataType">DataType</linkto>
68// enum.
69// <li> A shape if the field is an array.
70// <li> A RecordDesc if the field is itself a Record (the Record is an
71// hierarchical structure).
72// </ul>
73// Only one field with a given name is allowed (although fields in subrecords
74// may have the same name as a field in a parent or child Record).
75//
76// Field indices are zero relative, i.e. they range from 0 to
77// <src>nfields()-1</src>.
78// </synopsis>
79//
80// <example>
81// See the example in the description of the
82// <linkto class="Record:example1">Record</linkto> class.
83// </example>
84//
85// <motivation>
86// It is useful to be able to create many new objects with the same structure
87// as some other, without necessarily cloning it by copying all the values.
88// A ``Description'' type is necessary to do this (e.g., shape for an Array).
89// </motivation>
90//
91//
92// <todo asof="1995/06/01">
93// <li> Should the strategy wrt. field names be changed (not used in
94// field description equality, must be unique at a given level?).
95// <li> Perhaps we should be able to more conveniently change the description
96// of an existing field.
97// </todo>
98
100 public:
101 // Writes/reads the RecordDesc to/from an output stream.
102 // <group name=io>
103 friend ostream& operator<<(ostream& os, const RecordDesc& desc);
104 friend AipsIO& operator<<(AipsIO& os, const RecordDesc& desc);
105 friend AipsIO& operator>>(AipsIO& os, RecordDesc& desc);
106 // </group>
107
108 // Create a description with no fields.
109 RecordDesc();
110
111 // Create a description which is a copy of other.
112 RecordDesc(const RecordDesc& other);
113
114 // Replace this description with other.
115 RecordDesc& operator=(const RecordDesc& other);
116
117 ~RecordDesc();
118
119 // Add scalar, array, sub-record, or table field.
120 // If of array type, the shape is set to [-1], which indicates a
121 // variable sized array.
122 // If of sub-record type, the sub-record is free format.
123 // Returns the number of fields in the description.
124 uInt addField(const String& fieldName, DataType dataType);
125
126 // Add an array field of the indicated type. The DataType is promoted
127 // from a scalar type to an array type if necessary, e.g.,
128 // <src>TpInt ->TpArrayInt</src>. Returns the number of fields in
129 // the description.
130 // A shape of [-1] indicates a variable shape.
131 uInt addField(const String& fieldName, DataType scalarOrArrayType, const IPosition& shape);
132
133 // Add a Record field to the description. This allows hierarchical
134 // descriptions to be developed. Returns the number of fields in the
135 // description.
136 uInt addField(const String& fieldName, const RecordDesc& subDesc);
137
138 // Add a Table field to the description. The Table description has the
139 // given name. Returns the number of fields in the description.
140 // <br>
141 // When a table is put in a record field, it is checked if the name
142 // of its description matches this name. If this name is empty, it
143 // matches any table description.
144 // <note role=warning>
145 // Note that not all record types are able to instantiate a table field.
146 // E.g. <linkto class=TableRecord>TableRecord</linkto> can instantiate
147 // it, while <linkto class=Record>Record</linkto> cannot and throws an
148 // exception when a record description containing a table field is used.
149 // </note>
150 uInt addTable(const String& fieldName, const String& tableDescName);
151
152 // Get the comment for this field.
153 const String& comment(Int whichField) const;
154
155 // Set the comment for this field.
156 void setComment(Int whichField, const String& comment);
157
158 // Set the shape for this field.
159 // An exception will be thrown if the field is no array.
160 void setShape(Int whichField, const IPosition& shape);
161
162 // Merge a single field from other. If allowDuplicates is True, silently
163 // throw away fields if one with the same name and type already exists,
164 // otherwise an exception is thrown. Conflicting types always cause an
165 // exception. Returns the number of fields in the description.
167 const RecordDesc& other, Int whichFieldFromOther,
168 RecordInterface::DuplicatesFlag DuplicateAction = RecordInterface::ThrowOnDuplicates);
169
170 // Add all the fields from another RecordDesc to the current objects.
171 // It returns the new number of fields.
172 uInt merge(const RecordDesc& other,
173 RecordInterface::DuplicatesFlag DuplicateAction = RecordInterface::ThrowOnDuplicates);
174
175 // Remove the given field from the description.
176 // It returns the new number of fields.
177 uInt removeField(Int whichField);
178
179 // Rename the given field.
180 void renameField(const String& newName, Int whichField);
181
182 // Returns the index of the field named fieldName. Returns -1 if fieldName
183 // does not exist.
184 Int fieldNumber(const String& fieldName) const;
185
186 // Number of fields in the description.
187 uInt nfields() const;
188
189 // What is the type of the given field. Returns TpRecord if the field is
190 // a sub-Record.
191 DataType type(Int whichField) const;
192
193 // What is the name of the given field.
194 const String& name(Int whichField) const;
195
196 // Create a name for a field defined by index as *i (similar to glish).
197 // It takes care that the resulting name is unique by adding a suffix _j
198 // when needed.
199 String makeName(Int whichField) const;
200
201 // Make the given name unique by adding a suffix _j when needed.
202 // j is the minimal number needed to make it unique.
203 String uniqueName(const String& name) const;
204
205 // Returns True if whichField is an array.
206 Bool isArray(Int whichField) const;
207
208 // Returns True if whichField is a scalar.
209 Bool isScalar(Int whichField) const;
210
211 // Returns True if whichField is a sub-record.
212 Bool isSubRecord(Int whichField) const;
213
214 // Returns True if whichField is a table.
215 Bool isTable(Int whichField) const;
216
217 // What is the shape of the given field. Returns [1] if the field is a
218 // scalar, table or, sub-record, [-1] if it is a variable length array,
219 // and the actual shape for a fixed length array.
220 const IPosition& shape(Int whichField) const;
221
222 // What is the name of the table description.
223 // Returns an empty string when the field is no table.
224 const String& tableDescName(Int whichField) const;
225
226 // If whichField is a sub-record return its description.
227 // Otherwise an exception is thrown.
228 // The non-const version is named differently to prevent accidental
229 // use of the non-const version.
230 // <group>
231 const RecordDesc& subRecord(Int whichField) const;
232 RecordDesc& rwSubRecord(Int whichField);
233 // </group>
234
235 // This and other compare equal if the field types and shapes are identical
236 // (recursively if there are described sub-records).
237 // The field names are not used.
238 // <br>Use function isEqual if names are important, but order is not.
239 // <group>
240 Bool operator==(const RecordDesc& other) const;
241 Bool operator!=(const RecordDesc& other) const;
242 // </group>
243
244 // Test if this description conforms the other.
245 // It is NOT doing it recursively, thus is does not check if
246 // sub-records are conforming.
247 // <br>This is used by Record, to see if another record can be assigned
248 // to this record.
249 Bool conform(const RecordDesc& other) const;
250
251 // Test if this description equals another one.
252 // It is equal if the number of fields is equal and all field names in
253 // this description occur in the other too. The order of the fields
254 // is not important.
255 // <br>The flag equalDataTypes is set to True if the data types
256 // of all fields match.
257 // <br>Use function operator== if order and types are important,
258 // but names are not.
259 Bool isEqual(const RecordDesc& other, Bool& equalDataTypes) const;
260
261 // Test if this description is a subset of another one.
262 // It is similar to isEqual above.
263 Bool isSubset(const RecordDesc& other, Bool& equalDataTypes) const;
264
265 // Test if this description is a strict subset of another one, thus
266 // if it is a subset and not equal.
267 Bool isStrictSubset(const RecordDesc& other, Bool& equalDataTypes) const;
268
269 // Test if this description is a superset of another one.
270 Bool isSuperset(const RecordDesc& other, Bool& equalDataTypes) const;
271
272 // Test if this description is a strict superset of another one, thus
273 // if it is a superset and not equal.
274 Bool isStrictSuperset(const RecordDesc& other, Bool& equalDataTypes) const;
275
276 // Test if the set of field names in this and other record description
277 // is disjoint (i.e. if they do not share names).
278 Bool isDisjoint(const RecordDesc& other) const;
279
280 private:
281 // Writes/reads the RecordDesc to/from an output stream.
282 // <group>
283 ostream& put(ostream& os) const;
284 AipsIO& put(AipsIO& os) const;
286 // </group>
287
288 // Use a copy-on-write pointer to the RecordDescRep.
290};
291
293
294inline RecordDesc::RecordDesc(const RecordDesc& other) : desc_p(other.desc_p) {}
295
297 if (this != &other) {
298 desc_p = other.desc_p;
299 }
300 return *this;
301}
302
304
305inline uInt RecordDesc::addField(const String& fieldName, DataType dataType) {
306 return desc_p.rwRef().addField(fieldName, dataType);
307}
308
309inline uInt RecordDesc::addField(const String& fieldName, DataType scalarOrArrayType,
310 const IPosition& shape) {
311 return desc_p.rwRef().addArray(fieldName, scalarOrArrayType, shape);
312}
313
314inline uInt RecordDesc::addField(const String& fieldName, const RecordDesc& subDesc) {
315 return desc_p.rwRef().addRecord(fieldName, subDesc);
316}
317
318inline uInt RecordDesc::addTable(const String& fieldName, const String& tableDescName) {
319 return desc_p.rwRef().addTable(fieldName, tableDescName);
320}
321
322inline const String& RecordDesc::comment(Int whichField) const {
323 return desc_p.ref().comment(whichField);
324}
325
326inline void RecordDesc::setComment(Int whichField, const String& comment) {
327 desc_p.rwRef().setComment(whichField, comment);
328}
329
330inline void RecordDesc::setShape(Int whichField, const IPosition& shape) {
331 desc_p.rwRef().setShape(whichField, shape);
332}
333
334inline uInt RecordDesc::mergeField(const RecordDesc& other, Int whichFieldFromOther,
335 RecordInterface::DuplicatesFlag duplicateAction) {
336 return desc_p.rwRef().mergeField(other.desc_p.ref(), whichFieldFromOther, duplicateAction);
337}
338
340 RecordInterface::DuplicatesFlag duplicateAction) {
341 return desc_p.rwRef().merge(other.desc_p.ref(), duplicateAction);
342}
343
344inline uInt RecordDesc::removeField(Int whichField) {
345 return desc_p.rwRef().removeField(whichField);
346}
347
348inline void RecordDesc::renameField(const String& newName, Int whichField) {
349 desc_p.rwRef().renameField(newName, whichField);
350}
351
352inline Int RecordDesc::fieldNumber(const String& fieldName) const {
353 return desc_p.ref().fieldNumber(fieldName);
354}
355
356inline uInt RecordDesc::nfields() const { return desc_p.ref().nfields(); }
357
358inline DataType RecordDesc::type(Int whichField) const { return desc_p.ref().type(whichField); }
359
361 return desc_p.ref().uniqueName(name);
362}
363
364inline String RecordDesc::makeName(Int whichField) const {
365 return desc_p.ref().makeName(whichField);
366}
367
368inline const String& RecordDesc::name(Int whichField) const {
369 return desc_p.ref().name(whichField);
370}
371
372inline Bool RecordDesc::isArray(Int whichField) const { return desc_p.ref().isArray(whichField); }
373
374inline Bool RecordDesc::isScalar(Int whichField) const { return desc_p.ref().isScalar(whichField); }
375
376inline Bool RecordDesc::isSubRecord(Int whichField) const {
377 return desc_p.ref().isSubRecord(whichField);
378}
379
380inline Bool RecordDesc::isTable(Int whichField) const { return desc_p.ref().isTable(whichField); }
381
382inline const IPosition& RecordDesc::shape(Int whichField) const {
383 return desc_p.ref().shape(whichField);
384}
385
386inline const String& RecordDesc::tableDescName(Int whichField) const {
387 return desc_p.ref().tableDescName(whichField);
388}
389
390inline const RecordDesc& RecordDesc::subRecord(Int whichField) const {
391 return desc_p.ref().subRecord(whichField);
392}
393
395 return desc_p.rwRef().subRecord(whichField);
396}
397
398inline Bool RecordDesc::operator==(const RecordDesc& other) const {
399 return desc_p.ref() == other.desc_p.ref();
400}
401
402inline Bool RecordDesc::operator!=(const RecordDesc& other) const {
403 return desc_p.ref() != other.desc_p.ref();
404}
405inline Bool RecordDesc::conform(const RecordDesc& other) const {
406 return desc_p.ref().conform(other.desc_p.ref());
407}
408
409inline Bool RecordDesc::isEqual(const RecordDesc& other, Bool& equalDataTypes) const {
410 return desc_p.ref().isEqual(other.desc_p.ref(), equalDataTypes);
411}
412inline Bool RecordDesc::isSubset(const RecordDesc& other, Bool& equalDataTypes) const {
413 return desc_p.ref().isSubset(other.desc_p.ref(), equalDataTypes);
414}
415inline Bool RecordDesc::isStrictSubset(const RecordDesc& other, Bool& equalDataTypes) const {
416 return desc_p.ref().isStrictSubset(other.desc_p.ref(), equalDataTypes);
417}
418inline Bool RecordDesc::isSuperset(const RecordDesc& other, Bool& equalDataTypes) const {
419 return other.desc_p.ref().isSubset(desc_p.ref(), equalDataTypes);
420}
421inline Bool RecordDesc::isStrictSuperset(const RecordDesc& other, Bool& equalDataTypes) const {
422 return other.desc_p.ref().isStrictSubset(desc_p.ref(), equalDataTypes);
423}
424inline Bool RecordDesc::isDisjoint(const RecordDesc& other) const {
425 return desc_p.ref().isDisjoint(other.desc_p.ref());
426}
427
428inline ostream& operator<<(ostream& os, const RecordDesc& desc) { return desc.put(os); }
429inline AipsIO& operator<<(AipsIO& os, const RecordDesc& desc) { return desc.put(os); }
430inline AipsIO& operator>>(AipsIO& os, RecordDesc& desc) { return desc.get(os); }
431
432} // namespace casacore
433
434#endif
Bool isSubRecord(Int whichField) const
Returns True if whichField is a sub-record.
Definition RecordDesc.h:376
RecordDesc & rwSubRecord(Int whichField)
Definition RecordDesc.h:394
Bool isStrictSubset(const RecordDesc &other, Bool &equalDataTypes) const
Test if this description is a strict subset of another one, thus if it is a subset and not equal.
Definition RecordDesc.h:415
COWPtr< RecordDescRep > desc_p
Use a copy-on-write pointer to the RecordDescRep.
Definition RecordDesc.h:289
Int fieldNumber(const String &fieldName) const
Returns the index of the field named fieldName.
Definition RecordDesc.h:352
uInt nfields() const
Number of fields in the description.
Definition RecordDesc.h:356
uInt merge(const RecordDesc &other, RecordInterface::DuplicatesFlag DuplicateAction=RecordInterface::ThrowOnDuplicates)
Add all the fields from another RecordDesc to the current objects.
Definition RecordDesc.h:339
void renameField(const String &newName, Int whichField)
Rename the given field.
Definition RecordDesc.h:348
uInt removeField(Int whichField)
Remove the given field from the description.
Definition RecordDesc.h:344
RecordDesc()
Create a description with no fields.
Definition RecordDesc.h:292
String makeName(Int whichField) const
Create a name for a field defined by index as *i (similar to glish).
Definition RecordDesc.h:364
Bool isEqual(const RecordDesc &other, Bool &equalDataTypes) const
Test if this description equals another one.
Definition RecordDesc.h:409
Bool isSubset(const RecordDesc &other, Bool &equalDataTypes) const
Test if this description is a subset of another one.
Definition RecordDesc.h:412
const String & comment(Int whichField) const
Get the comment for this field.
Definition RecordDesc.h:322
Bool conform(const RecordDesc &other) const
Test if this description conforms the other.
Definition RecordDesc.h:405
AipsIO & get(AipsIO &os)
uInt mergeField(const RecordDesc &other, Int whichFieldFromOther, RecordInterface::DuplicatesFlag DuplicateAction=RecordInterface::ThrowOnDuplicates)
Merge a single field from other.
Definition RecordDesc.h:334
const String & name(Int whichField) const
What is the name of the given field.
Definition RecordDesc.h:368
const RecordDesc & subRecord(Int whichField) const
If whichField is a sub-record return its description.
Definition RecordDesc.h:390
Bool isDisjoint(const RecordDesc &other) const
Test if the set of field names in this and other record description is disjoint (i....
Definition RecordDesc.h:424
void setComment(Int whichField, const String &comment)
Set the comment for this field.
Definition RecordDesc.h:326
friend AipsIO & operator>>(AipsIO &os, RecordDesc &desc)
Definition RecordDesc.h:430
String uniqueName(const String &name) const
Make the given name unique by adding a suffix _j when needed.
Definition RecordDesc.h:360
Bool operator!=(const RecordDesc &other) const
Definition RecordDesc.h:402
friend ostream & operator<<(ostream &os, const RecordDesc &desc)
Writes/reads the RecordDesc to/from an output stream.
Definition RecordDesc.h:428
void setShape(Int whichField, const IPosition &shape)
Set the shape for this field.
Definition RecordDesc.h:330
Bool isTable(Int whichField) const
Returns True if whichField is a table.
Definition RecordDesc.h:380
Bool isSuperset(const RecordDesc &other, Bool &equalDataTypes) const
Test if this description is a superset of another one.
Definition RecordDesc.h:418
Bool operator==(const RecordDesc &other) const
This and other compare equal if the field types and shapes are identical (recursively if there are de...
Definition RecordDesc.h:398
DataType type(Int whichField) const
What is the type of the given field.
Definition RecordDesc.h:358
Bool isStrictSuperset(const RecordDesc &other, Bool &equalDataTypes) const
Test if this description is a strict superset of another one, thus if it is a superset and not equal.
Definition RecordDesc.h:421
Bool isArray(Int whichField) const
Returns True if whichField is an array.
Definition RecordDesc.h:372
RecordDesc & operator=(const RecordDesc &other)
Replace this description with other.
Definition RecordDesc.h:296
ostream & put(ostream &os) const
Writes/reads the RecordDesc to/from an output stream.
uInt addTable(const String &fieldName, const String &tableDescName)
Add a Table field to the description.
Definition RecordDesc.h:318
AipsIO & put(AipsIO &os) const
Bool isScalar(Int whichField) const
Returns True if whichField is a scalar.
Definition RecordDesc.h:374
const String & tableDescName(Int whichField) const
What is the name of the table description.
Definition RecordDesc.h:386
uInt addField(const String &fieldName, DataType dataType)
Add scalar, array, sub-record, or table field.
Definition RecordDesc.h:305
const IPosition & shape(Int whichField) const
What is the shape of the given field.
Definition RecordDesc.h:382
String: the storage and methods of handling collections of characters.
Definition String.h:355
For temporary backward namespace compatibility, use casa as alias for casacore.
Definition mainpage.dox:28
friend AipsIO & operator>>(AipsIO &os, Record &rec)
Read the Record from an input stream.
Definition Record.h:431
ostream & operator<<(ostream &os, const IComplex &)
Show on ostream.
unsigned int uInt
Definition aipstype.h:49
Int fieldNumber() const
Return the fieldnumber of this field.
String name() const
Return the name of the field.
int Int
Definition aipstype.h:48
bool Bool
Define the standard types used by Casacore.
Definition aipstype.h:40
const String & comment() const
Get the comment of this field.
DataType dataType(const RecordFieldId &) const