mirror of
https://github.com/HDFGroup/hdf5.git
synced 2024-12-27 08:01:04 +08:00
760 lines
27 KiB
C++
760 lines
27 KiB
C++
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* Copyright by The HDF Group. *
|
|
* 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
|
|
tcompound.cpp - HDF5 C++ testing the compound data type 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
|
|
|
|
/* Number of elements in each test */
|
|
#define NTESTELEM 100000
|
|
|
|
typedef struct complex_t {
|
|
double re;
|
|
double im;
|
|
} complex_t;
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_compound_1
|
|
*
|
|
* Purpose Tests various things about compound data types.
|
|
*
|
|
* Return None
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_compound_1()
|
|
{
|
|
// Output message about test being performed
|
|
SUBTEST("Compound Data Types");
|
|
try {
|
|
// Create an empty compound datatype
|
|
CompType complex_type(sizeof(complex_t));
|
|
|
|
// Add a couple of fields
|
|
complex_type.insertMember("real", HOFFSET(complex_t, re), PredType::NATIVE_DOUBLE);
|
|
complex_type.insertMember("imaginary", HOFFSET(complex_t, im), PredType::NATIVE_DOUBLE);
|
|
PASSED();
|
|
} // end of try block
|
|
|
|
catch (Exception &E) {
|
|
issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg());
|
|
}
|
|
} // test_compound_1()
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_compound_2
|
|
*
|
|
* Purpose Tests a compound type conversion where the source and
|
|
* destination are the same except for the order of the
|
|
* elements.
|
|
*
|
|
* Return None
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_compound_2()
|
|
{
|
|
typedef struct {
|
|
int a, b, c[4], d, e;
|
|
} src_typ_t;
|
|
typedef struct {
|
|
int e, d, c[4], b, a;
|
|
} dst_typ_t;
|
|
|
|
src_typ_t *s_ptr;
|
|
dst_typ_t *d_ptr;
|
|
const int nelmts = NTESTELEM;
|
|
const hsize_t four = 4;
|
|
int i;
|
|
unsigned char *buf = NULL, *orig = NULL, *bkg = NULL;
|
|
ArrayType *array_dt = NULL;
|
|
|
|
// Output message about test being performed
|
|
SUBTEST("Compound Element Reordering");
|
|
try {
|
|
// Sizes should be the same, but be careful just in case
|
|
buf = static_cast<unsigned char *>(malloc(nelmts * MAX(sizeof(src_typ_t), sizeof(dst_typ_t))));
|
|
bkg = static_cast<unsigned char *>(malloc(nelmts * sizeof(dst_typ_t)));
|
|
orig = static_cast<unsigned char *>(malloc(nelmts * sizeof(src_typ_t)));
|
|
for (i = 0; i < nelmts; i++) {
|
|
s_ptr = (reinterpret_cast<src_typ_t *>(orig)) + i;
|
|
s_ptr->a = i * 8 + 0;
|
|
s_ptr->b = i * 8 + 1;
|
|
s_ptr->c[0] = i * 8 + 2;
|
|
s_ptr->c[1] = i * 8 + 3;
|
|
s_ptr->c[2] = i * 8 + 4;
|
|
s_ptr->c[3] = i * 8 + 5;
|
|
s_ptr->d = i * 8 + 6;
|
|
s_ptr->e = i * 8 + 7;
|
|
}
|
|
memcpy(buf, orig, nelmts * sizeof(src_typ_t));
|
|
|
|
// Build hdf5 datatypes
|
|
array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four);
|
|
|
|
// Create an empty compound datatype
|
|
CompType st(sizeof(src_typ_t));
|
|
st.insertMember("a", HOFFSET(src_typ_t, a), PredType::NATIVE_INT);
|
|
st.insertMember("b", HOFFSET(src_typ_t, b), PredType::NATIVE_INT);
|
|
st.insertMember("c", HOFFSET(src_typ_t, c), *array_dt);
|
|
st.insertMember("d", HOFFSET(src_typ_t, d), PredType::NATIVE_INT);
|
|
st.insertMember("e", HOFFSET(src_typ_t, e), PredType::NATIVE_INT);
|
|
array_dt->close();
|
|
delete array_dt;
|
|
|
|
array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four);
|
|
|
|
// Create an empty compound datatype
|
|
CompType dt(sizeof(dst_typ_t));
|
|
dt.insertMember("a", HOFFSET(dst_typ_t, a), PredType::NATIVE_INT);
|
|
dt.insertMember("b", HOFFSET(dst_typ_t, b), PredType::NATIVE_INT);
|
|
dt.insertMember("c", HOFFSET(dst_typ_t, c), *array_dt);
|
|
dt.insertMember("d", HOFFSET(dst_typ_t, d), PredType::NATIVE_INT);
|
|
dt.insertMember("e", HOFFSET(dst_typ_t, e), PredType::NATIVE_INT);
|
|
array_dt->close();
|
|
|
|
// Perform the conversion
|
|
st.convert(dt, static_cast<size_t>(nelmts), buf, bkg);
|
|
|
|
// Compare results
|
|
for (i = 0; i < nelmts; i++) {
|
|
s_ptr = (reinterpret_cast<src_typ_t *>(orig)) + i;
|
|
d_ptr = (reinterpret_cast<dst_typ_t *>(buf)) + i;
|
|
if (s_ptr->a != d_ptr->a || s_ptr->b != d_ptr->b || s_ptr->c[0] != d_ptr->c[0] ||
|
|
s_ptr->c[1] != d_ptr->c[1] || s_ptr->c[2] != d_ptr->c[2] || s_ptr->c[3] != d_ptr->c[3] ||
|
|
s_ptr->d != d_ptr->d || s_ptr->e != d_ptr->e) {
|
|
H5_FAILED();
|
|
cerr << " i=" << i << endl;
|
|
cerr << " src={a=" << s_ptr->a << ", b=" << s_ptr->b << "c=[" << s_ptr->c[0] << ","
|
|
<< s_ptr->c[1] << "," << s_ptr->c[2] << "," << s_ptr->c[3] << ", d=" << s_ptr->d
|
|
<< ", e=" << s_ptr->e << "}" << endl;
|
|
cerr << " dst={a=" << s_ptr->a << ", b=" << s_ptr->b << "c=[" << s_ptr->c[0] << ","
|
|
<< s_ptr->c[1] << "," << s_ptr->c[2] << "," << s_ptr->c[3] << ", d=" << s_ptr->d
|
|
<< ", e=" << s_ptr->e << "}" << endl;
|
|
}
|
|
}
|
|
// Release resources
|
|
free(buf);
|
|
free(bkg);
|
|
free(orig);
|
|
s_ptr = NULL;
|
|
d_ptr = NULL;
|
|
st.close();
|
|
dt.close();
|
|
PASSED();
|
|
} // end of try block
|
|
|
|
catch (Exception &E) {
|
|
issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg());
|
|
}
|
|
|
|
delete array_dt;
|
|
} // test_compound_2()
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_compound_3
|
|
*
|
|
* Purpose Tests compound conversions where the source and destination
|
|
* are the same except the destination is missing a couple
|
|
* members which appear in the source.
|
|
*
|
|
* Return None
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_compound_3()
|
|
{
|
|
typedef struct {
|
|
int a, b, c[4], d, e;
|
|
} src_typ_t;
|
|
typedef struct {
|
|
int a, c[4], e;
|
|
} dst_typ_t;
|
|
|
|
src_typ_t *s_ptr;
|
|
dst_typ_t *d_ptr;
|
|
int i;
|
|
const int nelmts = NTESTELEM;
|
|
const hsize_t four = 4;
|
|
unsigned char *buf = NULL, *orig = NULL, *bkg = NULL;
|
|
ArrayType *array_dt = NULL;
|
|
|
|
// Output message about test being performed
|
|
SUBTEST("Compound Datatype Subset Conversions");
|
|
try {
|
|
/* Initialize */
|
|
buf = static_cast<unsigned char *>(malloc(nelmts * MAX(sizeof(src_typ_t), sizeof(dst_typ_t))));
|
|
bkg = static_cast<unsigned char *>(malloc(nelmts * sizeof(dst_typ_t)));
|
|
orig = static_cast<unsigned char *>(malloc(nelmts * sizeof(src_typ_t)));
|
|
for (i = 0; i < nelmts; i++) {
|
|
s_ptr = (reinterpret_cast<src_typ_t *>(orig)) + i;
|
|
s_ptr->a = i * 8 + 0;
|
|
s_ptr->b = i * 8 + 1;
|
|
s_ptr->c[0] = i * 8 + 2;
|
|
s_ptr->c[1] = i * 8 + 3;
|
|
s_ptr->c[2] = i * 8 + 4;
|
|
s_ptr->c[3] = i * 8 + 5;
|
|
s_ptr->d = i * 8 + 6;
|
|
s_ptr->e = i * 8 + 7;
|
|
}
|
|
memcpy(buf, orig, nelmts * sizeof(src_typ_t));
|
|
|
|
/* Build hdf5 datatypes */
|
|
array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four);
|
|
|
|
// Create an empty compound datatype
|
|
CompType st(sizeof(src_typ_t));
|
|
st.insertMember("a", HOFFSET(src_typ_t, a), PredType::NATIVE_INT);
|
|
st.insertMember("b", HOFFSET(src_typ_t, b), PredType::NATIVE_INT);
|
|
st.insertMember("c", HOFFSET(src_typ_t, c), *array_dt);
|
|
st.insertMember("d", HOFFSET(src_typ_t, d), PredType::NATIVE_INT);
|
|
st.insertMember("e", HOFFSET(src_typ_t, e), PredType::NATIVE_INT);
|
|
array_dt->close();
|
|
delete array_dt;
|
|
|
|
array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four);
|
|
|
|
// Create an empty compound datatype
|
|
CompType dt(sizeof(dst_typ_t));
|
|
dt.insertMember("a", HOFFSET(dst_typ_t, a), PredType::NATIVE_INT);
|
|
dt.insertMember("c", HOFFSET(dst_typ_t, c), *array_dt);
|
|
dt.insertMember("e", HOFFSET(dst_typ_t, e), PredType::NATIVE_INT);
|
|
array_dt->close();
|
|
|
|
/* Perform the conversion */
|
|
st.convert(dt, static_cast<size_t>(nelmts), buf, bkg);
|
|
|
|
/* Compare results */
|
|
for (i = 0; i < nelmts; i++) {
|
|
s_ptr = (reinterpret_cast<src_typ_t *>(orig)) + i;
|
|
d_ptr = (reinterpret_cast<dst_typ_t *>(buf)) + i;
|
|
if (s_ptr->a != d_ptr->a || s_ptr->c[0] != d_ptr->c[0] || s_ptr->c[1] != d_ptr->c[1] ||
|
|
s_ptr->c[2] != d_ptr->c[2] || s_ptr->c[3] != d_ptr->c[3] || s_ptr->e != d_ptr->e) {
|
|
H5_FAILED();
|
|
cerr << " i=" << i << endl;
|
|
cerr << " src={a=" << s_ptr->a << ", b=" << s_ptr->b << ", c=[" << s_ptr->c[0] << ","
|
|
<< s_ptr->c[1] << "," << s_ptr->c[2] << "," << s_ptr->c[3] << "], d=" << s_ptr->d
|
|
<< ", e=" << s_ptr->e << "}" << endl;
|
|
cerr << " dst={a=" << d_ptr->a << ", c=[" << d_ptr->c[0] << "," << d_ptr->c[1] << ","
|
|
<< d_ptr->c[2] << "," << d_ptr->c[3] << "], e=" << d_ptr->e << "}" << endl;
|
|
}
|
|
}
|
|
|
|
/* Release resources */
|
|
free(buf);
|
|
free(bkg);
|
|
free(orig);
|
|
s_ptr = NULL;
|
|
d_ptr = NULL;
|
|
st.close();
|
|
dt.close();
|
|
PASSED();
|
|
} // end of try block
|
|
|
|
catch (Exception &E) {
|
|
issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg());
|
|
}
|
|
|
|
delete array_dt;
|
|
} // test_compound_3()
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_compound_4
|
|
*
|
|
* Purpose Tests compound conversions when the destination has the same
|
|
* fields as the source but one or more of the fields are
|
|
* smaller.
|
|
*
|
|
* Return None
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_compound_4()
|
|
{
|
|
|
|
typedef struct {
|
|
int a, b, c[4], d, e;
|
|
} src_typ_t;
|
|
|
|
typedef struct {
|
|
short b;
|
|
int a, c[4];
|
|
short d;
|
|
int e;
|
|
} dst_typ_t;
|
|
|
|
src_typ_t *s_ptr;
|
|
dst_typ_t *d_ptr;
|
|
int i;
|
|
const int nelmts = NTESTELEM;
|
|
const hsize_t four = 4;
|
|
unsigned char *buf = NULL, *orig = NULL, *bkg = NULL;
|
|
ArrayType *array_dt = NULL;
|
|
|
|
// Output message about test being performed
|
|
SUBTEST("Compound Element Shrinking & Reordering");
|
|
try {
|
|
/* Sizes should be the same, but be careful just in case */
|
|
buf = static_cast<unsigned char *>(malloc(nelmts * MAX(sizeof(src_typ_t), sizeof(dst_typ_t))));
|
|
bkg = static_cast<unsigned char *>(malloc(nelmts * sizeof(dst_typ_t)));
|
|
orig = static_cast<unsigned char *>(malloc(nelmts * sizeof(src_typ_t)));
|
|
for (i = 0; i < nelmts; i++) {
|
|
s_ptr = (reinterpret_cast<src_typ_t *>(orig)) + i;
|
|
s_ptr->a = i * 8 + 0;
|
|
s_ptr->b = (i * 8 + 1) & 0x7fff;
|
|
s_ptr->c[0] = i * 8 + 2;
|
|
s_ptr->c[1] = i * 8 + 3;
|
|
s_ptr->c[2] = i * 8 + 4;
|
|
s_ptr->c[3] = i * 8 + 5;
|
|
s_ptr->d = (i * 8 + 6) & 0x7fff;
|
|
s_ptr->e = i * 8 + 7;
|
|
}
|
|
memcpy(buf, orig, nelmts * sizeof(src_typ_t));
|
|
|
|
/* Build hdf5 datatypes */
|
|
array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four);
|
|
|
|
// Create an empty compound datatype
|
|
CompType st(sizeof(src_typ_t));
|
|
st.insertMember("a", HOFFSET(src_typ_t, a), PredType::NATIVE_INT);
|
|
st.insertMember("b", HOFFSET(src_typ_t, b), PredType::NATIVE_INT);
|
|
st.insertMember("c", HOFFSET(src_typ_t, c), *array_dt);
|
|
st.insertMember("d", HOFFSET(src_typ_t, d), PredType::NATIVE_INT);
|
|
st.insertMember("e", HOFFSET(src_typ_t, e), PredType::NATIVE_INT);
|
|
array_dt->close();
|
|
delete array_dt;
|
|
|
|
array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four);
|
|
|
|
// Create an empty compound datatype
|
|
CompType dt(sizeof(dst_typ_t));
|
|
dt.insertMember("a", HOFFSET(dst_typ_t, a), PredType::NATIVE_INT);
|
|
dt.insertMember("b", HOFFSET(dst_typ_t, b), PredType::NATIVE_SHORT);
|
|
dt.insertMember("c", HOFFSET(dst_typ_t, c), *array_dt);
|
|
dt.insertMember("d", HOFFSET(dst_typ_t, d), PredType::NATIVE_SHORT);
|
|
dt.insertMember("e", HOFFSET(dst_typ_t, e), PredType::NATIVE_INT);
|
|
array_dt->close();
|
|
|
|
/* Perform the conversion */
|
|
st.convert(dt, static_cast<size_t>(nelmts), buf, bkg);
|
|
|
|
/* Compare results */
|
|
for (i = 0; i < nelmts; i++) {
|
|
s_ptr = (reinterpret_cast<src_typ_t *>(orig)) + i;
|
|
d_ptr = (reinterpret_cast<dst_typ_t *>(buf)) + i;
|
|
if (s_ptr->a != d_ptr->a || s_ptr->b != d_ptr->b || s_ptr->c[0] != d_ptr->c[0] ||
|
|
s_ptr->c[1] != d_ptr->c[1] || s_ptr->c[2] != d_ptr->c[2] || s_ptr->c[3] != d_ptr->c[3] ||
|
|
s_ptr->d != d_ptr->d || s_ptr->e != d_ptr->e) {
|
|
H5_FAILED();
|
|
cerr << " i=" << i << endl;
|
|
cerr << " src={a=" << s_ptr->a << ", b=" << s_ptr->b << "c=[" << s_ptr->c[0] << ","
|
|
<< s_ptr->c[1] << "," << s_ptr->c[2] << "," << s_ptr->c[3] << ", d=" << s_ptr->d
|
|
<< ", e=" << s_ptr->e << "}" << endl;
|
|
cerr << " dst={a=" << d_ptr->a << ", b=" << d_ptr->b << "c=[" << d_ptr->c[0] << ","
|
|
<< d_ptr->c[1] << "," << d_ptr->c[2] << "," << d_ptr->c[3] << ", d=" << d_ptr->d
|
|
<< ", e=" << d_ptr->e << "}" << endl;
|
|
} // if
|
|
} // for
|
|
|
|
/* Release resources */
|
|
free(buf);
|
|
free(bkg);
|
|
free(orig);
|
|
s_ptr = NULL;
|
|
d_ptr = NULL;
|
|
st.close();
|
|
dt.close();
|
|
PASSED();
|
|
} // end of try block
|
|
|
|
catch (Exception &E) {
|
|
issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg());
|
|
}
|
|
|
|
delete array_dt;
|
|
} // test_compound_4()
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_compound_5
|
|
*
|
|
* Purpose Many versions of HDF5 have a bug in the optimized compound
|
|
* datatype conversion function, H5T_conv_struct_opt(), which
|
|
* is triggered when the top-level type contains a struct
|
|
* which must undergo a conversion.
|
|
*
|
|
* Return None
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_compound_5()
|
|
{
|
|
typedef struct {
|
|
char name[16];
|
|
short tdim;
|
|
short coll_ids[4];
|
|
} src_typ_t;
|
|
|
|
typedef struct {
|
|
char name[16];
|
|
short tdim;
|
|
int coll_ids[4];
|
|
} dst_typ_t;
|
|
|
|
hsize_t dims[1] = {4};
|
|
src_typ_t src[2] = {{"one", 102, {104, 105, 106, 107}}, {"two", 202, {204, 205, 206, 207}}};
|
|
dst_typ_t *dst;
|
|
void *buf = calloc(2, sizeof(dst_typ_t));
|
|
void *bkg = calloc(2, sizeof(dst_typ_t));
|
|
ArrayType *array_dt = NULL;
|
|
|
|
// Output message about test being performed
|
|
SUBTEST("Optimized Struct Converter");
|
|
try {
|
|
|
|
/* Build datatypes */
|
|
array_dt = new ArrayType(PredType::NATIVE_SHORT, 1, dims);
|
|
CompType short_array(4 * sizeof(short));
|
|
short_array.insertMember("_", 0, *array_dt);
|
|
array_dt->close();
|
|
delete array_dt;
|
|
|
|
CompType int_array(4 * sizeof(int));
|
|
array_dt = new ArrayType(PredType::NATIVE_INT, 1, dims);
|
|
int_array.insertMember("_", 0, *array_dt);
|
|
array_dt->close();
|
|
|
|
StrType strg(PredType::C_S1, 16);
|
|
CompType src_type(sizeof(src_typ_t));
|
|
src_type.insertMember("name", HOFFSET(src_typ_t, name), strg);
|
|
src_type.insertMember("tdim", HOFFSET(src_typ_t, tdim), PredType::NATIVE_SHORT);
|
|
src_type.insertMember("coll_ids", HOFFSET(src_typ_t, coll_ids), short_array);
|
|
|
|
CompType dst_type(sizeof(dst_typ_t));
|
|
dst_type.insertMember("name", HOFFSET(dst_typ_t, name), strg);
|
|
dst_type.insertMember("tdim", HOFFSET(dst_typ_t, tdim), PredType::NATIVE_SHORT);
|
|
dst_type.insertMember("coll_ids", HOFFSET(dst_typ_t, coll_ids), int_array);
|
|
|
|
/* Convert data */
|
|
memcpy(buf, src, sizeof(src));
|
|
src_type.convert(dst_type, 2, buf, bkg);
|
|
dst = static_cast<dst_typ_t *>(buf);
|
|
|
|
/* Cleanup */
|
|
src_type.close();
|
|
dst_type.close();
|
|
strg.close();
|
|
short_array.close();
|
|
int_array.close();
|
|
|
|
/* Check results */
|
|
if (memcmp(src[1].name, dst[1].name, sizeof(src[1].name)) != 0 || src[1].tdim != dst[1].tdim ||
|
|
src[1].coll_ids[0] != dst[1].coll_ids[0] || src[1].coll_ids[1] != dst[1].coll_ids[1] ||
|
|
src[1].coll_ids[2] != dst[1].coll_ids[2] || src[1].coll_ids[3] != dst[1].coll_ids[3]) {
|
|
H5_FAILED();
|
|
}
|
|
|
|
/* Free memory buffers */
|
|
free(buf);
|
|
free(bkg);
|
|
dst = NULL;
|
|
PASSED();
|
|
} // end of try block
|
|
|
|
catch (Exception &E) {
|
|
issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg());
|
|
}
|
|
|
|
delete array_dt;
|
|
} // test_compound_5()
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_compound_6
|
|
*
|
|
* Purpose Tests compound conversions when the destination has the same
|
|
* fields as the source but one or more of the fields are
|
|
* larger.
|
|
*
|
|
* Return None
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_compound_6()
|
|
{
|
|
typedef struct {
|
|
short b;
|
|
short d;
|
|
} src_typ_t;
|
|
|
|
typedef struct {
|
|
long b;
|
|
long d;
|
|
} dst_typ_t;
|
|
|
|
src_typ_t *s_ptr;
|
|
dst_typ_t *d_ptr;
|
|
int i;
|
|
const int nelmts = NTESTELEM;
|
|
unsigned char *buf = NULL, *orig = NULL, *bkg = NULL;
|
|
|
|
// Output message about test being performed
|
|
SUBTEST("Compound Element Growing");
|
|
try {
|
|
/* Sizes should be the same, but be careful just in case */
|
|
buf = static_cast<unsigned char *>(malloc(nelmts * MAX(sizeof(src_typ_t), sizeof(dst_typ_t))));
|
|
bkg = static_cast<unsigned char *>(malloc(nelmts * sizeof(dst_typ_t)));
|
|
orig = static_cast<unsigned char *>(malloc(nelmts * sizeof(src_typ_t)));
|
|
for (i = 0; i < nelmts; i++) {
|
|
s_ptr = (reinterpret_cast<src_typ_t *>(orig)) + i;
|
|
s_ptr->b = (i * 8 + 1) & 0x7fff;
|
|
s_ptr->d = (i * 8 + 6) & 0x7fff;
|
|
}
|
|
memcpy(buf, orig, nelmts * sizeof(src_typ_t));
|
|
|
|
/* Build hdf5 datatypes */
|
|
CompType st(sizeof(src_typ_t));
|
|
st.insertMember("b", HOFFSET(src_typ_t, b), PredType::NATIVE_SHORT);
|
|
st.insertMember("d", HOFFSET(src_typ_t, d), PredType::NATIVE_SHORT);
|
|
|
|
CompType dt(sizeof(dst_typ_t));
|
|
dt.insertMember("b", HOFFSET(dst_typ_t, b), PredType::NATIVE_LONG);
|
|
dt.insertMember("d", HOFFSET(dst_typ_t, d), PredType::NATIVE_LONG);
|
|
|
|
/* Perform the conversion */
|
|
st.convert(dt, static_cast<size_t>(nelmts), buf, bkg);
|
|
|
|
/* Compare results */
|
|
for (i = 0; i < nelmts; i++) {
|
|
s_ptr = (reinterpret_cast<src_typ_t *>(orig)) + i;
|
|
d_ptr = (reinterpret_cast<dst_typ_t *>(buf)) + i;
|
|
if (s_ptr->b != d_ptr->b || s_ptr->d != d_ptr->d) {
|
|
H5_FAILED();
|
|
cerr << " i=" << i << endl;
|
|
cerr << " src={b=" << s_ptr->b << ", d=" << s_ptr->d << "}" << endl;
|
|
cerr << " dst={b=" << d_ptr->b << ", d=" << d_ptr->d << "}" << endl;
|
|
}
|
|
}
|
|
|
|
/* Release resources */
|
|
free(buf);
|
|
free(bkg);
|
|
free(orig);
|
|
s_ptr = NULL;
|
|
d_ptr = NULL;
|
|
st.close();
|
|
dt.close();
|
|
PASSED();
|
|
} // end of try block
|
|
|
|
catch (Exception &E) {
|
|
issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg());
|
|
}
|
|
} // test_compound_6()
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_compound_7
|
|
*
|
|
* Purpose Tests inserting fields into compound datatypes when the field
|
|
* overlaps the end of the compound datatype.
|
|
*
|
|
* Return None
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static void
|
|
test_compound_7()
|
|
{
|
|
typedef struct {
|
|
int a;
|
|
float b;
|
|
long c;
|
|
} s1_typ_t;
|
|
|
|
typedef struct {
|
|
int a;
|
|
float b;
|
|
long c;
|
|
double d;
|
|
} s2_typ_t;
|
|
|
|
// Output message about test being performed
|
|
SUBTEST("Compound Element Insertion");
|
|
try {
|
|
CompType tid1(sizeof(s1_typ_t));
|
|
|
|
tid1.insertMember("a", HOFFSET(s1_typ_t, a), PredType::NATIVE_INT);
|
|
tid1.insertMember("b", HOFFSET(s1_typ_t, b), PredType::NATIVE_FLOAT);
|
|
tid1.insertMember("c", HOFFSET(s1_typ_t, c), PredType::NATIVE_LONG);
|
|
|
|
size_t type_size = tid1.getSize();
|
|
verify_val(type_size, sizeof(s1_typ_t), "DataType::getSize", __LINE__, __FILE__);
|
|
|
|
CompType tid2;
|
|
tid2.copy(tid1);
|
|
|
|
type_size = tid2.getSize();
|
|
verify_val_noteq(type_size, sizeof(s2_typ_t), "DataType::getSize", __LINE__, __FILE__);
|
|
|
|
/* Should not be able to insert field past end of compound datatype */
|
|
try {
|
|
tid2.insertMember("d", HOFFSET(s2_typ_t, d), PredType::NATIVE_DOUBLE);
|
|
// Should FAIL but didn't, so throw an invalid action exception
|
|
throw InvalidActionException("CompType::insertMember",
|
|
"Attempted to insert field past end of compound data type.");
|
|
}
|
|
catch (DataTypeIException &err) {
|
|
}
|
|
|
|
/* Release resources */
|
|
tid1.close();
|
|
tid2.close();
|
|
PASSED();
|
|
} // end of try block
|
|
|
|
catch (Exception &E) {
|
|
issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg());
|
|
}
|
|
} // test_compound_7()
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_compound_set_size
|
|
*
|
|
* Purpose Tests member function setSize() on compound datatype
|
|
*
|
|
* Return None
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
const H5std_string COMPFILE("tcompound_types.h5");
|
|
|
|
static void
|
|
test_compound_set_size()
|
|
{
|
|
typedef struct {
|
|
int a, b, c[4], d, e;
|
|
} src_typ_t;
|
|
|
|
// Output message about test being performed
|
|
SUBTEST("Setting Size on Compound Datatype");
|
|
try {
|
|
// Create File
|
|
H5File file(COMPFILE, H5F_ACC_TRUNC);
|
|
|
|
// Create a compound datatype
|
|
CompType dtype(sizeof(src_typ_t));
|
|
|
|
dtype.insertMember("a", HOFFSET(src_typ_t, a), PredType::NATIVE_INT);
|
|
dtype.insertMember("b", HOFFSET(src_typ_t, b), PredType::NATIVE_FLOAT);
|
|
dtype.insertMember("c", HOFFSET(src_typ_t, c), PredType::NATIVE_LONG);
|
|
dtype.insertMember("d", HOFFSET(src_typ_t, d), PredType::NATIVE_DOUBLE);
|
|
|
|
// Verify that the compound is not packed
|
|
// bool packed = dtype.packed(); // not until C library provides API
|
|
// verify_val(packed, FALSE, "DataType::packed", __LINE__, __FILE__);
|
|
|
|
dtype.commit(file, "dtype");
|
|
|
|
// Close the type and file
|
|
dtype.close();
|
|
file.close();
|
|
|
|
// Open the file for read/write
|
|
file.openFile(COMPFILE, H5F_ACC_RDWR);
|
|
|
|
// Open the data type "dtype"
|
|
CompType dtype_tmp = file.openCompType("dtype");
|
|
|
|
// Make a copy of the data type
|
|
dtype.copy(dtype_tmp);
|
|
|
|
// Verify that the compound is not packed
|
|
// packed = dtype_tmp.packed(); // not until C library provides API
|
|
// verify_val(packed, FALSE, "DataType::packed", __LINE__, __FILE__);
|
|
|
|
// Expand the type, and verify that it became unpacked
|
|
dtype.setSize(33);
|
|
// packed = dtype.packed(); // not until C library provides API
|
|
// verify_val(packed, FALSE, "DataType::packed", __LINE__, __FILE__);
|
|
|
|
// Verify setSize() actually set size
|
|
size_t new_size = dtype.getSize();
|
|
verify_val(static_cast<long>(new_size), 33, "DataType::getSize", __LINE__, __FILE__);
|
|
|
|
// Shrink the type, and verify that it became packed
|
|
dtype.setSize(32);
|
|
// packed = dtype.packed(); // not until C library provides API
|
|
// verify_val(packed, TRUE, "DataType::packed", __LINE__, __FILE__);
|
|
|
|
// Verify setSize() actually set size again
|
|
new_size = dtype.getSize();
|
|
verify_val(static_cast<long>(new_size), 32, "DataType::getSize", __LINE__, __FILE__);
|
|
|
|
/* Close types and file */
|
|
dtype_tmp.close();
|
|
dtype.close();
|
|
file.close();
|
|
|
|
PASSED();
|
|
} // end of try block
|
|
|
|
catch (Exception &E) {
|
|
issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg());
|
|
}
|
|
} // test_compound_set_size()
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: test_compound
|
|
*
|
|
* Purpose Main compound datatype testing routine
|
|
*
|
|
* Return None
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
extern "C" void
|
|
test_compound()
|
|
{
|
|
// Output message about test being performed
|
|
MESSAGE(5, ("Testing Compound Data Type operations\n"));
|
|
|
|
test_compound_1(); // various things about compound data types
|
|
test_compound_2(); // compound element reordering
|
|
test_compound_3(); // compound datatype subset conversions
|
|
test_compound_4(); // compound element shrinking & reordering
|
|
test_compound_5(); // optimized struct converter
|
|
test_compound_6(); // compound element growing
|
|
test_compound_7(); // compound element insertion
|
|
test_compound_set_size(); // set size on compound data types
|
|
} // test_compound()
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: cleanup_compound
|
|
*
|
|
* Purpose Cleanup temporary test files - nothing at this time.
|
|
*
|
|
* Return None
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
extern "C" void
|
|
cleanup_compound()
|
|
{
|
|
HDremove(COMPFILE.c_str());
|
|
} // cleanup_file
|