00001 /* 00002 * The information in this file is 00003 * Copyright(c) 2007 Ball Aerospace & Technologies Corporation 00004 * and is subject to the terms and conditions of the 00005 * GNU Lesser General Public License Version 2.1 00006 * The license text is available from 00007 * http://www.gnu.org/licenses/lgpl.html 00008 */ 00009 00010 #ifndef HDF4UTILITIES_H 00011 #define HDF4UTILITIES_H 00012 00013 #include "AppConfig.h" 00014 00015 #include <hdf.h> 00016 #include <mfhdf.h> 00017 #include "HdfUtilities.h" 00018 00019 #include "Hdf4Attribute.h" 00020 #include "Hdf4Element.h" 00021 #include "DataVariant.h" 00022 #include "Resource.h" 00023 00024 #include <string> 00025 00026 namespace HdfUtilities 00027 { 00028 /** 00029 * Reads an attribute from an Hdf4Element based on the attribute name. 00030 * 00031 * Example usage: 00032 * @code 00033 * // assume pElement is a pDataset is a valid, non-NULL Hdf4Dataset 00034 * unsigned short badValue; 00035 * if (HdfUtilities::getAttribute(*pDataset, "_FillValue", badValue) == false) 00036 * { 00037 * // error condition 00038 * } 00039 * // use _FillValue here 00040 * @endcode 00041 * 00042 * @param element 00043 * The Hdf4Element from which to read the attribute. 00044 * @param attributeName 00045 * The name of the attribute to read in. 00046 * @param actualValue 00047 * Contains the actual value contained in the attribute. 00048 * 00049 * @return TRUE if the attribute was found and contained valid data, FALSE otherwise. 00050 */ 00051 template<typename T> 00052 bool getAttribute(const Hdf4Element& element, const std::string& attributeName, T& actualValue) 00053 { 00054 Hdf4Attribute* pAttr = element.getAttribute(attributeName); 00055 if (pAttr != NULL) 00056 { 00057 return pAttr->getVariant().getValue(actualValue); 00058 } 00059 return false; 00060 } 00061 00062 /** 00063 * Converts an HDF4 type to a string that can be used to create an Hdf4Attribute. 00064 * 00065 * @param type 00066 * The HDF4 type (ie. DFNT_CHAR). 00067 * @param count 00068 * The number of elements whose data type is 'type'. 00069 * 00070 * @return A string that represents the HDF5 type in the same way 00071 * that DynamicObect::get() expresses types as strings. 00072 */ 00073 std::string hdf4TypeToString(long type, size_t count); 00074 00075 00076 /** 00077 * Given an open HDF4 Attribute identifier retrieves 00078 * the attribute and places it in a variant. 00079 * 00080 * @param obj_id 00081 * The object identifier that the attribute should be read from. 00082 * @param attr_index 00083 * The index of the attribute to read. 00084 * @param var 00085 * The variant that the attribute data will be placed in. 00086 * 00087 * @return True if the attribute could be read, false otherwise. 00088 */ 00089 bool readHdf4Attribute(int32 obj_id, int32 attr_index, DataVariant& var); 00090 00091 /** 00092 * The %Hdf4FileObject is a trait object for use with the %Resource template. 00093 * 00094 * It provides capability for opening and closing HDF4 files. 00095 * 00096 * @see FileResource 00097 */ 00098 class Hdf4FileObject 00099 { 00100 public: 00101 /** 00102 * This is an implementation detail of the %Hdf4FileObject class. 00103 * 00104 * It is used for passing the parameters required by SDstart. 00105 */ 00106 struct Args 00107 { 00108 /** 00109 * The file name of the file that is opened. 00110 */ 00111 std::string mFilename; 00112 00113 /** 00114 * How the file is accessed (read, write, append, truncate, etc.). 00115 * 00116 * For details, see the HDF documentation. 00117 */ 00118 int32 mAccess; 00119 00120 /** 00121 * Constructs an Args object for an HDF4 File Object. 00122 * 00123 * See Resource.h for details. 00124 * 00125 * @param filename 00126 * The file that is opened. 00127 * @param access 00128 * How the file will be opened (ie. DFACC_READ, DFACC_WRITE, etc.). See the HDF 00129 * documentation for details. 00130 */ 00131 Args(std::string filename, int32 access = DFACC_READ) : mFilename(filename), mAccess(access) {} 00132 }; 00133 00134 /** 00135 * Obtains an HDF4 file handle. 00136 * 00137 * See Resource.h for details. 00138 * 00139 * @param args 00140 * The arguments for obtaining the resource. Should be of type Hdf4FileObject::Args. 00141 * @return Returns a pointer to a handle of the dataset. 00142 */ 00143 int32* obtainResource(const Args &args) const; 00144 00145 /** 00146 * Releases an HDF4 file handle. 00147 * 00148 * See Resource.h for details. 00149 * 00150 * @param args 00151 * The arguments for releasing the resource. Should be of type Hdf4FileObject::Args. 00152 * @param pHandle 00153 * A pointer to the handle to be freed. 00154 */ 00155 void releaseResource(const Args &args, int32* pHandle) const; 00156 }; 00157 00158 /** 00159 * This is a %Resource class that opens and closes HDF4 files. 00160 * 00161 * It has a conversion operator to allow an %Hdf4FileResource object to be used 00162 * where ever a int32* file handle would normally be used. 00163 * 00164 * see Hdf4DatasetResource for code examples. 00165 */ 00166 class Hdf4FileResource : public Resource<int32, Hdf4FileObject> 00167 { 00168 public: 00169 /** 00170 * Creates a resource to an HDF4 file handle. 00171 * 00172 * Auto-closes file when the object goes out of scope. 00173 * 00174 * @param pFilename 00175 * The name of the file to open. 00176 * @param access 00177 * Optional argument for how to access the file 00178 * (DFACC_READ, DFACC_WRITE, DFACC_CREATE, DFACC_ALL). 00179 */ 00180 Hdf4FileResource(const char *pFilename, int32 access = DFACC_READ) : 00181 Resource<int32, Hdf4FileObject>(Hdf4FileObject::Args(pFilename, access)) 00182 { 00183 } 00184 00185 /** 00186 * Allows for implict conversion of this resource type to an int32*. 00187 * 00188 * @return A pointer to an int32 reprsenting the file handle. 00189 */ 00190 operator int32*() 00191 { 00192 return get(); 00193 } 00194 }; 00195 00196 /** 00197 * This is an implementation detail of the %Hdf4DatasetObject class. 00198 * 00199 * It is used for passing the parameters required by SDselect. 00200 */ 00201 class Hdf4DatasetObject 00202 { 00203 public: 00204 /** 00205 * This is an implementation detail of the %Hdf4FileObject class. 00206 * 00207 * It is used for passing the parameters required by SDstart. 00208 */ 00209 struct Args 00210 { 00211 /** 00212 * The file handle that represents the file that contains 00213 * the dataset. 00214 */ 00215 int32 mFileHandle; 00216 00217 /** 00218 * The index of the dataset. 00219 * 00220 * There are two constructors provided, one that takes the name 00221 * of the dataset, one that takes the index. This value is 00222 * then initialized appropriately by the constructor. 00223 */ 00224 int mIndex; 00225 00226 /** 00227 * Constructs an Args object for an HDF4 Dataset Object. 00228 * 00229 * See Resource.h for details. 00230 * 00231 * @param fileHandle 00232 * A file handle repsesenting the file that contains the specified 00233 * dataset. 00234 * @param dsIndex 00235 * The index of the dataset to access. 00236 */ 00237 Args(int32 fileHandle, int dsIndex) : 00238 mFileHandle(fileHandle), 00239 mIndex(dsIndex) 00240 { 00241 } 00242 00243 /** 00244 * Constructs an Args object for an HDF4 Dataset Object. 00245 * 00246 * See Resource.h for details. 00247 * 00248 * This method is provided for convenience, behaving the 00249 * same as the constructor above. 00250 * 00251 * @param fileHandle 00252 * A file handle repsesenting the file that contains the specified 00253 * dataset. 00254 * @param datasetName 00255 * The name of the dataset to access. 00256 */ 00257 Args(int32 fileHandle, const std::string& datasetName) : 00258 mFileHandle(fileHandle) 00259 { 00260 mIndex = SDnametoindex(mFileHandle, datasetName.c_str()); 00261 } 00262 }; 00263 00264 /** 00265 * Obtains an HDF4 dataset handle. 00266 * 00267 * See Resource.h for details. 00268 * 00269 * @param args 00270 * The arguments for obtaining the resource. Should be of type Hdf4DatasetObject::Args. 00271 * @return Returns a pointer to a handle of the dataset. 00272 */ 00273 int32* obtainResource(const Args &args) const; 00274 00275 /** 00276 * Releases an HDF4 dataset handle. 00277 * 00278 * See Resource.h for details. 00279 * 00280 * @param args 00281 * The arguments for releasing the resource. Should be of type Hdf4DatasetObject::Args. 00282 * @param pHandle 00283 * A pointer to the handle to be freed. 00284 */ 00285 void releaseResource(const Args &args, int32* pHandle) const; 00286 }; 00287 00288 /** 00289 * This is a %Resource class that opens and closes HDF4 datasets. 00290 * 00291 * It has a conversion operator to allow an %Hdf4DatasetResource object to be used 00292 * where ever a int32* data handle would normally be used. 00293 * 00294 * @code 00295 * bool readData(const string& filename, int index) 00296 * { 00297 * Hdf4FileResource file("c:/data/a.hdf"); 00298 * if (file.get() != NULL && *file != FAIL) 00299 * { 00300 * Hdf4DatasetResource dataset(*file, index); 00301 * if (dataset.get() != NULL && *dataset != FAIL) 00302 * { 00303 * // do SDreaddata here 00304 * } 00305 * } 00306 * } 00307 * @endcode 00308 */ 00309 class Hdf4DatasetResource : public Resource<int32, Hdf4DatasetObject> 00310 { 00311 public: 00312 /** 00313 * Creates a resource to an Hdf4 dataset handle. 00314 * 00315 * Auto-closes data handle when the object goes out of scope. 00316 * 00317 * @param fileHandle 00318 * A handle to the file that contains the dataset. 00319 * @param datasetName 00320 * The name of the dataset to open. This is typically the easiest 00321 * way to get a data handle since it takes the result from Hdf4Dataset::getName(). 00322 */ 00323 Hdf4DatasetResource(int32 fileHandle, const std::string& datasetName) : 00324 Resource<int32, Hdf4DatasetObject>(Hdf4DatasetObject::Args(fileHandle, datasetName)) 00325 { 00326 } 00327 00328 /** 00329 * Creates a resource to an Hdf4 dataset handle. 00330 * 00331 * Auto-closes data handle when the object goes out of scope. 00332 * 00333 * @param fileHandle 00334 * A handle to the file that contains the dataset. 00335 * @param dsIndex 00336 * The index, if known, of the dataset. 00337 */ 00338 Hdf4DatasetResource(int32 fileHandle, int dsIndex) : 00339 Resource<int32, Hdf4DatasetObject>(Hdf4DatasetObject::Args(fileHandle, dsIndex)) 00340 { 00341 } 00342 00343 /** 00344 * Allows for implict conversion of this resource type to an int32*. 00345 * 00346 * @return A pointer to an int32 reprsenting the file handle. 00347 */ 00348 operator int32*() 00349 { 00350 return get(); 00351 } 00352 }; 00353 } 00354 00355 #endif