diff options
Diffstat (limited to 'src/H5Tfields.c')
-rw-r--r-- | src/H5Tfields.c | 486 |
1 files changed, 486 insertions, 0 deletions
diff --git a/src/H5Tfields.c b/src/H5Tfields.c new file mode 100644 index 0000000..be62d85 --- /dev/null +++ b/src/H5Tfields.c @@ -0,0 +1,486 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains commond functionality for fields in + * enumerated & compound datatypes in the H5T interface. + */ + +#include "H5Tmodule.h" /* This source code file is part of the H5T module */ + + +#include "H5private.h" /*generic functions */ +#include "H5Eprivate.h" /*error handling */ +#include "H5Iprivate.h" /*ID functions */ +#include "H5MMprivate.h" /*memory management */ +#include "H5Tpkg.h" /*data-type functions */ + + +/*------------------------------------------------------------------------- + * Function: H5Tget_nmembers + * + * Purpose: Determines how many members TYPE_ID has. The type must be + * either a compound datatype or an enumeration datatype. + * + * Return: Success: Number of members defined in the datatype. + * + * Failure: Negative + * + * Errors: + * + * Programmer: Robb Matzke + * Monday, December 8, 1997 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works with enumeration datatypes. + *------------------------------------------------------------------------- + */ +int +H5Tget_nmembers(hid_t type_id) +{ + H5T_t *dt; /* Datatype to query */ + int ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE1("Is", "i", type_id); + + /* Check args */ + if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") + + if((ret_value = H5T_get_nmembers(dt)) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "cannot return member number") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Tget_nmembers() */ + + +/*------------------------------------------------------------------------- + * Function: H5T_get_nmembers + * + * Purpose: Private function for H5Tget_nmembers. Determines how many + * members DTYPE has. The type must be either a compound data + * type or an enumeration datatype. + * + * Return: Success: Number of members defined in the datatype. + * + * Failure: Negative + * + * Errors: + * + * Programmer: Raymond Lu + * October 8, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +H5T_get_nmembers(const H5T_t *dt) +{ + int ret_value = -1; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + HDassert(dt); + + if(H5T_COMPOUND == dt->shared->type) + ret_value = (int)dt->shared->u.compnd.nmembs; + else if(H5T_ENUM == dt->shared->type) + ret_value = (int)dt->shared->u.enumer.nmembs; + else + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "operation not supported for type class") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T_get_nmembers() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tget_member_name + * + * Purpose: Returns the name of a member of a compound or enumeration + * datatype. Members are stored in no particular order with + * numbers 0 through N-1 where N is the value returned by + * H5Tget_nmembers(). + * + * Return: Success: Ptr to a string allocated with malloc(). The + * caller is responsible for freeing the string. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works with enumeration datatypes. + *------------------------------------------------------------------------- + */ +char * +H5Tget_member_name(hid_t type_id, unsigned membno) +{ + H5T_t *dt = NULL; + char *ret_value; + + FUNC_ENTER_API(NULL) + H5TRACE2("*s", "iIu", type_id, membno); + + /* Check args */ + if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a datatype") + + if(NULL == (ret_value = H5T__get_member_name(dt, membno))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "unable to get member name") + +done: + FUNC_LEAVE_API(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5T__get_member_name + * + * Purpose: Private function for H5Tget_member_name. Returns the name + * of a member of a compound or enumeration datatype. Members + * are stored in no particular order with numbers 0 through + * N-1 where N is the value returned by H5Tget_nmembers(). + * + * Return: Success: Ptr to a string allocated with malloc(). The + * caller is responsible for freeing the string. + * + * Failure: NULL + * + * Programmer: Raymond Lu + * October 9, 2002 + * + * Modifications: + *------------------------------------------------------------------------- + */ +char * +H5T__get_member_name(H5T_t const *dt, unsigned membno) +{ + char *ret_value = NULL; /* Return value */ + + FUNC_ENTER_PACKAGE + + HDassert(dt); + + switch (dt->shared->type) { + case H5T_COMPOUND: + if (membno>=dt->shared->u.compnd.nmembs) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid member number") + ret_value = H5MM_xstrdup(dt->shared->u.compnd.memb[membno].name); + break; + + case H5T_ENUM: + if (membno>=dt->shared->u.enumer.nmembs) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid member number") + ret_value = H5MM_xstrdup(dt->shared->u.enumer.name[membno]); + break; + + case H5T_NO_CLASS: + case H5T_INTEGER: + case H5T_FLOAT: + case H5T_TIME: + case H5T_STRING: + case H5T_BITFIELD: + case H5T_OPAQUE: + case H5T_REFERENCE: + case H5T_VLEN: + case H5T_ARRAY: + case H5T_NCLASSES: + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "operation not supported for type class") + } /*lint !e788 All appropriate cases are covered */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5Tget_member_index + * + * Purpose: Returns the index of a member in a compound or enumeration + * datatype by given name.Members are stored in no particular + * order with numbers 0 through N-1 where N is the value + * returned by H5Tget_nmembers(). + * + * Return: Success: index of the member if exists. + * Failure: -1. + * + * Programmer: Raymond Lu + * Thursday, April 4, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +H5Tget_member_index(hid_t type_id, const char *name) +{ + H5T_t *dt = NULL; + int ret_value=FAIL; + unsigned i; + + FUNC_ENTER_API(FAIL) + H5TRACE2("Is", "i*s", type_id, name); + + /* Check arguments */ + HDassert(name); + if(NULL == (dt = (H5T_t*)H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype") + + /* Locate member by name */ + switch(dt->shared->type) { + case H5T_COMPOUND: + for(i = 0; i < dt->shared->u.compnd.nmembs; i++) + if(!HDstrcmp(dt->shared->u.compnd.memb[i].name, name)) + HGOTO_DONE((int)i) + break; + case H5T_ENUM: + for(i = 0; i < dt->shared->u.enumer.nmembs; i++) + if(!HDstrcmp(dt->shared->u.enumer.name[i], name)) + HGOTO_DONE((int)i) + break; + + case H5T_NO_CLASS: + case H5T_INTEGER: + case H5T_FLOAT: + case H5T_TIME: + case H5T_STRING: + case H5T_BITFIELD: + case H5T_OPAQUE: + case H5T_REFERENCE: + case H5T_VLEN: + case H5T_ARRAY: + case H5T_NCLASSES: + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "operation not supported for this type") + } /*lint !e788 All appropriate cases are covered */ + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Tget_member_index() */ + + +/*------------------------------------------------------------------------- + * Function: H5T__sort_value + * + * Purpose: Sorts the members of a compound datatype by their offsets; + * sorts the members of an enum type by their values. This even + * works for locked datatypes since it doesn't change the value + * of the type. MAP is an optional parallel integer array which + * is also swapped along with members of DT. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__sort_value(const H5T_t *dt, int *map) +{ + unsigned nmembs; /* Number of members for datatype */ + size_t size; + hbool_t swapped; /* Whether we've swapped fields */ + uint8_t tbuf[32]; + unsigned i, j; /* Local index variables */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE_NOERR + + /* Check args */ + HDassert(dt); + HDassert(H5T_COMPOUND == dt->shared->type || H5T_ENUM == dt->shared->type); + + /* Use a bubble sort because we can short circuit */ + if(H5T_COMPOUND == dt->shared->type) { + if(H5T_SORT_VALUE != dt->shared->u.compnd.sorted) { + dt->shared->u.compnd.sorted = H5T_SORT_VALUE; + nmembs = dt->shared->u.compnd.nmembs; + for(i = nmembs - 1, swapped = TRUE; i > 0 && swapped; --i) { + for(j = 0, swapped = FALSE; j < i; j++) { + if(dt->shared->u.compnd.memb[j].offset > dt->shared->u.compnd.memb[j + 1].offset) { + H5T_cmemb_t tmp = dt->shared->u.compnd.memb[j]; + dt->shared->u.compnd.memb[j] = dt->shared->u.compnd.memb[j + 1]; + dt->shared->u.compnd.memb[j + 1] = tmp; + if(map) { + int x = map[j]; + + map[j] = map[j + 1]; + map[j + 1] = x; + } /* end if */ + swapped = TRUE; + } /* end if */ + } /* end for */ + } /* end for */ +#ifndef NDEBUG + /* I never trust a sort :-) -RPM */ + for(i = 0; i < (nmembs - 1); i++) + HDassert(dt->shared->u.compnd.memb[i].offset < dt->shared->u.compnd.memb[i + 1].offset); +#endif + } /* end if */ + } else if(H5T_ENUM == dt->shared->type) { + if(H5T_SORT_VALUE != dt->shared->u.enumer.sorted) { + dt->shared->u.enumer.sorted = H5T_SORT_VALUE; + nmembs = dt->shared->u.enumer.nmembs; + size = dt->shared->size; + HDassert(size <= sizeof(tbuf)); + for(i = (nmembs - 1), swapped = TRUE; i > 0 && swapped; --i) { + for(j = 0, swapped = FALSE; j < i; j++) { + if(HDmemcmp(dt->shared->u.enumer.value + (j * size), dt->shared->u.enumer.value + ((j + 1) * size), size) > 0) { + /* Swap names */ + char *tmp = dt->shared->u.enumer.name[j]; + dt->shared->u.enumer.name[j] = dt->shared->u.enumer.name[j + 1]; + dt->shared->u.enumer.name[j + 1] = tmp; + + /* Swap values */ + HDmemcpy(tbuf, dt->shared->u.enumer.value + (j * size), size); + HDmemcpy(dt->shared->u.enumer.value + (j * size), + dt->shared->u.enumer.value + ((j + 1) * size), size); + HDmemcpy(dt->shared->u.enumer.value + ((j + 1) * size), tbuf, size); + + /* Swap map */ + if(map) { + int x = map[j]; + + map[j] = map[j + 1]; + map[j + 1] = x; + } /* end if */ + + swapped = TRUE; + } /* end if */ + } /* end for */ + } /* end for */ +#ifndef NDEBUG + /* I never trust a sort :-) -RPM */ + for(i = 0; i < (nmembs - 1); i++) + HDassert(HDmemcmp(dt->shared->u.enumer.value + (i * size), dt->shared->u.enumer.value + ((i + 1) * size), size) < 0); +#endif + } /* end if */ + } /* end else */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__sort_value() */ + + +/*------------------------------------------------------------------------- + * Function: H5T__sort_name + * + * Purpose: Sorts members of a compound or enumeration datatype by their + * names. This even works for locked datatypes since it doesn't + * change the value of the types. + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Robb Matzke + * Monday, January 4, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__sort_name(const H5T_t *dt, int *map) +{ + unsigned i, j, nmembs; + size_t size; + hbool_t swapped; + uint8_t tbuf[32]; + + FUNC_ENTER_PACKAGE_NOERR + + /* Check args */ + HDassert(dt); + HDassert(H5T_COMPOUND==dt->shared->type || H5T_ENUM==dt->shared->type); + + /* Use a bubble sort because we can short circuit */ + if (H5T_COMPOUND==dt->shared->type) { + if (H5T_SORT_NAME!=dt->shared->u.compnd.sorted) { + dt->shared->u.compnd.sorted = H5T_SORT_NAME; + nmembs = dt->shared->u.compnd.nmembs; + for (i=nmembs-1, swapped=TRUE; i>0 && swapped; --i) { + for (j=0, swapped=FALSE; j<i; j++) { + if (HDstrcmp(dt->shared->u.compnd.memb[j].name, + dt->shared->u.compnd.memb[j+1].name)>0) { + H5T_cmemb_t tmp = dt->shared->u.compnd.memb[j]; + dt->shared->u.compnd.memb[j] = dt->shared->u.compnd.memb[j+1]; + dt->shared->u.compnd.memb[j+1] = tmp; + swapped = TRUE; + if (map) { + int x = map[j]; + map[j] = map[j+1]; + map[j+1] = x; + } + } + } + } +#ifndef NDEBUG + /* I never trust a sort :-) -RPM */ + for (i=0; i<nmembs-1; i++) { + HDassert(HDstrcmp(dt->shared->u.compnd.memb[i].name, + dt->shared->u.compnd.memb[i+1].name)<0); + } +#endif + } + } else if (H5T_ENUM==dt->shared->type) { + if (H5T_SORT_NAME!=dt->shared->u.enumer.sorted) { + dt->shared->u.enumer.sorted = H5T_SORT_NAME; + nmembs = dt->shared->u.enumer.nmembs; + size = dt->shared->size; + HDassert(size<=sizeof(tbuf)); + for (i=nmembs-1, swapped=TRUE; i>0 && swapped; --i) { + for (j=0, swapped=FALSE; j<i; j++) { + if (HDstrcmp(dt->shared->u.enumer.name[j], + dt->shared->u.enumer.name[j+1])>0) { + /* Swap names */ + char *tmp = dt->shared->u.enumer.name[j]; + dt->shared->u.enumer.name[j] = dt->shared->u.enumer.name[j+1]; + dt->shared->u.enumer.name[j+1] = tmp; + + /* Swap values */ + HDmemcpy(tbuf, dt->shared->u.enumer.value+j*size, size); + HDmemcpy(dt->shared->u.enumer.value+j*size, + dt->shared->u.enumer.value+(j+1)*size, size); + HDmemcpy(dt->shared->u.enumer.value+(j+1)*size, tbuf, size); + + /* Swap map */ + if (map) { + int x = map[j]; + map[j] = map[j+1]; + map[j+1] = x; + } + + swapped = TRUE; + } + } + } +#ifndef NDEBUG + /* I never trust a sort :-) -RPM */ + for (i=0; i<nmembs-1; i++) + HDassert(HDstrcmp(dt->shared->u.enumer.name[i], dt->shared->u.enumer.name[i+1])<0); +#endif + } + } + + FUNC_LEAVE_NOAPI(SUCCEED) +} + |