mirror of
https://github.com/HDFGroup/hdf5.git
synced 2024-11-21 01:04:10 +08:00
522 lines
17 KiB
C++
522 lines
17 KiB
C++
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* Copyright by The HDF Group. *
|
|
* Copyright by the Board of Trustees of the University of Illinois. *
|
|
* All rights reserved. *
|
|
* *
|
|
* This file is part of HDF5. The full HDF5 copyright notice, including *
|
|
* terms governing use, modification, and redistribution, is contained in *
|
|
* the COPYING file, which can be found at the root of the source code *
|
|
* distribution tree, or in https://www.hdfgroup.org/licenses. *
|
|
* If you do not have access to either file, you may request a copy from *
|
|
* help@hdfgroup.org. *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
/*****************************************************************************
|
|
FILE
|
|
tarray.cpp - HDF5 C++ testing the array datatype functionality
|
|
|
|
***************************************************************************/
|
|
#include <iostream>
|
|
using std::cerr;
|
|
using std::endl;
|
|
|
|
#include <string>
|
|
#include "H5Cpp.h" // C++ API header file
|
|
using namespace H5;
|
|
|
|
#include "h5test.h"
|
|
#include "h5cpputil.h" // C++ utilility header file
|
|
|
|
const H5std_string FILENAME("tarray.h5");
|
|
const H5std_string ARRAYTYPE_NAME("/Array type 1");
|
|
const int SPACE1_RANK = 1;
|
|
const hsize_t SPACE1_DIM1 = 4;
|
|
const int ARRAY1_RANK = 1;
|
|
const hsize_t ARRAY1_DIM1 = 4;
|
|
|
|
typedef enum flt_t { FLT_FLOAT, FLT_DOUBLE, FLT_LDOUBLE, FLT_OTHER } flt_t;
|
|
|
|
typedef enum int_t {
|
|
INT_CHAR,
|
|
INT_UCHAR,
|
|
INT_SHORT,
|
|
INT_USHORT,
|
|
INT_INT,
|
|
INT_UINT,
|
|
INT_LONG,
|
|
INT_ULONG,
|
|
INT_LLONG,
|
|
INT_ULLONG,
|
|
INT_OTHER
|
|
} int_t;
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_array_compound_array
|
|
*
|
|
* Purpose Tests 1-D array of compound datatypes (with array fields)
|
|
*
|
|
* Return None
|
|
*
|
|
* Programmer Binh-Minh Ribler (using C version)
|
|
* January, 2016
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_array_compound_array()
|
|
{
|
|
SUBTEST("ArrayType::getArrayNDims & ArrayType::getArrayDims");
|
|
typedef struct { // Typedef for compound datatype */
|
|
int i;
|
|
float f[ARRAY1_DIM1];
|
|
} s1_t;
|
|
s1_t wdata[SPACE1_DIM1][ARRAY1_DIM1]; // Information to write
|
|
s1_t rdata[SPACE1_DIM1][ARRAY1_DIM1]; // Information read in
|
|
hsize_t sdims1[] = {SPACE1_DIM1};
|
|
hsize_t tdims1[] = {ARRAY1_DIM1};
|
|
int nmemb; // Number of compound members
|
|
int ii; // counting variables
|
|
hsize_t idxi, idxj, idxk; // dimension indicing variables
|
|
H5T_class_t mclass; // Datatype class for field
|
|
|
|
// Initialize array data to write
|
|
for (idxi = 0; idxi < SPACE1_DIM1; idxi++)
|
|
for (idxj = 0; idxj < ARRAY1_DIM1; idxj++) {
|
|
wdata[idxi][idxj].i = static_cast<int>(idxi * 10 + idxj);
|
|
for (idxk = 0; idxk < ARRAY1_DIM1; idxk++) {
|
|
float temp = static_cast<float>(idxi) * 10.0F + static_cast<float>(idxj) * 2.5F +
|
|
static_cast<float>(idxk);
|
|
wdata[idxi][idxj].f[idxk] = temp;
|
|
}
|
|
} // end for
|
|
|
|
try {
|
|
// Create File
|
|
H5File file1(FILENAME, H5F_ACC_TRUNC);
|
|
|
|
// Create dataspace for datasets
|
|
DataSpace space(SPACE1_RANK, sdims1, NULL);
|
|
|
|
/*
|
|
* Create an array datatype of compounds, arrtype. Each compound
|
|
* datatype, comptype, contains an integer and an array of floats,
|
|
* arrfltype.
|
|
*/
|
|
|
|
// Create a compound datatype
|
|
CompType comptype(sizeof(s1_t));
|
|
|
|
// Insert integer field
|
|
comptype.insertMember("i", HOFFSET(s1_t, i), PredType::NATIVE_INT);
|
|
|
|
// Create an array of floats datatype
|
|
ArrayType arrfltype(PredType::NATIVE_FLOAT, ARRAY1_RANK, tdims1);
|
|
|
|
// Insert float array field
|
|
comptype.insertMember("f", HOFFSET(s1_t, f), arrfltype);
|
|
|
|
// Close array of floats field datatype
|
|
arrfltype.close();
|
|
|
|
// Create an array datatype of the compound datatype
|
|
ArrayType arrtype(comptype, ARRAY1_RANK, tdims1);
|
|
|
|
// Close compound datatype comptype
|
|
comptype.close();
|
|
|
|
// Create a dataset
|
|
DataSet dataset = file1.createDataSet("Dataset1", arrtype, space);
|
|
|
|
// Write dataset to disk
|
|
dataset.write(wdata, arrtype);
|
|
|
|
// Test opening ArrayType with opening constructor (Dec 2016)
|
|
|
|
// Commit the arrtype to give it a name
|
|
arrtype.commit(file1, ARRAYTYPE_NAME);
|
|
|
|
// Close it, then re-open with the opening constructor
|
|
arrtype.close();
|
|
ArrayType named_type(file1, ARRAYTYPE_NAME);
|
|
|
|
// Get and verify the type's name
|
|
H5std_string type_name = named_type.getObjName();
|
|
verify_val(type_name, ARRAYTYPE_NAME, "DataType::getObjName tests constructor", __LINE__, __FILE__);
|
|
named_type.close();
|
|
|
|
// Close all
|
|
dataset.close();
|
|
space.close();
|
|
file1.close();
|
|
|
|
// Re-open file
|
|
file1.openFile(FILENAME, H5F_ACC_RDONLY);
|
|
|
|
// Open the dataset
|
|
dataset = file1.openDataSet("Dataset1");
|
|
|
|
/*
|
|
* Check the datatype array of compounds
|
|
*/
|
|
|
|
// Verify that it is an array of compounds
|
|
DataType dstype = dataset.getDataType();
|
|
mclass = dstype.getClass();
|
|
verify_val(mclass == H5T_ARRAY, true, "f2_type.getClass", __LINE__, __FILE__);
|
|
|
|
dstype.close();
|
|
|
|
// Get the array datatype to check
|
|
ArrayType atype_check = dataset.getArrayType();
|
|
|
|
// Check the array rank
|
|
int ndims = atype_check.getArrayNDims();
|
|
verify_val(ndims, ARRAY1_RANK, "atype_check.getArrayNDims", __LINE__, __FILE__);
|
|
|
|
// Get the array dimensions
|
|
hsize_t rdims1[H5S_MAX_RANK];
|
|
atype_check.getArrayDims(rdims1);
|
|
|
|
// Check the array dimensions
|
|
for (ii = 0; ii < ndims; ii++)
|
|
if (rdims1[ii] != tdims1[ii]) {
|
|
TestErrPrintf("Array dimension information doesn't match!, rdims1[%d]=%" PRIuHSIZE
|
|
", tdims1[%d]=%" PRIuHSIZE "\n",
|
|
ii, rdims1[ii], ii, tdims1[ii]);
|
|
continue;
|
|
} // end if
|
|
|
|
// Test ArrayType::ArrayType(const hid_t existing_id)
|
|
ArrayType new_arrtype(atype_check.getId());
|
|
|
|
// Check the array rank
|
|
ndims = new_arrtype.getArrayNDims();
|
|
verify_val(ndims, ARRAY1_RANK, "new_arrtype.getArrayNDims", __LINE__, __FILE__);
|
|
|
|
// Get the array dimensions
|
|
new_arrtype.getArrayDims(rdims1);
|
|
|
|
// Check the array dimensions
|
|
for (ii = 0; ii < ndims; ii++)
|
|
if (rdims1[ii] != tdims1[ii]) {
|
|
TestErrPrintf("Array dimension information doesn't match!, rdims1[%d]=%" PRIuHSIZE
|
|
", tdims1[%d]=%" PRIuHSIZE "\n",
|
|
ii, rdims1[ii], ii, tdims1[ii]);
|
|
continue;
|
|
} // end if
|
|
|
|
/*
|
|
* Check the compound datatype and the array of floats datatype
|
|
* in the compound.
|
|
*/
|
|
// Get the compound datatype, which is the base datatype of the
|
|
// array datatype atype_check.
|
|
DataType base_type = atype_check.getSuper();
|
|
mclass = base_type.getClass();
|
|
verify_val(mclass == H5T_COMPOUND, true, "atype_check.getClass", __LINE__, __FILE__);
|
|
|
|
// Verify the compound datatype info
|
|
CompType ctype_check(base_type.getId());
|
|
base_type.close();
|
|
|
|
// Check the number of members
|
|
nmemb = ctype_check.getNmembers();
|
|
verify_val(nmemb, 2, "ctype_check.getNmembers", __LINE__, __FILE__);
|
|
|
|
// Check the 2nd field's name
|
|
H5std_string field2_name = ctype_check.getMemberName(1);
|
|
if (HDstrcmp(field2_name.c_str(), "f") != 0)
|
|
TestErrPrintf("Compound field name doesn't match!, field2_name=%s\n", field2_name.c_str());
|
|
|
|
// Get the 2nd field's datatype
|
|
DataType f2_type = ctype_check.getMemberDataType(1);
|
|
|
|
// Get the 2nd field's class, this 2nd field should have an array type
|
|
mclass = f2_type.getClass();
|
|
verify_val(mclass == H5T_ARRAY, true, "f2_type.getClass", __LINE__, __FILE__);
|
|
f2_type.close();
|
|
|
|
// Get the 2nd field, array of floats datatype, to check
|
|
ArrayType f2_atype_check = ctype_check.getMemberArrayType(1);
|
|
|
|
// Check the array rank
|
|
ndims = f2_atype_check.getArrayNDims();
|
|
verify_val(ndims, ARRAY1_RANK, "f2_atype_check.getArrayNDims", __LINE__, __FILE__);
|
|
|
|
// Get the array dimensions
|
|
HDmemset(rdims1, 0, sizeof(rdims1));
|
|
f2_atype_check.getArrayDims(rdims1);
|
|
|
|
// Check the array dimensions
|
|
for (ii = 0; ii < ndims; ii++)
|
|
if (rdims1[ii] != tdims1[ii]) {
|
|
TestErrPrintf("Array dimension information doesn't match!, rdims1[%d]=%" PRIuHSIZE
|
|
", tdims1[%d]=%" PRIuHSIZE "\n",
|
|
ii, rdims1[ii], ii, tdims1[ii]);
|
|
continue;
|
|
} // end if
|
|
|
|
// Close done datatypes
|
|
f2_atype_check.close();
|
|
ctype_check.close();
|
|
|
|
// Read dataset from disk
|
|
dataset.read(rdata, atype_check);
|
|
|
|
// Compare data read in
|
|
for (idxi = 0; idxi < SPACE1_DIM1; idxi++) {
|
|
for (idxj = 0; idxj < ARRAY1_DIM1; idxj++) {
|
|
if (wdata[idxi][idxj].i != rdata[idxi][idxj].i) {
|
|
TestErrPrintf("Array data information doesn't match!, wdata[%" PRIuHSIZE "][%" PRIuHSIZE
|
|
"].i=%d, "
|
|
"rdata[%" PRIuHSIZE "][%" PRIuHSIZE "].i=%d\n",
|
|
idxi, idxj, wdata[idxi][idxj].i, idxi, idxj, rdata[idxi][idxj].i);
|
|
continue;
|
|
} // end if
|
|
} // end for
|
|
} // end for
|
|
|
|
// Close all
|
|
atype_check.close();
|
|
dataset.close();
|
|
file1.close();
|
|
PASSED();
|
|
} // end of try block
|
|
catch (Exception &E) {
|
|
issue_fail_msg("test_array_compound_array", __LINE__, __FILE__, E.getCDetailMsg());
|
|
}
|
|
|
|
} // end test_array_compound_array()
|
|
|
|
/*
|
|
* Helper routine to demonstrate the issue in HDFFV-9562
|
|
*/
|
|
static H5::DataType
|
|
getArr()
|
|
{
|
|
hsize_t *dims = new hsize_t;
|
|
*dims = 5;
|
|
H5::ArrayType ret;
|
|
ret = H5::ArrayType(H5::PredType::NATIVE_INT, 1, dims);
|
|
delete dims;
|
|
return ret;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_array_assignment
|
|
*
|
|
* Purpose Tests the operator=
|
|
*
|
|
* Return None
|
|
*
|
|
* Programmer Binh-Minh Ribler (using C version)
|
|
* March, 2016
|
|
*
|
|
* Description:
|
|
* Used user's sample code in HDFFV-9562
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_array_assignment()
|
|
{
|
|
hsize_t sdims1[] = {SPACE1_DIM1};
|
|
SUBTEST("ArrayType::operator=");
|
|
|
|
try {
|
|
// Create File
|
|
H5File file1(FILENAME, H5F_ACC_TRUNC);
|
|
|
|
// Create dataspace for datasets
|
|
DataSpace space(SPACE1_RANK, sdims1, NULL);
|
|
|
|
/*
|
|
* Create an array datatype of compounds, arrtype. Each compound
|
|
* datatype, comptype, contains an integer and an array of floats,
|
|
* arrfltype.
|
|
*/
|
|
|
|
// Create a compound datatype
|
|
CompType comptype(static_cast<size_t>(24));
|
|
|
|
// Insert integer field
|
|
comptype.insertMember("i", 0, PredType::NATIVE_INT);
|
|
|
|
// Insert float array field
|
|
comptype.insertMember("a", 4, getArr());
|
|
|
|
// Create a dataset
|
|
DataSet dataset = file1.createDataSet("Dataset1", comptype, space);
|
|
|
|
// Close all
|
|
dataset.close();
|
|
comptype.close();
|
|
space.close();
|
|
file1.close();
|
|
|
|
PASSED();
|
|
} // end of try block
|
|
catch (Exception &E) {
|
|
issue_fail_msg("test_array_assignment", __LINE__, __FILE__, E.getCDetailMsg());
|
|
}
|
|
} // end test_array_assignment()
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_array_info
|
|
*
|
|
* Purpose Tests getting array information using the const methods.
|
|
*
|
|
* Return None
|
|
*
|
|
* Programmer Binh-Minh Ribler
|
|
* April, 2016
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_array_info()
|
|
{
|
|
SUBTEST("ArrayType Const Methods");
|
|
typedef struct { // Typedef for compound datatype */
|
|
int i;
|
|
float f[ARRAY1_DIM1];
|
|
} s1_t;
|
|
s1_t wdata[SPACE1_DIM1][ARRAY1_DIM1]; // Information to write
|
|
hsize_t sdims1[] = {SPACE1_DIM1};
|
|
hsize_t tdims1[] = {ARRAY1_DIM1};
|
|
int ii; // counting variables
|
|
hsize_t idxi, idxj, idxk; // dimension indicing variables
|
|
H5T_class_t mclass; // Datatype class for field
|
|
|
|
// Initialize array data to write
|
|
for (idxi = 0; idxi < SPACE1_DIM1; idxi++)
|
|
for (idxj = 0; idxj < ARRAY1_DIM1; idxj++) {
|
|
wdata[idxi][idxj].i = static_cast<int>(idxi * 10 + idxj);
|
|
for (idxk = 0; idxk < ARRAY1_DIM1; idxk++) {
|
|
float temp = static_cast<float>(idxi) * 10.0F + static_cast<float>(idxj) * 2.5F +
|
|
static_cast<float>(idxk);
|
|
wdata[idxi][idxj].f[idxk] = temp;
|
|
}
|
|
}
|
|
|
|
try {
|
|
// Create File
|
|
H5File file1(FILENAME, H5F_ACC_TRUNC);
|
|
|
|
// Create dataspace for datasets
|
|
DataSpace space(SPACE1_RANK, sdims1, NULL);
|
|
|
|
/*
|
|
* Create some array datatypes, then close the file.
|
|
*/
|
|
|
|
// Create an array of floats datatype
|
|
ArrayType arrfltype(PredType::NATIVE_FLOAT, ARRAY1_RANK, tdims1);
|
|
|
|
// Create an array datatype of the compound datatype
|
|
ArrayType arrtype(PredType::NATIVE_UINT, ARRAY1_RANK, tdims1);
|
|
|
|
// Create a dataset
|
|
DataSet dataset = file1.createDataSet("Dataset1", arrtype, space);
|
|
|
|
// Write dataset to disk
|
|
dataset.write(wdata, arrtype);
|
|
|
|
// Close array of floats field datatype
|
|
arrfltype.close();
|
|
|
|
// Close all
|
|
dataset.close();
|
|
arrtype.close();
|
|
space.close();
|
|
file1.close();
|
|
|
|
// Re-open file
|
|
file1.openFile(FILENAME, H5F_ACC_RDONLY);
|
|
|
|
// Open the dataset
|
|
dataset = file1.openDataSet("Dataset1");
|
|
|
|
/*
|
|
* Check the datatype array of compounds
|
|
*/
|
|
|
|
// Verify that it is an array of compounds
|
|
DataType dstype = dataset.getDataType();
|
|
mclass = dstype.getClass();
|
|
verify_val(mclass == H5T_ARRAY, true, "f2_type.getClass", __LINE__, __FILE__);
|
|
|
|
dstype.close();
|
|
|
|
{ // Let atype_check go out of scope
|
|
// Get the array datatype, declared as const
|
|
const ArrayType atype_check = dataset.getArrayType();
|
|
|
|
// Check the array rank with the const method
|
|
int ndims = atype_check.getArrayNDims();
|
|
verify_val(ndims, ARRAY1_RANK, "atype_check.getArrayNDims", __LINE__, __FILE__);
|
|
|
|
// Get the array dimensions with the const method
|
|
hsize_t rdims1[H5S_MAX_RANK];
|
|
atype_check.getArrayDims(rdims1);
|
|
|
|
// Check the array dimensions
|
|
for (ii = 0; ii < ndims; ii++)
|
|
if (rdims1[ii] != tdims1[ii]) {
|
|
TestErrPrintf("Array dimension information doesn't match!, rdims1[%d]=%" PRIuHSIZE
|
|
", tdims1[%d]=%" PRIuHSIZE "\n",
|
|
ii, rdims1[ii], ii, tdims1[ii]);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// Close all
|
|
dataset.close();
|
|
file1.close();
|
|
PASSED();
|
|
} // end of try block
|
|
catch (Exception &E) {
|
|
issue_fail_msg("test_array_info", __LINE__, __FILE__, E.getCDetailMsg());
|
|
}
|
|
|
|
} // end test_array_info()
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_array
|
|
*
|
|
* Purpose Main datatypes testing routine
|
|
*
|
|
* Return None
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
extern "C" void
|
|
test_array()
|
|
{
|
|
// Output message about test being performed
|
|
MESSAGE(5, ("Testing Array Datatypes\n"));
|
|
|
|
// Test array of compounds with array field
|
|
test_array_compound_array();
|
|
|
|
// Test operator= (HDFFV-9562)
|
|
test_array_assignment();
|
|
|
|
// Test const functions (HDFFV-9725)
|
|
test_array_info();
|
|
|
|
} // test_array()
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: cleanup_array
|
|
*
|
|
* Purpose Cleanup temporary test files
|
|
*
|
|
* Return None
|
|
*
|
|
* Programmer Binh-Minh Ribler (using C version)
|
|
* January, 2016
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
extern "C" void
|
|
cleanup_array()
|
|
{
|
|
HDremove(FILENAME.c_str());
|
|
} // cleanup_array
|