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