00001 //# HDF5Record.h: A class to write/read a record into HDF5 00002 //# Copyright (C) 2008 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id$ 00027 00028 #ifndef CASA_HDF5RECORD_H 00029 #define CASA_HDF5RECORD_H 00030 00031 //# Includes 00032 #include <casacore/casa/aips.h> 00033 #include <casacore/casa/HDF5/HDF5Object.h> 00034 #include <casacore/casa/HDF5/HDF5DataType.h> 00035 #include <casacore/casa/Containers/Record.h> 00036 00037 namespace casacore { //# NAMESPACE CASACORE - BEGIN 00038 00039 // <summary> 00040 // A class to write/read a record into HDF5. 00041 // </summary> 00042 00043 // <use visibility=export> 00044 00045 // <reviewed reviewer="" date="" tests="tHDF5Record.cc"> 00046 // </reviewed> 00047 00048 // <prerequisite> 00049 // <li> <a href="http://hdf.ncsa.uiuc.edu">HDF5 system</a> 00050 // <li> <linkto class=Record>class Record</linkto> 00051 // </prerequisite> 00052 00053 // <synopsis> 00054 // This class has a static function to write a Record (or TableRecord) 00055 // into an HDF5 file by storing it as attributes for the given group. 00056 // Another static function can read back the Record. 00057 // It can handle all types of fields in a record. 00058 // <br> 00059 // A few remarks: 00060 // <ul> 00061 // <li> When writing the record, it first deletes all attributes of the group 00062 // to be sure that the group's attributes only contain the record. 00063 // <li> A Casacore Record is a recursive structure, so it is written as 00064 // nested groups. The name of a subgroup is the name of the subrecord. 00065 // <li> HDF5 cannot deal with empty arrays. Therefore they are written as 00066 // a special compound type holding the rank and type of the empty array. 00067 // <li> HDF5 cannot hold empty fixed length strings. This is solved by 00068 // storing an empty string with the special value <tt>__empty__</tt>. 00069 // </ul> 00070 // </synopsis> 00071 00072 // <motivation> 00073 // Record is a very important class in Casacore images, so it has to be 00074 // possible to read and write them from/to HDF5. 00075 // </motivation> 00076 00077 class HDF5Record 00078 { 00079 public: 00080 // Read a record from the attributes of the given group. 00081 // Nested records are read back correctly. 00082 // An empty record is returned if the group does not exist. 00083 static Record readRecord (const HDF5Object& parentHid, 00084 const String& groupName); 00085 00086 // Write the record as attributes of a group of the given parent. 00087 // Nested records are written as nested groups. 00088 // The group is deleted first if it already exists. 00089 static void writeRecord (const HDF5Object& parentHid, 00090 const String& recordName, 00091 const RecordInterface& rec); 00092 00093 // Remove the record (i.e. group) from the given parent. 00094 // Nothing is done if the record does not exist. 00095 static void remove (const HDF5Object& parentHid, 00096 const String& recordName); 00097 00098 // Read the (possibly nested) record values from the given group hid. 00099 static Record doReadRecord (hid_t parentHid); 00100 00101 // Write the (possibly nested) record values into the given group hid. 00102 static void doWriteRecord (const HDF5Object& groupHid, 00103 const RecordInterface& rec); 00104 00105 private: 00106 // Read a scalar value and add it to the record. 00107 static void readScalar (hid_t attrId, hid_t dtid, 00108 const String& name, RecordInterface& rec); 00109 00110 // Read an array value and add it to the record. 00111 static void readArray (hid_t attrId, hid_t dtid, const IPosition&, 00112 const String& name, RecordInterface& rec); 00113 00114 // Read a scalar string from an attribute and add it to the record. 00115 static void readScaString (hid_t attrId, Int sz, 00116 const String& name, RecordInterface& rec); 00117 00118 // Read a array of strings from an atrribute and add it to the record. 00119 static void readArrString (hid_t attrId, const IPosition&, 00120 const String& name, RecordInterface& rec); 00121 00122 // Read a field containing an empty array. 00123 static void readEmptyArray (hid_t attrId, 00124 const String& name, RecordInterface& rec); 00125 00126 // Read a field containing a scalar of fixed length. 00127 template<typename T> 00128 static void readSca (hid_t attrId, const String& name, 00129 RecordInterface& rec) 00130 { 00131 T value; 00132 HDF5DataType dtype((T*)0); 00133 read (attrId, &value, dtype); 00134 rec.define (name, value); 00135 } 00136 00137 // Read a field containing an array of fixed length elements. 00138 template<typename T> 00139 static void readArr (hid_t attrId, const IPosition& shape, 00140 const String& name, 00141 RecordInterface& rec) 00142 { 00143 Array<T> value(shape); 00144 HDF5DataType dtype((T*)0); 00145 read (attrId, value.data(), dtype); 00146 rec.define (name, value); 00147 } 00148 00149 // Read fixed length values from an attribute (scalar and array). 00150 static void read (hid_t attrId, void* value, 00151 const HDF5DataType& dtype); 00152 00153 // Write a fixed length scalar value as attribute. 00154 static void writeScalar (hid_t parentHid, const String& name, 00155 const void* value, 00156 const HDF5DataType& dtype); 00157 00158 // Write an array of fixed length values as attribute. 00159 static void writeArray (hid_t parentHid, const String& name, 00160 const void* value, const IPosition& shape, 00161 const HDF5DataType& dtype); 00162 00163 // Write a scalar string as attribute. 00164 // HDF5 cannot handle empty strings, so for empty strings a special 00165 // value is written. 00166 static void writeScaString (hid_t parentHid, const String& name, 00167 const String& value); 00168 00169 // Write an array of strings as attribute. 00170 // HDF5 cannot handle empty strings, so for empty strings a special 00171 // value is written. 00172 static void writeArrString (hid_t parentHid, const String& name, 00173 const Array<String>& value); 00174 00175 // Write a field containing an empty array. 00176 static void writeEmptyArray (hid_t groupHid, const String& name, 00177 Int rank, DataType dtype); 00178 00179 // Write a field containing a fixed length scalar value. 00180 template<typename T> 00181 static void writeSca (hid_t parentHid, const String& name, 00182 const RecordInterface& rec, Int i) 00183 { 00184 T value; 00185 rec.get (i, value); 00186 HDF5DataType dtype((T*)0); 00187 writeScalar (parentHid, name, &value, dtype); 00188 } 00189 00190 // Write a field containing an array of fixed length elements. 00191 template<typename T> 00192 static void writeArr (hid_t parentHid, const String& name, 00193 const RecordInterface& rec, Int i) 00194 { 00195 Array<T> value; 00196 rec.get (i, value); 00197 HDF5DataType dtype((T*)0); 00198 writeArray (parentHid, name, value.data(), value.shape(), dtype); 00199 } 00200 00201 }; 00202 00203 } 00204 00205 #endif