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