//# RecordRep.cc: A hierarchical collection of named fields of various types //# Copyright (C) 1996,1997,1999,2000,2001,2002,2005 //# 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$ #include #include #include #include #include #include #include #include #include #include #include #include #include //# for memmove with gcc-4.3 namespace casacore { //# NAMESPACE CASACORE - BEGIN // Tweaked for SUN NTV compiler. Added the const_cast to give a hint to the Solaris compiler. RecordRep::RecordRep () : nused_p (0) {} RecordRep::RecordRep (const RecordDesc& description) : desc_p (description), nused_p (0) { restructure (desc_p, True); } RecordRep::RecordRep (const RecordRep& other) : desc_p (other.desc_p), nused_p (0) { restructure (desc_p, False); copy_other (other); } RecordRep& RecordRep::operator= (const RecordRep& other) { if (this != &other) { restructure (other.desc_p, False); copy_other (other); } return *this; } RecordRep::~RecordRep() { delete_myself (desc_p.nfields()); } void RecordRep::restructure (const RecordDesc& newDescription, Bool recursive) { delete_myself (desc_p.nfields()); desc_p = newDescription; nused_p = desc_p.nfields(); datavec_p.resize (nused_p); datavec_p = static_cast(0); data_p.resize (nused_p); for (uInt i=0; i= data_p.nelements()) { datavec_p.resize (nused_p + 16); data_p.resize (nused_p + 16); } datavec_p[nused_p] = 0; data_p[nused_p++] = ptr; } void RecordRep::removeDataPtr (Int index) { nused_p--; if (index < Int(nused_p)) { memmove (&datavec_p[index], &datavec_p[index+1], (nused_p-index) * sizeof(void*)); memmove (&data_p[index], &data_p[index+1], (nused_p-index) * sizeof(void*)); } } void RecordRep::removeData (Int whichField, void* ptr, void* vecptr) { DataType type = desc_p.type(whichField); if (type == TpRecord) { delete static_cast(ptr); }else{ deleteDataField (type, ptr, vecptr); } } void RecordRep::removeField (Int whichField) { removeData (whichField, data_p[whichField], datavec_p[whichField]); removeDataPtr (whichField); removeFieldFromDesc (whichField); } void RecordRep::addFieldToDesc (const String& name, DataType type, const IPosition& shape, Bool fixedShape) { if (fixedShape) { desc_p.addField (name, type, shape); }else{ desc_p.addField (name, type); } } void RecordRep::removeFieldFromDesc (Int whichField) { desc_p.removeField (whichField); } void RecordRep::addDataField (const String& name, DataType type, const IPosition& shape, Bool fixedShape, const void* data) { AlwaysAssert (type == TpBool || type == TpArrayBool || type == TpUChar || type == TpArrayUChar || type == TpShort || type == TpArrayShort || type == TpInt || type == TpArrayInt || type == TpUInt || type == TpArrayUInt || type == TpInt64 || type == TpArrayInt64 || type == TpFloat || type == TpArrayFloat || type == TpDouble || type == TpArrayDouble || type == TpComplex || type == TpArrayComplex || type == TpDComplex || type == TpArrayDComplex || type == TpString || type == TpArrayString , AipsError); addFieldToDesc (name, type, shape, fixedShape); void* ptr = createDataField (type, shape); copyDataField (type, ptr, data); addDataPtr (ptr); } void RecordRep::addField (const String& name, const Record& rec, RecordInterface::RecordType type) { // When the record is empty, it is variable structured. if (rec.nfields() == 0) { type = RecordInterface::Variable; } // When the new field is fixed, add its description too. if (type == RecordInterface::Fixed) { desc_p.addField (name, rec.description()); }else{ desc_p.addField (name, TpRecord); } // Use default ctor and assignment to be sure that the // new record gets the correct record type. Record* ptr = new Record (this, type); *ptr = rec; addDataPtr (ptr); } void RecordRep::checkShape (DataType type, const IPosition& shape, const void* value, const String& fieldName) { IPosition arrShape; switch (type) { case TpArrayBool: arrShape = static_cast*>(value)->shape(); break; case TpArrayUChar: arrShape = static_cast*>(value)->shape(); break; case TpArrayShort: arrShape = static_cast*>(value)->shape(); break; case TpArrayInt: arrShape = static_cast*>(value)->shape(); break; case TpArrayUInt: arrShape = static_cast*>(value)->shape(); break; case TpArrayInt64: arrShape = static_cast*>(value)->shape(); break; case TpArrayFloat: arrShape = static_cast*>(value)->shape(); break; case TpArrayDouble: arrShape = static_cast*>(value)->shape(); break; case TpArrayComplex: arrShape = static_cast*>(value)->shape(); break; case TpArrayDComplex: arrShape = static_cast*>(value)->shape(); break; case TpArrayString: arrShape = static_cast*>(value)->shape(); break; default: throw (AipsError ("RecordRep::checkShape")); } if (! shape.isEqual (arrShape)) { throw (ArrayConformanceError ("Record::define - fixed array conformance error for field " + fieldName)); } } void RecordRep::defineDataField (Int whichField, DataType type, const void* value) { AlwaysAssert (whichField >= 0 && whichField < Int(nused_p), AipsError); DataType descDtype = desc_p.type(whichField); if (type == descDtype) { if (type == TpRecord) { *static_cast(data_p[whichField]) = *static_cast(value); }else{ if (desc_p.isArray(whichField)) { const IPosition& shape = desc_p.shape(whichField); if (shape.nelements() > 0 && shape(0) > 0) { checkShape (type, shape, value, desc_p.name(whichField)); } } copyDataField (type, data_p[whichField], value); } } else if (isArray(type) && asScalar(type) == descDtype) { // A scalar can be defined using a single element vector. checkShape (type, IPosition(1,1), value, desc_p.name(whichField)); // Make sure there is a datavec entry. get_pointer (whichField, type); copyDataField (type, datavec_p[whichField], value); } else { throw (AipsError ("RecordRep::defineDataField - " "incorrect data type used for field " + desc_p.name(whichField))); } } void* RecordRep::createDataField (DataType type, const IPosition& shape) { IPosition arrayShape; if (shape.nelements() > 0 && shape(0) > 0) { arrayShape = shape; } switch (type) { case TpBool: { Bool* ptr = new Bool; *ptr = False; return ptr; } case TpUChar: { uChar* ptr = new uChar; *ptr = 0; return ptr; } case TpShort: { Short* ptr = new Short; *ptr = 0; return ptr; } case TpInt: { Int* ptr = new Int; *ptr = 0; return ptr; } case TpUInt: { uInt* ptr = new uInt; *ptr = 0; return ptr; } case TpInt64: { Int64* ptr = new Int64; *ptr = 0; return ptr; } case TpFloat: { float* ptr = new float; *ptr = 0.0; return ptr; } case TpDouble: { double* ptr = new double; *ptr = 0.0; return ptr; } case TpComplex: return new Complex; case TpDComplex: return new DComplex; case TpString: return new String; case TpArrayBool: { Array* ptr = new Array (arrayShape); *ptr = False; return ptr; } case TpArrayUChar: { Array* ptr = new Array (arrayShape); *ptr = 0; return ptr; } case TpArrayShort: { Array* ptr = new Array (arrayShape); *ptr = 0; return ptr; } case TpArrayInt: { Array* ptr = new Array (arrayShape); *ptr = 0; return ptr; } case TpArrayUInt: { Array* ptr = new Array (arrayShape); *ptr = 0; return ptr; } case TpArrayInt64: { Array* ptr = new Array (arrayShape); *ptr = 0; return ptr; } case TpArrayFloat: { Array* ptr = new Array (arrayShape); *ptr = 0.0; return ptr; } case TpArrayDouble: { Array* ptr = new Array (arrayShape); *ptr = 0.0; return ptr; } case TpArrayComplex: return new Array (arrayShape); case TpArrayDComplex: return new Array (arrayShape); case TpArrayString: return new Array (arrayShape); default: throw (AipsError ("RecordRep::createDataField: unknown data type " + String::toString(int(type)))); } } void RecordRep::makeDataVec (Int whichField, DataType type) { IPosition shape(1,1); switch (type) { case TpBool: datavec_p[whichField] = new Array (shape, static_cast(data_p[whichField]), SHARE); break; case TpUChar: datavec_p[whichField] = new Array (shape, static_cast(data_p[whichField]), SHARE); break; case TpShort: datavec_p[whichField] = new Array (shape, static_cast(data_p[whichField]), SHARE); break; case TpInt: datavec_p[whichField] = new Array (shape, static_cast(data_p[whichField]), SHARE); break; case TpUInt: datavec_p[whichField] = new Array (shape, static_cast(data_p[whichField]), SHARE); break; case TpInt64: datavec_p[whichField] = new Array (shape, static_cast(data_p[whichField]), SHARE); break; case TpFloat: datavec_p[whichField] = new Array (shape, static_cast(data_p[whichField]), SHARE); break; case TpDouble: datavec_p[whichField] = new Array (shape, static_cast(data_p[whichField]), SHARE); break; case TpComplex: datavec_p[whichField] = new Array (shape, static_cast(data_p[whichField]), SHARE); break; case TpDComplex: datavec_p[whichField] = new Array (shape, static_cast(data_p[whichField]), SHARE); break; case TpString: datavec_p[whichField] = new Array (shape, static_cast(data_p[whichField]), SHARE); break; default: throw (AipsError ("RecordRep::makeDataVec: unknown data type")); } } void RecordRep::delete_myself (uInt nfields) { if (nfields > nused_p) { nfields = nused_p; } for (uInt i=0; i(ptr); delete static_cast*>(vecptr); break; case TpUChar: delete static_cast(ptr); delete static_cast*>(vecptr); break; case TpShort: delete static_cast(ptr); delete static_cast*>(vecptr); break; case TpInt: delete static_cast(ptr); delete static_cast*>(vecptr); break; case TpUInt: delete static_cast(ptr); delete static_cast*>(vecptr); break; case TpInt64: delete static_cast(ptr); delete static_cast*>(vecptr); break; case TpFloat: delete static_cast(ptr); delete static_cast*>(vecptr); break; case TpDouble: delete static_cast(ptr); delete static_cast*>(vecptr); break; case TpComplex: delete static_cast(ptr); delete static_cast*>(vecptr); break; case TpDComplex: delete static_cast(ptr); delete static_cast*>(vecptr); break; case TpString: delete static_cast(ptr); delete static_cast*>(vecptr); break; case TpArrayBool: delete static_cast*>(ptr); break; case TpArrayUChar: delete static_cast*>(ptr); break; case TpArrayShort: delete static_cast*>(ptr); break; case TpArrayInt: delete static_cast*>(ptr); break; case TpArrayUInt: delete static_cast*>(ptr); break; case TpArrayInt64: delete static_cast*>(ptr); break; case TpArrayFloat: delete static_cast*>(ptr); break; case TpArrayDouble: delete static_cast*>(ptr); break; case TpArrayComplex: delete static_cast*>(ptr); break; case TpArrayDComplex: delete static_cast*>(ptr); break; case TpArrayString: delete static_cast*>(ptr); break; default: throw (AipsError ("RecordRep::deleteDataField")); } } Bool RecordRep::conform (const RecordRep& other) const { // First check (non-recursively) if the descriptions conform. if (! desc_p.conform (other.desc_p)) { return False; } // Now check for each fixed sub-record if it conforms. for (uInt i=0; i(const_cast(data_p[i])); if (thisRecord.isFixed()) { const Record& thatRecord = *static_cast(const_cast(other.data_p[i])); if (! thisRecord.conform (thatRecord)) { return False; } } } } return True; } void RecordRep::copyData (const RecordRep& other) { // Assume conform has already been called DebugAssert (conform (other), AipsError); copy_other (other); } void RecordRep::copy_other (const RecordRep& other) { for (uInt i=0; i(data_p[i]) = *static_cast(const_cast(other.data_p[i])); }else{ copyDataField (desc_p.type(i), data_p[i], other.data_p[i]); } } } void RecordRep::copyDataField (DataType type, Int whichField, const void* that) const { copyDataField (type, data_p[whichField], that); } void RecordRep::copyDataField (DataType type, void* ptr, const void* that) const { switch (type) { case TpBool: *static_cast(ptr) = *static_cast(that); break; case TpUChar: *static_cast(ptr) = *static_cast(that); break; case TpShort: *static_cast(ptr) = *static_cast(that); break; case TpInt: *static_cast(ptr) = *static_cast(that); break; case TpUInt: *static_cast(ptr) = *static_cast(that); break; case TpInt64: *static_cast(ptr) = *static_cast(that); break; case TpFloat: *static_cast(ptr) = *static_cast(that); break; case TpDouble: *static_cast(ptr) = *static_cast(that); break; case TpComplex: *static_cast(ptr) = *static_cast(that); break; case TpDComplex: *static_cast(ptr) = *static_cast(that); break; case TpString: *static_cast(ptr) = *static_cast(that); break; case TpArrayBool: static_cast*>(ptr)->resize (static_cast*>(that)->shape()); *static_cast*>(ptr) = *static_cast*>(that); break; case TpArrayUChar: static_cast*>(ptr)->resize (static_cast*>(that)->shape()); *static_cast*>(ptr) = *static_cast*>(that); break; case TpArrayShort: static_cast*>(ptr)->resize (static_cast*>(that)->shape()); *static_cast*>(ptr) = *static_cast*>(that); break; case TpArrayInt: static_cast*>(ptr)->resize (static_cast*>(that)->shape()); *static_cast*>(ptr) = *static_cast*>(that); break; case TpArrayUInt: static_cast*>(ptr)->resize (static_cast*>(that)->shape()); *static_cast*>(ptr) = *static_cast*>(that); break; case TpArrayInt64: static_cast*>(ptr)->resize (static_cast*>(that)->shape()); *static_cast*>(ptr) = *static_cast*>(that); break; case TpArrayFloat: static_cast*>(ptr)->resize (static_cast*>(that)->shape()); *static_cast*>(ptr) = *static_cast*>(that); break; case TpArrayDouble: static_cast*>(ptr)->resize (static_cast*>(that)->shape()); *static_cast*>(ptr) = *static_cast*>(that); break; case TpArrayComplex: static_cast*>(ptr)->resize (static_cast*>(that)->shape()); *static_cast*>(ptr) = *static_cast*>(that); break; case TpArrayDComplex: static_cast*>(ptr)->resize (static_cast*>(that)->shape()); *static_cast*>(ptr) = *static_cast*>(that); break; case TpArrayString: static_cast*>(ptr)->resize (static_cast*>(that)->shape()); *static_cast*>(ptr) = *static_cast*>(that); break; default: throw (AipsError ("RecordRep::copyDataField")); } } void* RecordRep::get_pointer (Int whichField, DataType type, const String& recordType) const { AlwaysAssert (recordType == "Record", AipsError); return get_pointer (whichField, type); } void* RecordRep::get_pointer (Int whichField, DataType type) const { AlwaysAssert (whichField >= 0 && whichField < Int(nused_p), AipsError); DataType descDtype = desc_p.type(whichField); if (type == descDtype) { return data_p[whichField]; } // A scalar can be returned as an array. if (! (isArray(type) && asScalar(type) == descDtype)) { throw (AipsError ("RecordRep::get_pointer - " "incorrect data type " + ValType::getTypeStr(type) + " used for field " + desc_p.name(whichField) + " with type " + ValType::getTypeStr(descDtype))); } if (datavec_p[whichField] == 0) { const_cast(this)->makeDataVec (whichField, descDtype); } return datavec_p[whichField]; } void RecordRep::mergeField (const RecordRep& other, Int whichFieldFromOther, RecordInterface::DuplicatesFlag flag) { // If the field exists and if flag tells to overwrite, // the field is removed first. if (flag == RecordInterface::OverwriteDuplicates) { Int fld = desc_p.fieldNumber (other.desc_p.name(whichFieldFromOther)); if (fld >= 0) { removeField (fld); } } // Try to add the field to the description. Int nr = desc_p.nfields(); Int nrnew = desc_p.mergeField (other.desc_p, whichFieldFromOther, flag); // It succeeded if nfields increased. // Then the value can be defined. if (nrnew > nr) { DataType type = desc_p.type (nr); void* otherPtr = other.get_pointer (whichFieldFromOther, type); void* ptr; if (type == TpRecord) { ptr = new Record (*static_cast(otherPtr)); }else{ ptr = createDataField (type, desc_p.shape(nr)); copyDataField (type, ptr, otherPtr); } addDataPtr (ptr); } } void RecordRep::merge (const RecordRep& other, RecordInterface::DuplicatesFlag flag) { Int n = other.desc_p.nfields(); for (Int i=0; i(ptr); break; case TpUChar: os << "uChar " << Int(*static_cast(ptr)); break; case TpShort: os << "Short " << *static_cast(ptr); break; case TpInt: os << "Int " << *static_cast(ptr); break; case TpUInt: os << "uInt " << *static_cast(ptr); break; case TpInt64: os << "Int64 " << *static_cast(ptr); break; case TpFloat: os << "Float " << *static_cast(ptr); break; case TpDouble: os << "Double " << *static_cast(ptr); break; case TpComplex: os << "Complex " << *static_cast(ptr); break; case TpDComplex: os << "DComplex " << *static_cast(ptr); break; case TpString: os << "String " << '"' << *static_cast(ptr) << '"'; break; case TpArrayBool: os << "Bool array with shape " << static_cast*>(ptr)->shape(); if (maxNrValues != 0) { const Array& arr = *static_cast*>(ptr); if (maxNrValues < 0) { os << endl << arr; } else { Vector vec = arr.reform (IPosition(1, arr.nelements())); if (uInt(maxNrValues+1) >= vec.nelements()) { os << endl << indent << " " << vec; } else { os << ", first values:" << endl << indent << " " << vec(Slice(0,maxNrValues-1)); } } } break; case TpArrayUChar: os << "uChar array with shape " << static_cast*>(ptr)->shape(); if (maxNrValues != 0) { const Array& arr = *static_cast*>(ptr); if (maxNrValues < 0) { os << endl << arr; } else { Vector vec = arr.reform (IPosition(1, arr.nelements())); if (uInt(maxNrValues+1) >= vec.nelements()) { os << endl << indent << " " << vec; } else { os << ", first values:" << endl << indent << " " << vec(Slice(0,maxNrValues-1)); } } } break; case TpArrayShort: os << "Short array with shape " << static_cast*>(ptr)->shape(); if (maxNrValues != 0) { const Array& arr = *static_cast*>(ptr); if (maxNrValues < 0) { os << endl << arr; } else { Vector vec = arr.reform (IPosition(1, arr.nelements())); if (uInt(maxNrValues+1) >= vec.nelements()) { os << endl << indent << " " << vec; } else { os << ", first values:" << endl << indent << " " << vec(Slice(0,maxNrValues-1)); } } } break; case TpArrayInt: os << "Int array with shape " << static_cast*>(ptr)->shape(); if (maxNrValues != 0) { const Array& arr = *static_cast*>(ptr); if (maxNrValues < 0) { os << endl << arr; } else { Vector vec = arr.reform (IPosition(1, arr.nelements())); if (uInt(maxNrValues+1) >= vec.nelements()) { os << endl << indent << " " << vec; } else { os << ", first values:" << endl << indent << " " << vec(Slice(0,maxNrValues-1)); } } } break; case TpArrayUInt: os << "uInt array with shape " << static_cast*>(ptr)->shape(); if (maxNrValues != 0) { const Array& arr = *static_cast*>(ptr); if (maxNrValues < 0) { os << endl << arr; } else { Vector vec = arr.reform (IPosition(1, arr.nelements())); if (uInt(maxNrValues+1) >= vec.nelements()) { os << endl << indent << " " << vec; } else { os << ", first values:" << endl << indent << " " << vec(Slice(0,maxNrValues-1)); } } } break; case TpArrayInt64: os << "Int64 array with shape " << static_cast*>(ptr)->shape(); if (maxNrValues != 0) { const Array& arr = *static_cast*>(ptr); if (maxNrValues < 0) { os << endl << arr; } else { Vector vec = arr.reform (IPosition(1, arr.nelements())); if (uInt(maxNrValues+1) >= vec.nelements()) { os << endl << indent << " " << vec; } else { os << ", first values:" << endl << indent << " " << vec(Slice(0,maxNrValues-1)); } } } break; case TpArrayFloat: os << "Float array with shape " << static_cast*>(ptr)->shape(); if (maxNrValues != 0) { const Array& arr = *static_cast*>(ptr); if (maxNrValues < 0) { os << endl << arr; } else { Vector vec = arr.reform (IPosition(1, arr.nelements())); if (uInt(maxNrValues+1) >= vec.nelements()) { os << endl << indent << " " << vec; } else { os << ", first values:" << endl << indent << " " << vec(Slice(0,maxNrValues-1)); } } } break; case TpArrayDouble: os << "Double array with shape " << static_cast*>(ptr)->shape(); if (maxNrValues != 0) { const Array& arr = *static_cast*>(ptr); if (maxNrValues < 0) { os << endl << arr; } else { Vector vec = arr.reform (IPosition(1, arr.nelements())); if (uInt(maxNrValues+1) >= vec.nelements()) { os << endl << indent << " " << vec; } else { os << ", first values:" << endl << indent << " " << vec(Slice(0,maxNrValues-1)); } } } break; case TpArrayComplex: os << "Complex array with shape " << static_cast*>(ptr)->shape(); if (maxNrValues != 0) { const Array& arr = *static_cast*>(ptr); if (maxNrValues < 0) { os << endl << arr; } else { Vector vec = arr.reform (IPosition(1, arr.nelements())); if (uInt(maxNrValues+1) >= vec.nelements()) { os << endl << indent << " " << vec; } else { os << ", first values:" << endl << indent << " " << vec(Slice(0,maxNrValues-1)); } } } break; case TpArrayDComplex: os << "DComplex array with shape " << static_cast*>(ptr)->shape(); if (maxNrValues != 0) { const Array& arr = *static_cast*>(ptr); if (maxNrValues < 0) { os << endl << arr; } else { Vector vec = arr.reform (IPosition(1, arr.nelements())); if (uInt(maxNrValues+1) >= vec.nelements()) { os << endl << indent << " " << vec; } else { os << ", first values:" << endl << indent << " " << vec(Slice(0,maxNrValues-1)); } } } break; case TpArrayString: os << "String array with shape " << static_cast*>(ptr)->shape(); if (maxNrValues != 0) { const Array& arr = *static_cast*>(ptr); if (maxNrValues < 0) { os << endl << arr; } else { Vector vec = arr.reform (IPosition(1, arr.nelements())); if (uInt(maxNrValues+1) >= vec.nelements()) { os << endl << indent << " " << vec; } else { os << ", first values:" << endl << indent << " " << vec(Slice(0,maxNrValues-1)); } } } break; default: throw (AipsError ("RecordRep::printDataField")); } } void RecordRep::print (std::ostream& os, Int maxNrValues, const String& indent) const { for (uInt i=0; i(data_p[i])->print (os, maxNrValues, indent+" "); os << indent << '}' << endl; } else { printDataField (os, desc_p.type(i), indent, maxNrValues, data_p[i]); os << endl; } } } void RecordRep::putDataField (AipsIO& os, DataType type, const void* ptr) const { switch (type) { case TpBool: os << *static_cast(ptr); break; case TpUChar: os << *static_cast(ptr); break; case TpShort: os << *static_cast(ptr); break; case TpInt: os << *static_cast(ptr); break; case TpUInt: os << *static_cast(ptr); break; case TpInt64: os << *static_cast(ptr); break; case TpFloat: os << *static_cast(ptr); break; case TpDouble: os << *static_cast(ptr); break; case TpComplex: os << *static_cast(ptr); break; case TpDComplex: os << *static_cast(ptr); break; case TpString: os << *static_cast(ptr); break; case TpArrayBool: putArray (os, *static_cast*>(ptr), "Array"); break; case TpArrayUChar: putArray (os, *static_cast*>(ptr), "Array"); break; case TpArrayShort: putArray (os, *static_cast*>(ptr), "Array"); break; case TpArrayInt: putArray (os, *static_cast*>(ptr), "Array"); break; case TpArrayUInt: putArray (os, *static_cast*>(ptr), "Array"); break; case TpArrayInt64: putArray (os, *static_cast*>(ptr), "Array"); break; case TpArrayFloat: putArray (os, *static_cast*>(ptr), "Array"); break; case TpArrayDouble: putArray (os, *static_cast*>(ptr), "Array"); break; case TpArrayComplex: putArray (os, *static_cast*>(ptr), "Array"); break; case TpArrayDComplex: putArray (os, *static_cast*>(ptr), "Array"); break; case TpArrayString: putArray (os, *static_cast*>(ptr), "Array"); break; default: throw (AipsError ("RecordRep::putDataField")); } } void RecordRep::getDataField (AipsIO& os, DataType type, void* ptr) { switch (type) { case TpBool: os >> *static_cast(ptr); break; case TpUChar: os >> *static_cast(ptr); break; case TpShort: os >> *static_cast(ptr); break; case TpInt: os >> *static_cast(ptr); break; case TpUInt: os >> *static_cast(ptr); break; case TpInt64: os >> *static_cast(ptr); break; case TpFloat: os >> *static_cast(ptr); break; case TpDouble: os >> *static_cast(ptr); break; case TpComplex: os >> *static_cast(ptr); break; case TpDComplex: os >> *static_cast(ptr); break; case TpString: os >> *static_cast(ptr); break; case TpArrayBool: os >> *static_cast*>(ptr); break; case TpArrayUChar: os >> *static_cast*>(ptr); break; case TpArrayShort: os >> *static_cast*>(ptr); break; case TpArrayInt: os >> *static_cast*>(ptr); break; case TpArrayUInt: os >> *static_cast*>(ptr); break; case TpArrayInt64: os >> *static_cast*>(ptr); break; case TpArrayFloat: os >> *static_cast*>(ptr); break; case TpArrayDouble: os >> *static_cast*>(ptr); break; case TpArrayComplex: os >> *static_cast*>(ptr); break; case TpArrayDComplex: os >> *static_cast*>(ptr); break; case TpArrayString: os >> *static_cast*>(ptr); break; default: throw (AipsError ("RecordRep::getDataField")); } } void RecordRep::putRecord (AipsIO& os, int recordType) const { os.putstart ("Record", 1); // version 1 os << desc_p; os << recordType; putData (os); os.putend(); } void RecordRep::putData (AipsIO& os) const { for (uInt i=0; i(const_cast(data_p[i])); }else{ static_cast(const_cast(data_p[i]))->putData (os); } }else{ putDataField (os, desc_p.type(i), data_p[i]); } } } void RecordRep::getRecord (AipsIO& os, Int& recordType) { // Support reading scalar and array keyword sets as records. // They are the very old way of storing keywords, since long replaced // by Record. The code does not exist anymore, but theoretically such data // can exist in a very old table. Therefore it is still supported here. uInt version; String type = os.getNextType(); if (type == "ScalarKeywordSet") { version = os.getstart ("ScalarKeywordSet"); getKeySet (os, version, 0); } else if (type == "ArrayKeywordSet") { version = os.getstart ("ArrayKeywordSet"); getKeySet (os, version, 1); }else{ uInt version = os.getstart ("Record"); // Get the description and restructure the record. RecordDesc desc; os >> desc; os >> recordType; restructure (desc, True); // Read the data. getData (os, version); } os.getend(); } void RecordRep::getData (AipsIO& os, uInt version) { for (uInt i=0; i> *static_cast(data_p[i]); }else{ static_cast(data_p[i])->getData (os, version); } }else{ getDataField (os, desc_p.type(i), data_p[i]); } } } void RecordRep::getKeySet (AipsIO& os, uInt version, uInt type) { // First build the description from the map of keyword names and // attributes. RecordDesc desc; getKeyDesc (os, desc); // Define the record from the description. // Read the keyword values and define the corresponding record value. restructure (desc, True); getScalarKeys (os); if (type == 1) { getArrayKeys (os); } // Newer keyword sets may contain nested keyword sets. // We do not support reading those, so throw an exception when they exist. if (version > 1) { uInt n; os >> n; AlwaysAssert (n==0, AipsError); } } void RecordRep::getKeyDesc (AipsIO& os, RecordDesc& desc) { // Start reading the Map of keyword names and attributes. os.getstart ("Map"); int dt; String name, comment; // Get #names and the default attribute (datatype + comment). uInt i, n; os >> n; os >> dt; os >> comment; // Get each keyword name and attribute. // Add them to the record description. for (i=0; i> name; os >> dt; os >> comment; desc.addField (name, DataType(dt)); } os.getend(); // Get the excluded data types and names. // Note that exNames was written as a Block, but can be // read as a Block. This is a template instantiation less. Block exDtype; Block exNames; os >> exDtype; os >> exNames; } void RecordRep::getScalarKeys (AipsIO& os) { uInt i, n; String name; // Read the values per type. os >> n; for (i=0; i> name; getDataField (os, TpBool, data_p[fieldNumber (name)]); } os >> n; for (i=0; i> name; getDataField (os, TpInt, data_p[fieldNumber (name)]); } os >> n; for (i=0; i> name; getDataField (os, TpUInt, data_p[fieldNumber (name)]); } os >> n; for (i=0; i> name; getDataField (os, TpFloat, data_p[fieldNumber (name)]); } os >> n; for (i=0; i> name; getDataField (os, TpDouble, data_p[fieldNumber (name)]); } os >> n; for (i=0; i> name; getDataField (os, TpComplex, data_p[fieldNumber (name)]); } os >> n; for (i=0; i> name; getDataField (os, TpDComplex, data_p[fieldNumber (name)]); } os >> n; for (i=0; i> name; getDataField (os, TpString, data_p[fieldNumber (name)]); } } void RecordRep::getArrayKeys (AipsIO& os) { uInt i, n; String name; // Read the values per type. os >> n; for (i=0; i> name; getDataField (os, TpArrayBool, data_p[fieldNumber (name)]); } os >> n; for (i=0; i> name; getDataField (os, TpArrayInt, data_p[fieldNumber (name)]); } os >> n; for (i=0; i> name; getDataField (os, TpArrayUInt, data_p[fieldNumber (name)]); } os >> n; for (i=0; i> name; getDataField (os, TpArrayFloat, data_p[fieldNumber (name)]); } os >> n; for (i=0; i> name; getDataField (os, TpArrayDouble, data_p[fieldNumber (name)]); } os >> n; for (i=0; i> name; getDataField (os, TpArrayComplex, data_p[fieldNumber (name)]); } os >> n; for (i=0; i> name; getDataField (os, TpArrayDComplex, data_p[fieldNumber (name)]); } os >> n; for (i=0; i> name; getDataField (os, TpArrayString, data_p[fieldNumber (name)]); } } } //# NAMESPACE CASACORE - END