mirror of
https://github.com/HDFGroup/hdf5.git
synced 2024-11-27 02:10:55 +08:00
[svn-r469] Changes since 19980707
---------------------- ./bin/trace ./src/H5.c Added tracing support for H5S_seloper_t and H5S_class_t. ./src/H5Sselect.c ./src/H5S.c Added tracing statements that weren't inserted previously because of formatting problems. ./src/H5T.c ./src/H5Tconv.c ./src/H5Tpkg.h ./src/H5Tprivate.h ./src/H5Tpublic.h ./test/cmpd_dset.c Added H5Tinsert_array() for inserting an array member into a compound data type. Added support to the struct conversion function for member arrays. The index permutation is not supported yet in the conversion (source and destination must have the same permutations).
This commit is contained in:
parent
a8e53d7884
commit
6a1bea937d
@ -35,6 +35,8 @@ $Source = "";
|
||||
"off_t" => "o",
|
||||
"H5P_class_t" => "p",
|
||||
"char*" => "s",
|
||||
"H5S_class_t" => "Sc",
|
||||
"H5S_seloper_t" => "Ss",
|
||||
"H5T_cset_t", => "Tc",
|
||||
"H5T_norm_t" => "Tn",
|
||||
"H5T_order_t" => "To",
|
||||
|
53
src/H5.c
53
src/H5.c
@ -53,6 +53,7 @@ FILE *fdopen(int fd, const char *mode);
|
||||
#include <H5Iprivate.h> /*atoms */
|
||||
#include <H5MMprivate.h> /*memory management */
|
||||
#include <H5Pprivate.h> /*property lists */
|
||||
#include <H5Sprivate.h> /*data spaces */
|
||||
#include <H5Tprivate.h> /*data types */
|
||||
#include <H5Zprivate.h> /*compression */
|
||||
|
||||
@ -1518,6 +1519,58 @@ H5_trace (hbool_t returning, const char *func, const char *type, ...)
|
||||
}
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
switch (type[1]) {
|
||||
case 'c':
|
||||
if (ptr) {
|
||||
fprintf(out, "0x%lx", (unsigned long)vp);
|
||||
} else {
|
||||
H5S_class_t cls = va_arg(ap, H5S_class_t);
|
||||
switch (cls) {
|
||||
case H5S_NO_CLASS:
|
||||
fprintf(out, "H5S_NO_CLASS");
|
||||
break;
|
||||
case H5S_SCALAR:
|
||||
fprintf(out, "H5S_SCALAR");
|
||||
break;
|
||||
case H5S_SIMPLE:
|
||||
fprintf(out, "H5S_SIMPLE");
|
||||
break;
|
||||
case H5S_COMPLEX:
|
||||
fprintf(out, "H5S_COMPLEX");
|
||||
break;
|
||||
default:
|
||||
fprintf(out, "%ld", (long)cls);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (ptr) {
|
||||
fprintf(out, "0x%lx", (unsigned long)vp);
|
||||
} else {
|
||||
H5S_seloper_t so = va_arg(ap, H5S_seloper_t);
|
||||
switch (so) {
|
||||
case H5S_NOOP:
|
||||
fprintf(out, "H5S_NOOP");
|
||||
break;
|
||||
case H5S_SELECT_SET:
|
||||
fprintf(out, "H5S_SELECT_SET");
|
||||
break;
|
||||
default:
|
||||
fprintf(out, "%ld", (long)so);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(out, "BADTYPE(F%c)", type[1]);
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (ptr) {
|
||||
fprintf (out, "0x%lx", (unsigned long)vp);
|
||||
|
@ -160,14 +160,16 @@ H5O_dtype_decode_helper(const uint8 **pp, H5T_t *dt)
|
||||
dt->u.compnd.nmembs = flags & 0xffff;
|
||||
assert(dt->u.compnd.nmembs > 0);
|
||||
dt->u.compnd.nalloc = dt->u.compnd.nmembs;
|
||||
dt->u.compnd.memb = H5MM_calloc(dt->u.compnd.nalloc*sizeof(H5T_member_t));
|
||||
dt->u.compnd.memb = H5MM_calloc(dt->u.compnd.nalloc*
|
||||
sizeof(H5T_member_t));
|
||||
if (NULL==dt->u.compnd.memb) {
|
||||
HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL,
|
||||
"memory allocation failed");
|
||||
}
|
||||
for (i = 0; i < dt->u.compnd.nmembs; i++) {
|
||||
dt->u.compnd.memb[i].name = H5MM_xstrdup((const char *)*pp);
|
||||
*pp += ((HDstrlen((const char *)*pp) + 8) / 8) * 8; /*multiple of 8 w/ null terminator */
|
||||
/*multiple of 8 w/ null terminator */
|
||||
*pp += ((HDstrlen((const char *)*pp) + 8) / 8) * 8;
|
||||
UINT32DECODE(*pp, dt->u.compnd.memb[i].offset);
|
||||
dt->u.compnd.memb[i].ndims = *(*pp)++;
|
||||
assert(dt->u.compnd.memb[i].ndims <= 4);
|
||||
@ -194,6 +196,12 @@ H5O_dtype_decode_helper(const uint8 **pp, H5T_t *dt)
|
||||
HRETURN_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL,
|
||||
"can't decode member type");
|
||||
}
|
||||
|
||||
/* Total member size */
|
||||
dt->u.compnd.memb[i].size = dt->u.compnd.memb[i].type->size;
|
||||
for (j=0; j<dt->u.compnd.memb[i].ndims; j++) {
|
||||
dt->u.compnd.memb[i].size *= dt->u.compnd.memb[i].dim[j];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -138,12 +138,13 @@ done:
|
||||
REVISION LOG
|
||||
--------------------------------------------------------------------------*/
|
||||
hid_t
|
||||
H5Screate(H5S_class_t type)
|
||||
H5Screate (H5S_class_t type)
|
||||
{
|
||||
H5S_t *new_ds=NULL;
|
||||
hid_t ret_value = FAIL;
|
||||
|
||||
FUNC_ENTER(H5Screate, FAIL);
|
||||
H5TRACE1("i","Sc",type);
|
||||
|
||||
/* Check args */
|
||||
if(type<=H5S_NO_CLASS || type> H5S_SIMPLE) /* don't allow complex dataspace yet */
|
||||
|
@ -192,6 +192,7 @@ H5Sselect_hyperslab (hid_t spaceid, H5S_seloper_t op,
|
||||
herr_t ret_value=FAIL; /* return value */
|
||||
|
||||
FUNC_ENTER (H5Sselect_hyperslab, FAIL);
|
||||
H5TRACE6("e","iSs*Hs*h*h*h",spaceid,op,start,_stride,count,_block);
|
||||
|
||||
/* Check args */
|
||||
if (H5_DATASPACE != H5I_group(spaceid) ||
|
||||
@ -332,6 +333,7 @@ H5Sselect_npoints (hid_t spaceid)
|
||||
hsize_t ret_value=0; /* return value */
|
||||
|
||||
FUNC_ENTER (H5Sselect_npoints, 0);
|
||||
H5TRACE1("h","i",spaceid);
|
||||
|
||||
/* Check args */
|
||||
if (H5_DATASPACE != H5I_group(spaceid) ||
|
||||
|
116
src/H5T.c
116
src/H5T.c
@ -2761,7 +2761,79 @@ H5Tinsert (hid_t parent_id, const char *name, size_t offset, hid_t member_id)
|
||||
}
|
||||
|
||||
/* Insert */
|
||||
if (H5T_insert(parent, name, offset, member) < 0) {
|
||||
if (H5T_insert(parent, name, offset, 0, NULL, NULL, member) < 0) {
|
||||
HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL,
|
||||
"can't insert member");
|
||||
}
|
||||
|
||||
FUNC_LEAVE(SUCCEED);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5Tinsert_array
|
||||
*
|
||||
* Purpose: Adds another member to the compound data type PARENT_ID. The
|
||||
* new member has a NAME which must be unique within the
|
||||
* compound data type. The OFFSET argument defines the start of
|
||||
* the member in an instance of the compound data type and
|
||||
* MEMBER_ID is the type of the new member. The member is an
|
||||
* array with NDIMS dimensionality and the size of the array is
|
||||
* DIMS. The total member size should be relatively small.
|
||||
*
|
||||
* Return: Success: SUCCEED
|
||||
*
|
||||
* Failure: FAIL
|
||||
*
|
||||
* Programmer: Robb Matzke
|
||||
* Tuesday, July 7, 1998
|
||||
*
|
||||
* Modifications:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5Tinsert_array (hid_t parent_id, const char *name, size_t offset,
|
||||
int ndims, const size_t *dim, const int *perm,
|
||||
hid_t member_id)
|
||||
{
|
||||
H5T_t *parent = NULL; /*the compound parent data type */
|
||||
H5T_t *member = NULL; /*the atomic member type */
|
||||
intn i;
|
||||
|
||||
FUNC_ENTER(H5Tinsert_array, FAIL);
|
||||
H5TRACE7("e","iszIs*z*Isi",parent_id,name,offset,ndims,dim,perm,member_id);
|
||||
|
||||
/* Check args */
|
||||
if (H5_DATATYPE != H5I_group(parent_id) ||
|
||||
NULL == (parent = H5I_object(parent_id)) ||
|
||||
H5T_COMPOUND != parent->type) {
|
||||
HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound data type");
|
||||
}
|
||||
if (H5T_STATE_TRANSIENT!=parent->state) {
|
||||
HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent type read-only");
|
||||
}
|
||||
if (!name || !*name) {
|
||||
HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no member name");
|
||||
}
|
||||
if (ndims<1 || ndims>4) {
|
||||
HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid dimensionality");
|
||||
}
|
||||
if (!dim) {
|
||||
HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no dimensions specified");
|
||||
}
|
||||
for (i=0; i<ndims; i++) {
|
||||
if (dim[i]<1) {
|
||||
HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid dimension");
|
||||
}
|
||||
}
|
||||
if (H5_DATATYPE != H5I_group(member_id) ||
|
||||
NULL == (member = H5I_object(member_id))) {
|
||||
HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
|
||||
}
|
||||
|
||||
/* Insert */
|
||||
if (H5T_insert(parent, name, offset, ndims, dim, perm, member) < 0) {
|
||||
HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL,
|
||||
"can't insert member");
|
||||
}
|
||||
@ -3781,9 +3853,12 @@ H5T_get_size(const H5T_t *dt)
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5T_insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member)
|
||||
H5T_insert(H5T_t *parent, const char *name, size_t offset, intn ndims,
|
||||
const size_t *dim, const intn *perm, const H5T_t *member)
|
||||
{
|
||||
intn i;
|
||||
intn idx, i;
|
||||
size_t total_size;
|
||||
|
||||
|
||||
FUNC_ENTER(H5T_insert, FAIL);
|
||||
|
||||
@ -3794,7 +3869,7 @@ H5T_insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member)
|
||||
assert(name && *name);
|
||||
|
||||
/* Does NAME already exist in PARENT? */
|
||||
for (i = 0; i < parent->u.compnd.nmembs; i++) {
|
||||
for (i=0; i<parent->u.compnd.nmembs; i++) {
|
||||
if (!HDstrcmp(parent->u.compnd.memb[i].name, name)) {
|
||||
HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL,
|
||||
"member name is not unique");
|
||||
@ -3802,12 +3877,13 @@ H5T_insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member)
|
||||
}
|
||||
|
||||
/* Does the new member overlap any existing member ? */
|
||||
for (i = 0; i < parent->u.compnd.nmembs; i++) {
|
||||
for (total_size=member->size, i=0; i<ndims; i++) total_size *= dim[i];
|
||||
for (i=0; i<parent->u.compnd.nmembs; i++) {
|
||||
if ((offset <= parent->u.compnd.memb[i].offset &&
|
||||
offset + member->size > parent->u.compnd.memb[i].offset) ||
|
||||
offset + total_size > parent->u.compnd.memb[i].offset) ||
|
||||
(parent->u.compnd.memb[i].offset <= offset &&
|
||||
parent->u.compnd.memb[i].offset +
|
||||
parent->u.compnd.memb[i].type->size > offset)) {
|
||||
parent->u.compnd.memb[i].size > offset)) {
|
||||
HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL,
|
||||
"member overlaps with another member");
|
||||
}
|
||||
@ -3827,11 +3903,16 @@ H5T_insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member)
|
||||
}
|
||||
|
||||
/* Add member to end of member array */
|
||||
i = parent->u.compnd.nmembs;
|
||||
parent->u.compnd.memb[i].name = H5MM_xstrdup(name);
|
||||
parent->u.compnd.memb[i].offset = offset;
|
||||
parent->u.compnd.memb[i].ndims = 0; /*defaults to scalar */
|
||||
parent->u.compnd.memb[i].type = H5T_copy (member, H5T_COPY_ALL);
|
||||
idx = parent->u.compnd.nmembs;
|
||||
parent->u.compnd.memb[idx].name = H5MM_xstrdup(name);
|
||||
parent->u.compnd.memb[idx].offset = offset;
|
||||
parent->u.compnd.memb[idx].size = total_size;
|
||||
parent->u.compnd.memb[idx].ndims = ndims;
|
||||
parent->u.compnd.memb[idx].type = H5T_copy (member, H5T_COPY_ALL);
|
||||
for (i=0; i<ndims; i++) {
|
||||
parent->u.compnd.memb[idx].dim[i] = dim[i];
|
||||
parent->u.compnd.memb[idx].perm[i] = perm?perm[i]:i;
|
||||
}
|
||||
|
||||
parent->u.compnd.nmembs++;
|
||||
FUNC_LEAVE(SUCCEED);
|
||||
@ -3868,7 +3949,7 @@ H5T_pack(H5T_t *dt)
|
||||
|
||||
if (H5T_COMPOUND == dt->type) {
|
||||
/* Recursively pack the members */
|
||||
for (i = 0; i < dt->u.compnd.nmembs; i++) {
|
||||
for (i=0; i<dt->u.compnd.nmembs; i++) {
|
||||
if (H5T_pack(dt->u.compnd.memb[i].type) < 0) {
|
||||
HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,
|
||||
"unable to pack part of a compound data type");
|
||||
@ -3877,9 +3958,9 @@ H5T_pack(H5T_t *dt)
|
||||
|
||||
/* Remove padding between members */
|
||||
H5T_sort_by_offset(dt);
|
||||
for (i = 0, offset = 0; i < dt->u.compnd.nmembs; i++) {
|
||||
for (i=0, offset=0; i<dt->u.compnd.nmembs; i++) {
|
||||
dt->u.compnd.memb[i].offset = offset;
|
||||
offset += H5T_get_size (dt->u.compnd.memb[i].type);
|
||||
offset += dt->u.compnd.memb[i].size;
|
||||
}
|
||||
|
||||
/* Change total size */
|
||||
@ -4043,6 +4124,11 @@ H5T_cmp(const H5T_t *dt1, const H5T_t *dt2)
|
||||
if (dt1->u.compnd.memb[idx1[i]].offset >
|
||||
dt2->u.compnd.memb[idx2[i]].offset) HGOTO_DONE(1);
|
||||
|
||||
if (dt1->u.compnd.memb[idx1[i]].size <
|
||||
dt2->u.compnd.memb[idx2[i]].size) HGOTO_DONE(-1);
|
||||
if (dt1->u.compnd.memb[idx1[i]].size >
|
||||
dt2->u.compnd.memb[idx2[i]].size) HGOTO_DONE(1);
|
||||
|
||||
if (dt1->u.compnd.memb[idx1[i]].ndims <
|
||||
dt2->u.compnd.memb[idx2[i]].ndims) HGOTO_DONE(-1);
|
||||
if (dt1->u.compnd.memb[idx1[i]].ndims >
|
||||
|
@ -23,6 +23,7 @@ typedef struct H5T_conv_struct_t {
|
||||
hid_t *dst_memb_id; /*destination member type ID's */
|
||||
H5T_conv_t *memb_conv; /*array of membr conversion functions*/
|
||||
H5T_cdata_t **memb_cdata; /*array of member cdata pointers */
|
||||
size_t *memb_nelmts; /*member element count */
|
||||
} H5T_conv_struct_t;
|
||||
|
||||
/* Interface initialization */
|
||||
@ -268,6 +269,45 @@ H5T_conv_struct_init (H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata)
|
||||
priv->dst_memb_id[priv->src2dst[i]] = tid;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Those members which are in both the source and destination must be
|
||||
* the same size and shape arrays.
|
||||
*/
|
||||
for (i=0; i<src->u.compnd.nmembs; i++) {
|
||||
if (priv->src2dst[i]>=0) {
|
||||
H5T_member_t *src_memb = src->u.compnd.memb + i;
|
||||
H5T_member_t *dst_memb = dst->u.compnd.memb + priv->src2dst[i];
|
||||
if (src_memb->ndims != dst_memb->ndims) {
|
||||
HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
|
||||
"source and dest members have incompatible "
|
||||
"size or shape");
|
||||
}
|
||||
for (j=0; j<src_memb->ndims; j++) {
|
||||
if (src_memb->dim[j] != dst_memb->dim[j]) {
|
||||
HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
|
||||
"source and dest members have "
|
||||
"incompatible size or shape");
|
||||
}
|
||||
#ifndef LATER
|
||||
/* Their permutation vectors must be equal */
|
||||
if (src_memb->perm[j]!=dst_memb->perm[j]) {
|
||||
HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
|
||||
"member permutations must be equal");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate number of elements of each member */
|
||||
priv->memb_nelmts = H5MM_malloc(src->u.compnd.nmembs*sizeof(size_t));
|
||||
for (i=0; i<src->u.compnd.nmembs; i++) {
|
||||
priv->memb_nelmts[i] = 1;
|
||||
for (j=0; j<src->u.compnd.memb[i].ndims; j++) {
|
||||
priv->memb_nelmts[i] *= src->u.compnd.memb[i].dim[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -374,24 +414,6 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
|
||||
assert (H5T_COMPOUND==src->type);
|
||||
assert (H5T_COMPOUND==dst->type);
|
||||
|
||||
#ifndef LATER
|
||||
/*
|
||||
* Struct members must be scalar for now.
|
||||
*/
|
||||
for (i=0; i<src->u.compnd.nmembs; i++) {
|
||||
if (src->u.compnd.memb[i].ndims>0) {
|
||||
HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
|
||||
"array members are not supported yet");
|
||||
}
|
||||
}
|
||||
for (i=0; i<dst->u.compnd.nmembs; i++) {
|
||||
if (dst->u.compnd.memb[i].ndims>0) {
|
||||
HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
|
||||
"array members are not supported yet");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (H5T_conv_struct_init (src, dst, cdata)<0) {
|
||||
HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL,
|
||||
"unable to initialize conversion data");
|
||||
@ -402,11 +424,12 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
|
||||
/*
|
||||
* Free the private conversion data.
|
||||
*/
|
||||
H5MM_xfree (priv->src2dst);
|
||||
H5MM_xfree (priv->src_memb_id);
|
||||
H5MM_xfree (priv->dst_memb_id);
|
||||
H5MM_xfree (priv->memb_conv);
|
||||
H5MM_xfree (priv->memb_cdata);
|
||||
H5MM_xfree(priv->src2dst);
|
||||
H5MM_xfree(priv->src_memb_id);
|
||||
H5MM_xfree(priv->dst_memb_id);
|
||||
H5MM_xfree(priv->memb_conv);
|
||||
H5MM_xfree(priv->memb_cdata);
|
||||
H5MM_xfree(priv->memb_nelmts);
|
||||
cdata->priv = priv = H5MM_xfree (priv);
|
||||
break;
|
||||
|
||||
@ -463,25 +486,23 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
|
||||
src_memb = src->u.compnd.memb + i;
|
||||
dst_memb = dst->u.compnd.memb + src2dst[i];
|
||||
|
||||
if (H5T_get_size (dst_memb->type) <=
|
||||
H5T_get_size (src_memb->type)) {
|
||||
if (dst_memb->size <= src_memb->size) {
|
||||
H5T_conv_t tconv_func = priv->memb_conv[src2dst[i]];
|
||||
H5T_cdata_t *memb_cdata = priv->memb_cdata[src2dst[i]];
|
||||
memb_cdata->command = H5T_CONV_CONV;
|
||||
(tconv_func)(priv->src_memb_id[src2dst[i]],
|
||||
priv->dst_memb_id[src2dst[i]],
|
||||
memb_cdata,
|
||||
1,
|
||||
memb_cdata, priv->memb_nelmts[i],
|
||||
buf + src_memb->offset,
|
||||
bkg + dst_memb->offset);
|
||||
|
||||
HDmemmove (buf + offset, buf + src_memb->offset,
|
||||
H5T_get_size (dst_memb->type));
|
||||
offset += H5T_get_size (dst_memb->type);
|
||||
dst_memb->size);
|
||||
offset += dst_memb->size;
|
||||
} else {
|
||||
HDmemmove (buf + offset, buf + src_memb->offset,
|
||||
H5T_get_size (src_memb->type));
|
||||
offset += H5T_get_size (src_memb->type);
|
||||
src_memb->size);
|
||||
offset += src_memb->size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -496,19 +517,18 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
|
||||
if (src2dst[i]<0) continue;
|
||||
src_memb = src->u.compnd.memb + i;
|
||||
dst_memb = dst->u.compnd.memb + src2dst[i];
|
||||
offset -= H5T_get_size (dst_memb->type);
|
||||
offset -= dst_memb->size;
|
||||
|
||||
if (H5T_get_size (dst_memb->type) >
|
||||
H5T_get_size (src_memb->type)) {
|
||||
if (dst_memb->size > src_memb->size) {
|
||||
H5T_conv_t tconv_func = priv->memb_conv[src2dst[i]];
|
||||
H5T_cdata_t *memb_cdata = priv->memb_cdata[src2dst[i]];
|
||||
memb_cdata->command = H5T_CONV_CONV;
|
||||
(tconv_func)(priv->src_memb_id[src2dst[i]],
|
||||
priv->dst_memb_id[src2dst[i]], memb_cdata, 1,
|
||||
buf + offset, bkg + dst_memb->offset);
|
||||
priv->dst_memb_id[src2dst[i]],
|
||||
memb_cdata, priv->memb_nelmts[i],
|
||||
buf+offset, bkg+dst_memb->offset);
|
||||
}
|
||||
HDmemmove (bkg+dst_memb->offset, buf+offset,
|
||||
H5T_get_size (dst_memb->type));
|
||||
HDmemmove (bkg+dst_memb->offset, buf+offset, dst_memb->size);
|
||||
}
|
||||
assert (0==offset);
|
||||
|
||||
@ -935,7 +955,7 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
|
||||
/* Conversion-related variables */
|
||||
hssize_t expo; /*exponent */
|
||||
hssize_t expo_max; /*maximum possible dst exponent */
|
||||
size_t msize; /*useful size of mantissa in src*/
|
||||
size_t msize=0; /*useful size of mantissa in src*/
|
||||
size_t mpos; /*offset to useful mant is src */
|
||||
size_t mrsh; /*amount to right shift mantissa*/
|
||||
hbool_t carry; /*carry after rounding mantissa */
|
||||
|
@ -86,6 +86,7 @@ struct H5T_t {
|
||||
typedef struct H5T_member_t {
|
||||
char *name; /*name of this member */
|
||||
size_t offset; /*offset from beginning of struct */
|
||||
size_t size; /*total size: dims * type_size */
|
||||
intn ndims; /*member dimensionality */
|
||||
size_t dim[4]; /*size in each dimension */
|
||||
intn perm[4]; /*index permutation */
|
||||
|
@ -54,7 +54,8 @@ size_t H5T_get_size (const H5T_t *dt);
|
||||
intn H5T_cmp (const H5T_t *dt1, const H5T_t *dt2);
|
||||
hbool_t H5T_is_atomic (const H5T_t *dt);
|
||||
herr_t H5T_insert (H5T_t *parent, const char *name, size_t offset,
|
||||
const H5T_t *member);
|
||||
intn ndims, const size_t *dim, const intn *perm,
|
||||
const H5T_t *member);
|
||||
herr_t H5T_sort_by_offset (H5T_t *dt);
|
||||
herr_t H5T_pack (H5T_t *dt);
|
||||
herr_t H5T_debug (H5T_t *dt, FILE * stream);
|
||||
|
@ -342,6 +342,9 @@ hbool_t H5Tcommitted (hid_t type_id);
|
||||
/* Operations defined on compound data types */
|
||||
herr_t H5Tinsert (hid_t parent_id, const char *name, size_t offset,
|
||||
hid_t member_id);
|
||||
herr_t H5Tinsert_array (hid_t parent_id, const char *name, size_t offset,
|
||||
int ndims, const size_t *dim, const int *perm,
|
||||
hid_t member_id);
|
||||
herr_t H5Tpack (hid_t type_id);
|
||||
|
||||
/* Querying property values */
|
||||
|
@ -238,27 +238,6 @@ dsets.o: \
|
||||
../src/H5Zpublic.h \
|
||||
../src/H5Spublic.h \
|
||||
../src/H5Tpublic.h
|
||||
cmpd_dset.o: \
|
||||
cmpd_dset.c \
|
||||
../src/hdf5.h \
|
||||
../src/H5public.h \
|
||||
../src/H5config.h \
|
||||
../src/H5Ipublic.h \
|
||||
../src/H5Apublic.h \
|
||||
../src/H5ACpublic.h \
|
||||
../src/H5Bpublic.h \
|
||||
../src/H5Dpublic.h \
|
||||
../src/H5Epublic.h \
|
||||
../src/H5Fpublic.h \
|
||||
../src/H5Gpublic.h \
|
||||
../src/H5HGpublic.h \
|
||||
../src/H5HLpublic.h \
|
||||
../src/H5MFpublic.h \
|
||||
../src/H5MMpublic.h \
|
||||
../src/H5Opublic.h \
|
||||
../src/H5Ppublic.h \
|
||||
../src/H5Zpublic.h \
|
||||
../src/H5Spublic.h
|
||||
extend.o: \
|
||||
extend.c \
|
||||
../src/hdf5.h \
|
||||
@ -446,3 +425,24 @@ bittests.o: \
|
||||
../src/H5Gprivate.h \
|
||||
../src/H5Gpublic.h \
|
||||
../src/H5Bprivate.h
|
||||
cmpd_dset.o: \
|
||||
cmpd_dset.c \
|
||||
../src/hdf5.h \
|
||||
../src/H5public.h \
|
||||
../src/H5config.h \
|
||||
../src/H5Ipublic.h \
|
||||
../src/H5Apublic.h \
|
||||
../src/H5ACpublic.h \
|
||||
../src/H5Bpublic.h \
|
||||
../src/H5Dpublic.h \
|
||||
../src/H5Epublic.h \
|
||||
../src/H5Fpublic.h \
|
||||
../src/H5Gpublic.h \
|
||||
../src/H5HGpublic.h \
|
||||
../src/H5HLpublic.h \
|
||||
../src/H5MFpublic.h \
|
||||
../src/H5MMpublic.h \
|
||||
../src/H5Opublic.h \
|
||||
../src/H5Ppublic.h \
|
||||
../src/H5Zpublic.h \
|
||||
../src/H5Spublic.h
|
||||
|
118
test/cmpd_dset.c
118
test/cmpd_dset.c
@ -18,7 +18,7 @@
|
||||
typedef struct s1_t {
|
||||
unsigned int a;
|
||||
unsigned int b;
|
||||
unsigned int c;
|
||||
unsigned int c[4];
|
||||
unsigned int d;
|
||||
unsigned int e;
|
||||
} s1_t;
|
||||
@ -30,7 +30,7 @@ typedef s1_t s2_t;
|
||||
typedef struct s3_t {
|
||||
unsigned int e;
|
||||
unsigned int d;
|
||||
unsigned int c;
|
||||
unsigned int c[4];
|
||||
unsigned int b;
|
||||
unsigned int a;
|
||||
} s3_t;
|
||||
@ -47,7 +47,7 @@ typedef struct s5_t {
|
||||
unsigned int a;
|
||||
unsigned int b;
|
||||
unsigned int mid1;
|
||||
unsigned int c;
|
||||
unsigned int c[4];
|
||||
unsigned int mid2;
|
||||
unsigned int d;
|
||||
unsigned int e;
|
||||
@ -154,6 +154,7 @@ main (void)
|
||||
hssize_t f_offset[2]; /*offset of hyperslab in file */
|
||||
hsize_t h_size[2]; /*size of hyperslab */
|
||||
hsize_t h_sample[2]; /*hyperslab sampling */
|
||||
size_t memb_size[1] = {4};
|
||||
|
||||
/* Create the file */
|
||||
file = H5Fcreate (TEST_FILE_NAME, H5F_ACC_TRUNC|H5F_ACC_DEBUG,
|
||||
@ -180,18 +181,22 @@ STEP 1: Initialize dataset `s1' and store it on disk in native order.\n");
|
||||
|
||||
/* Initialize the dataset */
|
||||
for (i=0; i<NX*NY; i++) {
|
||||
s1[i].a = 5*i+0;
|
||||
s1[i].a = 8*i+0;
|
||||
s1[i].b = 2000*2*i;
|
||||
s1[i].c = 5*i+2;
|
||||
s1[i].c[0] = 8*i+2;
|
||||
s1[i].c[1] = 8*i+3;
|
||||
s1[i].c[2] = 8*i+4;
|
||||
s1[i].c[3] = 8*i+5;
|
||||
s1[i].d = 2001+2*i;
|
||||
s1[i].e = 5*i+4;
|
||||
s1[i].e = 8*i+7;
|
||||
}
|
||||
|
||||
/* Create the memory data type */
|
||||
s1_tid = H5Tcreate (H5T_COMPOUND, sizeof(s1_t));
|
||||
H5Tinsert (s1_tid, "a", HOFFSET(s1_t,a), H5T_NATIVE_INT);
|
||||
H5Tinsert (s1_tid, "b", HOFFSET(s1_t,b), H5T_NATIVE_INT);
|
||||
H5Tinsert (s1_tid, "c", HOFFSET(s1_t,c), H5T_NATIVE_INT);
|
||||
H5Tinsert_array (s1_tid, "c", HOFFSET(s1_t,c), 1, memb_size, NULL,
|
||||
H5T_NATIVE_INT);
|
||||
H5Tinsert (s1_tid, "d", HOFFSET(s1_t,d), H5T_NATIVE_INT);
|
||||
H5Tinsert (s1_tid, "e", HOFFSET(s1_t,e), H5T_NATIVE_INT);
|
||||
assert (s1_tid>=0);
|
||||
@ -220,7 +225,8 @@ STEP 2: Read the dataset from disk into a new memory buffer which has the\n\
|
||||
s2_tid = H5Tcreate (H5T_COMPOUND, sizeof(s2_t));
|
||||
H5Tinsert (s2_tid, "a", HOFFSET(s2_t,a), H5T_NATIVE_INT);
|
||||
H5Tinsert (s2_tid, "b", HOFFSET(s2_t,b), H5T_NATIVE_INT);
|
||||
H5Tinsert (s2_tid, "c", HOFFSET(s2_t,c), H5T_NATIVE_INT);
|
||||
H5Tinsert_array (s2_tid, "c", HOFFSET(s2_t,c), 1, memb_size, NULL,
|
||||
H5T_NATIVE_INT);
|
||||
H5Tinsert (s2_tid, "d", HOFFSET(s2_t,d), H5T_NATIVE_INT);
|
||||
H5Tinsert (s2_tid, "e", HOFFSET(s2_t,e), H5T_NATIVE_INT);
|
||||
assert (s2_tid>=0);
|
||||
@ -233,7 +239,10 @@ STEP 2: Read the dataset from disk into a new memory buffer which has the\n\
|
||||
for (i=0; i<NX*NY; i++) {
|
||||
assert (s1[i].a==s2[i].a);
|
||||
assert (s1[i].b==s2[i].b);
|
||||
assert (s1[i].c==s2[i].c);
|
||||
assert (s1[i].c[0]==s2[i].c[0]);
|
||||
assert (s1[i].c[1]==s2[i].c[1]);
|
||||
assert (s1[i].c[2]==s2[i].c[2]);
|
||||
assert (s1[i].c[3]==s2[i].c[3]);
|
||||
assert (s1[i].d==s2[i].d);
|
||||
assert (s1[i].e==s2[i].e);
|
||||
}
|
||||
@ -252,7 +261,8 @@ STEP 3: Read the dataset again with members in a different order.\n");
|
||||
s3_tid = H5Tcreate (H5T_COMPOUND, sizeof(s3_t));
|
||||
H5Tinsert (s3_tid, "a", HOFFSET(s3_t,a), H5T_NATIVE_INT);
|
||||
H5Tinsert (s3_tid, "b", HOFFSET(s3_t,b), H5T_NATIVE_INT);
|
||||
H5Tinsert (s3_tid, "c", HOFFSET(s3_t,c), H5T_NATIVE_INT);
|
||||
H5Tinsert_array (s3_tid, "c", HOFFSET(s3_t,c), 1, memb_size, NULL,
|
||||
H5T_NATIVE_INT);
|
||||
H5Tinsert (s3_tid, "d", HOFFSET(s3_t,d), H5T_NATIVE_INT);
|
||||
H5Tinsert (s3_tid, "e", HOFFSET(s3_t,e), H5T_NATIVE_INT);
|
||||
assert (s3_tid>=0);
|
||||
@ -265,7 +275,10 @@ STEP 3: Read the dataset again with members in a different order.\n");
|
||||
for (i=0; i<NX*NY; i++) {
|
||||
assert (s1[i].a==s3[i].a);
|
||||
assert (s1[i].b==s3[i].b);
|
||||
assert (s1[i].c==s3[i].c);
|
||||
assert (s1[i].c[0]==s3[i].c[0]);
|
||||
assert (s1[i].c[1]==s3[i].c[1]);
|
||||
assert (s1[i].c[2]==s3[i].c[2]);
|
||||
assert (s1[i].c[3]==s3[i].c[3]);
|
||||
assert (s1[i].d==s3[i].d);
|
||||
assert (s1[i].e==s3[i].e);
|
||||
}
|
||||
@ -316,7 +329,8 @@ STEP 5: Read members into a superset which is partially initialized.\n");
|
||||
s5_tid = H5Tcreate (H5T_COMPOUND, sizeof(s5_t));
|
||||
H5Tinsert (s5_tid, "a", HOFFSET(s5_t,a), H5T_NATIVE_INT);
|
||||
H5Tinsert (s5_tid, "b", HOFFSET(s5_t,b), H5T_NATIVE_INT);
|
||||
H5Tinsert (s5_tid, "c", HOFFSET(s5_t,c), H5T_NATIVE_INT);
|
||||
H5Tinsert_array (s5_tid, "c", HOFFSET(s5_t,c), 1, memb_size, NULL,
|
||||
H5T_NATIVE_INT);
|
||||
H5Tinsert (s5_tid, "d", HOFFSET(s5_t,d), H5T_NATIVE_INT);
|
||||
H5Tinsert (s5_tid, "e", HOFFSET(s5_t,e), H5T_NATIVE_INT);
|
||||
assert (s5_tid>=0);
|
||||
@ -329,7 +343,10 @@ STEP 5: Read members into a superset which is partially initialized.\n");
|
||||
for (i=0; i<NX*NY; i++) {
|
||||
assert (s1[i].a==s5[i].a);
|
||||
assert (s1[i].b==s5[i].b);
|
||||
assert (s1[i].c==s5[i].c);
|
||||
assert (s1[i].c[0]==s5[i].c[0]);
|
||||
assert (s1[i].c[1]==s5[i].c[1]);
|
||||
assert (s1[i].c[2]==s5[i].c[2]);
|
||||
assert (s1[i].c[3]==s5[i].c[3]);
|
||||
assert (s1[i].d==s5[i].d);
|
||||
assert (s1[i].e==s5[i].e);
|
||||
}
|
||||
@ -355,8 +372,8 @@ STEP 6: Update fields `b' and `d' on the file, leaving the other fields\n\
|
||||
|
||||
/* Initialize `s4' with new values */
|
||||
for (i=0; i<NX*NY; i++) {
|
||||
s4[i].b = 5*i+1;
|
||||
s4[i].d = 5*i+3;
|
||||
s4[i].b = 8*i+1;
|
||||
s4[i].d = 8*i+6;
|
||||
}
|
||||
|
||||
/* Write the data to file */
|
||||
@ -369,11 +386,14 @@ STEP 6: Update fields `b' and `d' on the file, leaving the other fields\n\
|
||||
|
||||
/* Compare */
|
||||
for (i=0; i<NX*NY; i++) {
|
||||
assert (s1[i].a == 5*i+0);
|
||||
assert (s1[i].b == 5*i+1);
|
||||
assert (s1[i].c == 5*i+2);
|
||||
assert (s1[i].d == 5*i+3);
|
||||
assert (s1[i].e == 5*i+4);
|
||||
assert (s1[i].a == 8*i+0);
|
||||
assert (s1[i].b == 8*i+1);
|
||||
assert (s1[i].c[0] == 8*i+2);
|
||||
assert (s1[i].c[1] == 8*i+3);
|
||||
assert (s1[i].c[2] == 8*i+4);
|
||||
assert (s1[i].c[3] == 8*i+5);
|
||||
assert (s1[i].d == 8*i+6);
|
||||
assert (s1[i].e == 8*i+7);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -398,7 +418,10 @@ STEP 7: Reading original dataset with explicit data space.\n");
|
||||
for (i=0; i<NX*NY; i++) {
|
||||
assert (s2[i].a == s1[i].a);
|
||||
assert (s2[i].b == s1[i].b);
|
||||
assert (s2[i].c == s1[i].c);
|
||||
assert (s2[i].c[0] == s1[i].c[0]);
|
||||
assert (s2[i].c[1] == s1[i].c[1]);
|
||||
assert (s2[i].c[2] == s1[i].c[2]);
|
||||
assert (s2[i].c[3] == s1[i].c[3]);
|
||||
assert (s2[i].d == s1[i].d);
|
||||
assert (s2[i].e == s1[i].e);
|
||||
}
|
||||
@ -420,7 +443,8 @@ STEP 8: Read middle third hyperslab into memory array.\n");
|
||||
f_offset[1] = NY/3;
|
||||
h_size[0] = 2*NX/3 - f_offset[0];
|
||||
h_size[1] = 2*NY/3 - f_offset[1];
|
||||
status = H5Sselect_hyperslab (s8_f_sid, H5S_SELECT_SET, f_offset, NULL, h_size, NULL);
|
||||
status = H5Sselect_hyperslab (s8_f_sid, H5S_SELECT_SET, f_offset, NULL,
|
||||
h_size, NULL);
|
||||
assert (status>=0);
|
||||
|
||||
/* Create memory data space */
|
||||
@ -441,7 +465,10 @@ STEP 8: Read middle third hyperslab into memory array.\n");
|
||||
|
||||
assert (ps8->a == ps1->a);
|
||||
assert (ps8->b == ps1->b);
|
||||
assert (ps8->c == ps1->c);
|
||||
assert (ps8->c[0] == ps1->c[0]);
|
||||
assert (ps8->c[1] == ps1->c[1]);
|
||||
assert (ps8->c[2] == ps1->c[2]);
|
||||
assert (ps8->c[3] == ps1->c[3]);
|
||||
assert (ps8->d == ps1->d);
|
||||
assert (ps8->e == ps1->e);
|
||||
}
|
||||
@ -462,7 +489,8 @@ STEP 9: Read middle third of hyperslab into middle third of memory array.\n");
|
||||
|
||||
/* Initialize */
|
||||
for (i=0; i<NX*NY; i++) {
|
||||
s2[i].a = s2[i].b = s2[i].c = s2[i].d = s2[i].e = (unsigned)(-1);
|
||||
s2[i].a = s2[i].b = s2[i].d = s2[i].e = (unsigned)(-1);
|
||||
s2[i].c[0] = s2[i].c[1] = s2[i].c[2] = s2[i].c[3] = (unsigned)(-1);
|
||||
}
|
||||
|
||||
/* Read the hyperslab */
|
||||
@ -480,13 +508,19 @@ STEP 9: Read middle third of hyperslab into middle third of memory array.\n");
|
||||
(hsize_t)j<f_offset[1]+h_size[1]) {
|
||||
assert (ps2->a == ps1->a);
|
||||
assert (ps2->b == ps1->b);
|
||||
assert (ps2->c == ps1->c);
|
||||
assert (ps2->c[0] == ps1->c[0]);
|
||||
assert (ps2->c[1] == ps1->c[1]);
|
||||
assert (ps2->c[2] == ps1->c[2]);
|
||||
assert (ps2->c[3] == ps1->c[3]);
|
||||
assert (ps2->d == ps1->d);
|
||||
assert (ps2->e == ps1->e);
|
||||
} else {
|
||||
assert (ps2->a == (unsigned)(-1));
|
||||
assert (ps2->b == (unsigned)(-1));
|
||||
assert (ps2->c == (unsigned)(-1));
|
||||
assert (ps2->c[0] == (unsigned)(-1));
|
||||
assert (ps2->c[1] == (unsigned)(-1));
|
||||
assert (ps2->c[2] == (unsigned)(-1));
|
||||
assert (ps2->c[3] == (unsigned)(-1));
|
||||
assert (ps2->d == (unsigned)(-1));
|
||||
assert (ps2->e == (unsigned)(-1));
|
||||
}
|
||||
@ -505,7 +539,8 @@ STEP 10: Read middle third of hyperslab into middle third of memory array\n\
|
||||
|
||||
/* Initialize */
|
||||
for (i=0; i<NX*NY; i++) {
|
||||
s5[i].a = s5[i].b = s5[i].c = s5[i].d = s5[i].e = (unsigned)(-1);
|
||||
s5[i].a = s5[i].b = s5[i].d = s5[i].e = (unsigned)(-1);
|
||||
s5[i].c[0] = s5[i].c[1] = s5[i].c[2] = s5[i].c[3] = (unsigned)(-1);
|
||||
s5[i].pre = s5[i].mid1 = s5[i].mid2 = s5[i].post = (unsigned)(-1);
|
||||
}
|
||||
|
||||
@ -526,7 +561,10 @@ STEP 10: Read middle third of hyperslab into middle third of memory array\n\
|
||||
assert (ps5->a == ps1->a);
|
||||
assert (ps5->b == ps1->b);
|
||||
assert (ps5->mid1 == (unsigned)(-1));
|
||||
assert (ps5->c == ps1->c);
|
||||
assert (ps5->c[0] == ps1->c[0]);
|
||||
assert (ps5->c[1] == ps1->c[1]);
|
||||
assert (ps5->c[2] == ps1->c[2]);
|
||||
assert (ps5->c[3] == ps1->c[3]);
|
||||
assert (ps5->mid2 == (unsigned)(-1));
|
||||
assert (ps5->d == ps1->d);
|
||||
assert (ps5->e == ps1->e);
|
||||
@ -536,7 +574,10 @@ STEP 10: Read middle third of hyperslab into middle third of memory array\n\
|
||||
assert (ps5->a == (unsigned)(-1));
|
||||
assert (ps5->b == (unsigned)(-1));
|
||||
assert (ps5->mid1 == (unsigned)(-1));
|
||||
assert (ps5->c == (unsigned)(-1));
|
||||
assert (ps5->c[0] == (unsigned)(-1));
|
||||
assert (ps5->c[1] == (unsigned)(-1));
|
||||
assert (ps5->c[2] == (unsigned)(-1));
|
||||
assert (ps5->c[3] == (unsigned)(-1));
|
||||
assert (ps5->mid2 == (unsigned)(-1));
|
||||
assert (ps5->d == (unsigned)(-1));
|
||||
assert (ps5->e == (unsigned)(-1));
|
||||
@ -582,9 +623,12 @@ STEP 11: Write an array back to the middle third of the dataset to\n\
|
||||
for (j=0; j<NY; j++) {
|
||||
s1_t *ps1 = s1 + i*NY + j;
|
||||
|
||||
assert (ps1->a == 5*(i*NY+j)+0);
|
||||
assert (ps1->c == 5*(i*NY+j)+2);
|
||||
assert (ps1->e == 5*(i*NY+j)+4);
|
||||
assert (ps1->a == 8*(i*NY+j)+0);
|
||||
assert (ps1->c[0] == 8*(i*NY+j)+2);
|
||||
assert (ps1->c[1] == 8*(i*NY+j)+3);
|
||||
assert (ps1->c[2] == 8*(i*NY+j)+4);
|
||||
assert (ps1->c[3] == 8*(i*NY+j)+5);
|
||||
assert (ps1->e == 8*(i*NY+j)+7);
|
||||
if ((hssize_t)i>=f_offset[0] &&
|
||||
(hsize_t)i<f_offset[0]+h_size[0] &&
|
||||
(hssize_t)j>=f_offset[1] &&
|
||||
@ -592,8 +636,8 @@ STEP 11: Write an array back to the middle third of the dataset to\n\
|
||||
assert (ps1->b == (unsigned)(-1));
|
||||
assert (ps1->d == (unsigned)(-1));
|
||||
} else {
|
||||
assert (ps1->b == 5*(i*NY+j)+1);
|
||||
assert (ps1->d == 5*(i*NY+j)+3);
|
||||
assert (ps1->b == 8*(i*NY+j)+1);
|
||||
assert (ps1->d == 8*(i*NY+j)+6);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -602,12 +646,6 @@ STEP 11: Write an array back to the middle third of the dataset to\n\
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Release resources.
|
||||
|
Loading…
Reference in New Issue
Block a user