From 7d63d5e3ff5d8de37ac28106730255cb4a6739e2 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Wed, 12 Feb 2003 08:44:31 -0500 Subject: [svn-r6395] Purpose: Code cleanup. Description: Break up the ~9350 line H5T.c module into smaller pieces, which contain code for a particular feature or support for a datatype class. This should make the "main" H5T code (still in H5T.c) easier to support, as well as removing some of the "minor" routines from the user applications which don't use them (my rough estimates show about 4% reduction (~30K on a FreeBSD machine) in optimized, staticly-linked binaries for very simple programs) Platforms tested: Tested h5committest {arabica (fortran), eirene (fortran, C++) modi4 (parallel, fortran)} FreeBSD 4.7 (sleipnir) Misc. update: Update MANIFEST --- MANIFEST | 15 + src/H5T.c | 6066 +++++++++-------------------------------------------- src/H5Tarray.c | 343 +++ src/H5Tbit.c | 34 +- src/H5Tcommit.c | 206 ++ src/H5Tcompound.c | 512 +++++ src/H5Tconv.c | 37 +- src/H5Tcset.c | 159 ++ src/H5Tenum.c | 582 +++++ src/H5Tfields.c | 505 +++++ src/H5Tfixed.c | 182 ++ src/H5Tfloat.c | 447 ++++ src/H5Tnative.c | 761 +++++++ src/H5Toffset.c | 258 +++ src/H5Topaque.c | 139 ++ src/H5Torder.c | 148 ++ src/H5Tpad.c | 151 ++ src/H5Tpkg.h | 23 + src/H5Tprecis.c | 266 +++ src/H5Tprivate.h | 40 - src/H5Tstrpad.c | 171 ++ src/H5Tvlen.c | 146 +- src/Makefile.in | 7 +- 23 files changed, 6066 insertions(+), 5132 deletions(-) create mode 100644 src/H5Tarray.c create mode 100644 src/H5Tcommit.c create mode 100644 src/H5Tcompound.c create mode 100644 src/H5Tcset.c create mode 100644 src/H5Tenum.c create mode 100644 src/H5Tfields.c create mode 100644 src/H5Tfixed.c create mode 100644 src/H5Tfloat.c create mode 100644 src/H5Tnative.c create mode 100644 src/H5Toffset.c create mode 100644 src/H5Topaque.c create mode 100644 src/H5Torder.c create mode 100644 src/H5Tpad.c create mode 100644 src/H5Tprecis.c create mode 100644 src/H5Tstrpad.c diff --git a/MANIFEST b/MANIFEST index cd8ea04..626e30a 100644 --- a/MANIFEST +++ b/MANIFEST @@ -909,11 +909,26 @@ ./src/H5ST.c ./src/H5STprivate.h ./src/H5T.c +./src/H5Tarray.c ./src/H5Tbit.c +./src/H5Tcommit.c +./src/H5Tcompound.c ./src/H5Tconv.c +./src/H5Tcset.c +./src/H5Tenum.c +./src/H5Tfields.c +./src/H5Tfixed.c +./src/H5Tfloat.c +./src/H5Tnative.c +./src/H5Toffset.c +./src/H5Topaque.c +./src/H5Torder.c +./src/H5Tpad.c ./src/H5Tpkg.h +./src/H5Tprecis.c ./src/H5Tprivate.h ./src/H5Tpublic.h +./src/H5Tstrpad.c ./src/H5Tvlen.c ./src/H5TB.c ./src/H5TBprivate.h diff --git a/src/H5T.c b/src/H5T.c index 86a3876..90c62bd 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -1,33 +1,41 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + /* - * Copyright (C) 1998-2001 NCSA - * All rights reserved. - * - * Programmer: Robb Matzke - * Tuesday, March 31, 1998 + * Module Info: This module contains most of the "core" functionality of + * the H5T interface, including the API initialization code, etc. + * Many routines that are infrequently used, or are specialized for + * one particular datatype class are in another module. */ #define H5T_PACKAGE /*suppress error about including H5Tpkg */ #include "H5private.h" /*generic functions */ #include "H5Dprivate.h" /*datasets (for H5Tcopy) */ -#include "H5Iprivate.h" /*ID functions */ #include "H5Eprivate.h" /*error handling */ #include "H5FLprivate.h" /*Free Lists */ #include "H5Gprivate.h" /*groups */ -#include "H5HGprivate.h" /*global heap */ +#include "H5Iprivate.h" /*ID functions */ #include "H5MMprivate.h" /*memory management */ #include "H5Pprivate.h" /* Property Lists */ -#include "H5Sprivate.h" /*data space */ #include "H5Tpkg.h" /*data-type functions */ #define PABLO_MASK H5T_mask -#define H5T_COMPND_INC 64 /*typical max numb of members per struct */ - /* Interface initialization */ static int interface_initialize_g = 0; #define INTERFACE_INIT H5T_init_interface -static herr_t H5T_init_interface(void); /* * Predefined data types. These are initialized at runtime in H5Tinit.c and @@ -222,9 +230,6 @@ static struct { /* The overflow handler */ H5T_overflow_t H5T_overflow_g = NULL; -/* Local static functions */ -static herr_t H5T_print_stats(H5T_path_t *path, int *nprint/*in,out*/); - /* Declare the free list for H5T_t's */ H5FL_DEFINE(H5T_t); @@ -232,9 +237,12 @@ H5FL_DEFINE(H5T_t); H5FL_DEFINE(H5T_path_t); /* Static local functions */ +static H5T_t *H5T_open(H5G_entry_t *loc, const char *name, hid_t dxpl_id); +static herr_t H5T_print_stats(H5T_path_t *path, int *nprint/*in,out*/); +static herr_t H5T_unregister(H5T_pers_t pers, const char *name, H5T_t *src, + H5T_t *dst, H5T_conv_t func, hid_t dxpl_id); static herr_t H5T_register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_conv_t func, hid_t dxpl_id); -static H5T_t * H5T_vlen_create(H5T_t *base); /*------------------------------------------------------------------------- @@ -278,7 +286,7 @@ DESCRIPTION Initializes any interface-specific data or routines. --------------------------------------------------------------------------*/ -static herr_t +herr_t H5T_init_interface(void) { H5T_t *native_schar=NULL; /* Datatype structure for native signed char */ @@ -2126,85 +2134,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5Tcommit - * - * Purpose: Save a transient data type to a file and turn the type handle - * into a named, immutable type. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Monday, June 1, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tcommit(hid_t loc_id, const char *name, hid_t type_id) -{ - H5G_entry_t *loc = NULL; - H5T_t *type = NULL; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Tcommit, FAIL); - H5TRACE3("e","isi",loc_id,name,type_id); - - /* Check arguments */ - if (NULL==(loc=H5G_loc (loc_id))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); - if (!name || !*name) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no name"); - if (NULL==(type=H5I_object_verify(type_id, H5I_DATATYPE))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - - /* Commit the type */ - if (H5T_commit (loc, name, type, H5AC_dxpl_id)<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to commit data type"); - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tcommitted - * - * Purpose: Determines if a data type is committed or not. - * - * Return: Success: TRUE if committed, FALSE otherwise. - * - * Failure: Negative - * - * Programmer: Robb Matzke - * Thursday, June 4, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -htri_t -H5Tcommitted(hid_t type_id) -{ - H5T_t *type = NULL; - htri_t ret_value; /* Return value */ - - FUNC_ENTER_API(H5Tcommitted, FAIL); - H5TRACE1("b","i",type_id); - - /* Check arguments */ - if (NULL==(type=H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - - /* Set return value */ - ret_value= (H5T_STATE_OPEN==type->state || H5T_STATE_NAMED==type->state); - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- * Function: H5Tcopy * * Purpose: Copies a data type. The resulting data type is not locked. @@ -2642,696 +2571,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5Tget_native_type - * - * Purpose: High-level API to return the native type of a datatype. - * The native type is chosen by matching the size and class of - * querried datatype from the following native premitive - * datatypes: - * H5T_NATIVE_CHAR H5T_NATIVE_UCHAR - * H5T_NATIVE_SHORT H5T_NATIVE_USHORT - * H5T_NATIVE_INT H5T_NATIVE_UINT - * H5T_NATIVE_LONG H5T_NATIVE_ULONG - * H5T_NATIVE_LLONG H5T_NATIVE_ULLONG - * - * H5T_NATIVE_FLOAT - * H5T_NATIVE_DOUBLE - * H5T_NATIVE_LDOUBLE - * - * Compound, array, enum, and VL types all choose among these - * types for theire members. Time, Bifield, Opaque, Reference - * types are only copy out. - * - * Return: Success: Returns the native data type if successful. - * - * Failure: negative - * - * Programmer: Raymond Lu - * Oct 3, 2002 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -hid_t H5Tget_native_type(hid_t type_id, H5T_direction_t direction) -{ - H5T_t *dt; /* Datatype to create native datatype from */ - H5T_t *new_dt=NULL; /* Datatype for native datatype created */ - size_t comp_size=0; /* Compound datatype's size */ - hid_t ret_value; /* Return value */ - - FUNC_ENTER_API(H5Tget_native_type, FAIL); - H5TRACE1("z","i",type_id); - - /* check argument */ - if(NULL==(dt=H5I_object_verify(type_id, H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - - if(direction!=H5T_DIR_DEFAULT && direction!=H5T_DIR_ASCEND - && direction!=H5T_DIR_DESCEND) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not valid direction value"); - - if((new_dt = H5T_get_native_type(dt, direction, NULL, NULL, &comp_size))==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "cannot retrieve native type"); - - if((ret_value=H5I_register(H5I_DATATYPE, new_dt)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data type"); - -done: - /* Error cleanup */ - if(ret_value<0) { - if(new_dt) - H5T_close(new_dt); - } /* end if */ - - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_get_native_type - * - * Purpose: Returns the native type of a datatype. - * - * Return: Success: Returns the native data type if successful. - * - * Failure: negative - * - * Programmer: Raymond Lu - * Oct 3, 2002 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5T_t* H5T_get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_align, size_t *offset, size_t *comp_size) -{ - H5T_t *dt; /* Datatype to make native */ - H5T_class_t h5_class; /* Class of datatype to make native */ - size_t size; /* Size of datatype to make native */ - int nmemb; /* Number of members in compound & enum types */ - H5T_t *super_type; /* Super type of VL, array and enum datatypes */ - H5T_t *nat_super_type; /* Native form of VL, array & enum super datatype */ - H5T_t *new_type=NULL; /* New native datatype */ - int i; /* Local index variable */ - H5T_t *ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(H5T_get_native_type, NULL); - - assert(dtype); - - if((h5_class = H5T_get_class(dtype))<0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a valid class"); - - if((size = H5T_get_size(dtype))==0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a valid size"); - - switch(h5_class) { - case H5T_INTEGER: - { - H5T_sign_t sign; /* Signedness of integer type */ - - if((sign = H5T_get_sign(dtype))==H5T_SGN_ERROR) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a valid signess"); - - if((ret_value = H5T_get_native_integer(size, sign, direction, struct_align, offset, comp_size))==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve integer type"); - } - break; - - case H5T_FLOAT: - if((ret_value = H5T_get_native_float(size, direction, struct_align, offset, comp_size))==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); - - break; - - case H5T_STRING: - { - size_t align; - size_t pointer_size; - - if(H5T_is_variable_str(dtype)) { - if(NULL==(dt=H5I_object(H5T_C_S1))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); - if((ret_value=H5T_copy(dt, H5T_COPY_TRANSIENT))==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); - if(H5T_set_size(ret_value, H5T_VARIABLE)<0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot set size"); - - /* Update size, offset and compound alignment for parent. */ - align = H5T_POINTER_COMP_ALIGN_g; - pointer_size = sizeof(char*); - - if(H5T_cmp_offset(comp_size, offset, pointer_size, 1, align, struct_align)<0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset"); - - } else { - /*size_t char_size;*/ - - if(NULL==(dt=H5I_object(H5T_NATIVE_UCHAR))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); - if((ret_value=H5T_copy(dt, H5T_COPY_TRANSIENT))==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); - if(H5T_set_size(ret_value, size)<0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot set size"); - - /* Update size, offset and compound alignment for parent. */ - align = H5T_NATIVE_SCHAR_COMP_ALIGN_g; - - if(H5T_cmp_offset(comp_size, offset, sizeof(char), size, align, struct_align)<0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset"); - - } - } - break; - - /* These three types don't need to compute compound field information since they - * can't be used as field. */ - case H5T_TIME: - case H5T_BITFIELD: - case H5T_OPAQUE: - if((ret_value=H5T_copy(dtype, H5T_COPY_TRANSIENT))==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); - - break; - case H5T_REFERENCE: - { - size_t align; - size_t ref_size; - int not_equal; - - if((ret_value=H5T_copy(dtype, H5T_COPY_TRANSIENT))==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); - - /* Decide if the data type is object or dataset region reference. */ - if(NULL==(dt=H5I_object(H5T_STD_REF_OBJ_g))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); - not_equal = H5T_cmp(ret_value, dt); - - /* Update size, offset and compound alignment for parent. */ - if(!not_equal) { - align = H5T_HOBJREF_COMP_ALIGN_g; - ref_size = sizeof(hobj_ref_t); - } else { - align = H5T_HDSETREGREF_COMP_ALIGN_g; - ref_size = sizeof(hdset_reg_ref_t); - } - - if(H5T_cmp_offset(comp_size, offset, ref_size, 1, align, struct_align)<0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset"); - } - break; - - case H5T_COMPOUND: - { - H5T_t *memb_type; /* Datatype of member */ - H5T_t **memb_list; /* List of compound member IDs */ - size_t *memb_offset; /* List of member offsets in compound type, including member size and alignment */ - size_t children_size=0;/* Total size of compound members */ - size_t children_st_align=0; /* The max alignment among compound members. This'll be the compound alignment */ - char **comp_mname; /* List of member names in compound type */ - - if((nmemb = H5T_get_nmembers(dtype))<=0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "compound data type doesn't have any member"); - - if((memb_list = (H5T_t**)H5MM_malloc(nmemb*sizeof(H5T_t*)))==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot allocate memory"); - if((memb_offset = (size_t*)H5MM_calloc(nmemb*sizeof(size_t)))==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot allocate memory"); - if((comp_mname = (char**)H5MM_malloc(nmemb*sizeof(char*)))==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot allocate memory"); - - /* Construct child compound type and retrieve a list of their IDs, offsets, total size, and alignment for compound type. */ - for(i=0; i0); - - if(direction == H5T_DIR_DEFAULT || direction == H5T_DIR_ASCEND) { - if(size==sizeof(char)) - match=H5T_NATIVE_INT_MATCH_CHAR; - else if(size==sizeof(short)) - match=H5T_NATIVE_INT_MATCH_SHORT; - else if(size==sizeof(int)) - match=H5T_NATIVE_INT_MATCH_INT; - else if(size==sizeof(long)) - match=H5T_NATIVE_INT_MATCH_LONG; - else if(size==sizeof(long_long)) - match=H5T_NATIVE_INT_MATCH_LLONG; - else /* If no native type matches the querried datatype, simply choose the type of biggest size. */ - match=H5T_NATIVE_INT_MATCH_LLONG; - } else if(direction == H5T_DIR_DESCEND) { - if(size==sizeof(long_long)) - match=H5T_NATIVE_INT_MATCH_LLONG; - else if(size==sizeof(long)) - match=H5T_NATIVE_INT_MATCH_LONG; - else if(size==sizeof(int)) - match=H5T_NATIVE_INT_MATCH_INT; - else if(size==sizeof(short)) - match=H5T_NATIVE_INT_MATCH_SHORT; - else if(size==sizeof(char)) - match=H5T_NATIVE_INT_MATCH_CHAR; - else /* If no native type matches the querried datatype, simple choose the type of smallest size. */ - match=H5T_NATIVE_INT_MATCH_CHAR; - } - - /* Set the appropriate native datatype information */ - switch(match) { - case H5T_NATIVE_INT_MATCH_CHAR: - if(sign==H5T_SGN_2) - tid = H5T_NATIVE_SCHAR; - else - tid = H5T_NATIVE_UCHAR; - - align = H5T_NATIVE_SCHAR_COMP_ALIGN_g; - break; - - case H5T_NATIVE_INT_MATCH_SHORT: - if(sign==H5T_SGN_2) - tid = H5T_NATIVE_SHORT; - else - tid = H5T_NATIVE_USHORT; - - align = H5T_NATIVE_SHORT_COMP_ALIGN_g; - break; - - case H5T_NATIVE_INT_MATCH_INT: - if(sign==H5T_SGN_2) - tid = H5T_NATIVE_INT; - else - tid = H5T_NATIVE_UINT; - - align = H5T_NATIVE_INT_COMP_ALIGN_g; - break; - - case H5T_NATIVE_INT_MATCH_LONG: - if(sign==H5T_SGN_2) - tid = H5T_NATIVE_LONG; - else - tid = H5T_NATIVE_ULONG; - - align = H5T_NATIVE_LONG_COMP_ALIGN_g; - break; - - case H5T_NATIVE_INT_MATCH_LLONG: - if(sign==H5T_SGN_2) - tid = H5T_NATIVE_LLONG; - else - tid = H5T_NATIVE_ULLONG; - - align = H5T_NATIVE_LLONG_COMP_ALIGN_g; - break; - - default: - assert(0 && "Unknown native integer match!"); - break; - } /* end switch */ - - /* Create new native type */ - assert(tid>=0); - if(NULL==(dt=H5I_object(tid))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); - if((ret_value=H5T_copy(dt, H5T_COPY_TRANSIENT))==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); - - /* compute size and offset of compound type member. */ - if(H5T_cmp_offset(comp_size, offset, size, 1, align, struct_align)<0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_get_native_float - * - * Purpose: Returns the native floatt type of a datatype. - * - * Return: Success: Returns the native data type if successful. - * - * Failure: negative - * - * Programmer: Raymond Lu - * Oct 3, 2002 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5T_t* H5T_get_native_float(size_t size, H5T_direction_t direction, size_t *struct_align, size_t *offset, size_t *comp_size) -{ - H5T_t *dt=NULL; /* Appropriate native datatype to copy */ - hid_t tid=(-1); /* Datatype ID of appropriate native datatype */ - size_t align=0; /* Alignment necessary for native datatype */ - enum match_type { /* The different kinds of floating point types we can match */ - H5T_NATIVE_FLOAT_MATCH_FLOAT, - H5T_NATIVE_FLOAT_MATCH_DOUBLE, - H5T_NATIVE_FLOAT_MATCH_LDOUBLE, - H5T_NATIVE_FLOAT_MATCH_UNKNOWN - } match=H5T_NATIVE_FLOAT_MATCH_UNKNOWN; - H5T_t *ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(H5T_get_native_integer, NULL); - - assert(size>0); - - if(direction == H5T_DIR_DEFAULT || direction == H5T_DIR_ASCEND) { - if(size==sizeof(float)) - match=H5T_NATIVE_FLOAT_MATCH_FLOAT; - else if(size==sizeof(double)) - match=H5T_NATIVE_FLOAT_MATCH_DOUBLE; - else if(size==sizeof(long double)) - match=H5T_NATIVE_FLOAT_MATCH_LDOUBLE; - else /* If not match, return the biggest datatype */ - match=H5T_NATIVE_FLOAT_MATCH_LDOUBLE; - } else { - if(size==sizeof(long double)) - match=H5T_NATIVE_FLOAT_MATCH_LDOUBLE; - else if(size==sizeof(double)) - match=H5T_NATIVE_FLOAT_MATCH_DOUBLE; - else if(size==sizeof(float)) - match=H5T_NATIVE_FLOAT_MATCH_FLOAT; - else - match=H5T_NATIVE_FLOAT_MATCH_FLOAT; - } - - /* Set the appropriate native floating point information */ - switch(match) { - case H5T_NATIVE_FLOAT_MATCH_FLOAT: - tid = H5T_NATIVE_FLOAT; - align = H5T_NATIVE_FLOAT_COMP_ALIGN_g; - break; - - case H5T_NATIVE_FLOAT_MATCH_DOUBLE: - tid = H5T_NATIVE_DOUBLE; - align = H5T_NATIVE_DOUBLE_COMP_ALIGN_g; - break; - - case H5T_NATIVE_FLOAT_MATCH_LDOUBLE: - tid = H5T_NATIVE_LDOUBLE; - align = H5T_NATIVE_LDOUBLE_COMP_ALIGN_g; - break; - - default: - assert(0 && "Unknown native floating-point match!"); - break; - } /* end switch */ - - /* Create new native type */ - assert(tid>=0); - if(NULL==(dt=H5I_object(tid))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); - if((ret_value=H5T_copy(dt, H5T_COPY_TRANSIENT))==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); - - /* compute offset of compound type member. */ - if(H5T_cmp_offset(comp_size, offset, size, 1, align, struct_align)<0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_cmp_offset - * - * Purpose: This function is only for convenience. It computes the - * compound type size, offset of the member being considered - * and the alignment for the whole compound type. - * - * Return: Success: Non-negative value. - * - * Failure: Negative value. - * - * Programmer: Raymond Lu - * December 10, 2002 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t H5T_cmp_offset(size_t *comp_size, size_t *offset, size_t elem_size, - size_t nelems, size_t align, size_t *struct_align) -{ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI(H5T_cmp_offset, FAIL); - - if(offset && comp_size) { - if(align>1 && *comp_size%align) { - /* Add alignment value */ - *offset = *comp_size + (align - *comp_size%align); - *comp_size += (align - *comp_size%align); - } else - *offset = *comp_size; - - /* compute size of compound type member. */ - *comp_size += nelems*elem_size; - } - - if(struct_align && *struct_align < align) - *struct_align = align; - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- * Function: H5Tget_size * * Purpose: Determines the total size of a data type in bytes. @@ -3431,324 +2670,428 @@ done: /*------------------------------------------------------------------------- - * Function: H5Tget_order + * Function: H5Tget_super * - * Purpose: Returns the byte order of a data type. + * Purpose: Returns the type from which TYPE is derived. In the case of + * an enumeration type the return value is an integer type. * - * Return: Success: A byte order constant + * Return: Success: Type ID for base data type. * - * Failure: H5T_ORDER_ERROR (Negative) + * Failure: negative * * Programmer: Robb Matzke - * Wednesday, January 7, 1998 + * Wednesday, December 23, 1998 * * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works for derived data types. * *------------------------------------------------------------------------- */ -H5T_order_t -H5Tget_order(hid_t type_id) +hid_t +H5Tget_super(hid_t type) { - H5T_t *dt = NULL; - H5T_order_t ret_value; - - FUNC_ENTER_API(H5Tget_order, H5T_ORDER_ERROR); - H5TRACE1("To","i",type_id); + H5T_t *dt=NULL, *super=NULL; + hid_t ret_value; + + FUNC_ENTER_API(H5Tget_super, FAIL); + H5TRACE1("i","i",type); - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_ORDER_ERROR, "not a data type"); - - if (dt->parent) - dt = dt->parent; /*defer to parent*/ - if (H5T_COMPOUND==dt->type || H5T_OPAQUE==dt->type || H5T_ARRAY ==dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5T_ORDER_ERROR, "operation not defined for specified data type"); - - /* Order */ - assert(H5T_is_atomic(dt)); - ret_value = dt->u.atomic.order; + if (NULL==(dt=H5I_object_verify(type,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if((super=H5T_get_super(dt))==NULL) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "not a data type"); + if ((ret_value=H5I_register(H5I_DATATYPE, super))<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register parent data type"); done: + if(ret_value<0) { + if(super!=NULL) + H5T_close(super); + } /* end if */ + FUNC_LEAVE_API(ret_value); } /*------------------------------------------------------------------------- - * Function: H5Tset_order + * Function: H5T_get_super * - * Purpose: Sets the byte order for a data type. + * Purpose: Private function for H5Tget_super. Returns the type from + * which TYPE is derived. In the case of an enumeration type + * the return value is an integer type. * - * Return: Non-negative on success/Negative on failure + * Return: Success: Data type for base data type. * - * Programmer: Robb Matzke - * Wednesday, January 7, 1998 + * Failure: NULL + * + * Programmer: Raymond Lu + * October 9, 2002 * * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works for derived data types. * *------------------------------------------------------------------------- */ -herr_t -H5Tset_order(hid_t type_id, H5T_order_t order) +H5T_t * +H5T_get_super(H5T_t *dt) { - H5T_t *dt = NULL; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Tset_order, FAIL); - H5TRACE2("e","iTo",type_id,order); + H5T_t *ret_value=NULL; + + FUNC_ENTER_NOAPI(H5T_get_super, NULL); - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (H5T_STATE_TRANSIENT!=dt->state) - HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); - if (order < 0 || order > H5T_ORDER_NONE) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "illegal byte order"); - if (H5T_ENUM==dt->type && dt->u.enumer.nmembs>0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined"); - if (dt->parent) - dt = dt->parent; /*defer to parent*/ - if (H5T_COMPOUND==dt->type || H5T_OPAQUE==dt->type || H5T_ARRAY==dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5T_ORDER_ERROR, "operation not defined for specified data type"); + assert(dt); - /* Commit */ - assert(H5T_is_atomic(dt)); - dt->u.atomic.order = order; + if (!dt->parent) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a derived data type"); + if (NULL==(ret_value=H5T_copy(dt->parent, H5T_COPY_ALL))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy parent data type"); done: - FUNC_LEAVE_API(ret_value); + FUNC_LEAVE_NOAPI(ret_value); } /*------------------------------------------------------------------------- - * Function: H5Tget_precision - * - * Purpose: Gets the precision of a data type. The precision is - * the number of significant bits which, unless padding is - * present, is 8 times larger than the value returned by - * H5Tget_size(). + * Function: H5T_register * - * Return: Success: Number of significant bits + * Purpose: Register a hard or soft conversion function for a data type + * conversion path. The path is specified by the source and + * destination data types SRC_ID and DST_ID (for soft functions + * only the class of these types is important). If FUNC is a + * hard function then it replaces any previous path; if it's a + * soft function then it replaces all existing paths to which it + * applies and is used for any new path to which it applies as + * long as that path doesn't have a hard function. * - * Failure: 0 (all atomic types have at least one - * significant bit) + * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke - * Wednesday, January 7, 1998 + * Friday, January 9, 1998 * * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works for derived data types. * *------------------------------------------------------------------------- */ -size_t -H5Tget_precision(hid_t type_id) +static herr_t +H5T_register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, + H5T_conv_t func, hid_t dxpl_id) { - H5T_t *dt = NULL; - size_t ret_value; + hid_t tmp_sid=-1, tmp_did=-1;/*temporary data type IDs */ + H5T_path_t *old_path=NULL; /*existing conversion path */ + H5T_path_t *new_path=NULL; /*new conversion path */ + H5T_cdata_t cdata; /*temporary conversion data */ + int nprint=0; /*number of paths shut down */ + int i; /*counter */ + herr_t ret_value=SUCCEED; /*return value */ - FUNC_ENTER_API(H5Tget_precision, 0); - H5TRACE1("z","i",type_id); + FUNC_ENTER_NOINIT(H5T_register); /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a data type"); - if (dt->parent) - dt = dt->parent; /*defer to parent*/ - if (H5T_COMPOUND==dt->type || H5T_OPAQUE==dt->type || H5T_ARRAY==dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, 0, "operation not defined for specified data type"); - - /* Precision */ - assert(H5T_is_atomic(dt)); - ret_value = dt->u.atomic.prec; + assert(src); + assert(dst); + assert(func); + assert(H5T_PERS_HARD==pers || H5T_PERS_SOFT==pers); + assert(name && *name); + + if (H5T_PERS_HARD==pers) { + /* Locate or create a new conversion path */ + if (NULL==(new_path=H5T_path_find(src, dst, name, func, dxpl_id))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to locate/allocate conversion path"); + + /* + * Notify all other functions to recalculate private data since some + * functions might cache a list of conversion functions. For + * instance, the compound type converter caches a list of conversion + * functions for the members, so adding a new function should cause + * the list to be recalculated to use the new function. + */ + for (i=0; icdata.recalc = TRUE; + } /* end for */ + + } else { + /* Add function to end of soft list */ + if (H5T_g.nsoft>=H5T_g.asoft) { + size_t na = MAX(32, 2*H5T_g.asoft); + H5T_soft_t *x = H5MM_realloc(H5T_g.soft, na*sizeof(H5T_soft_t)); + + if (!x) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + H5T_g.asoft = (int)na; + H5T_g.soft = x; + } /* end if */ + HDstrncpy (H5T_g.soft[H5T_g.nsoft].name, name, H5T_NAMELEN); + H5T_g.soft[H5T_g.nsoft].name[H5T_NAMELEN-1] = '\0'; + H5T_g.soft[H5T_g.nsoft].src = src->type; + H5T_g.soft[H5T_g.nsoft].dst = dst->type; + H5T_g.soft[H5T_g.nsoft].func = func; + H5T_g.nsoft++; + + /* + * Any existing path (except the no-op path) to which this new soft + * conversion function applies should be replaced by a new path that + * uses this function. + */ + for (i=1; iis_hard || + old_path->src->type!=src->type || + old_path->dst->type!=dst->type) { + continue; + } + if ((tmp_sid = H5I_register(H5I_DATATYPE, H5T_copy(old_path->src, H5T_COPY_ALL)))<0 || + (tmp_did = H5I_register(H5I_DATATYPE, H5T_copy(old_path->dst, H5T_COPY_ALL)))<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data types for conv query"); + HDmemset(&cdata, 0, sizeof cdata); + cdata.command = H5T_CONV_INIT; + if ((func)(tmp_sid, tmp_did, &cdata, (hsize_t)0, 0, 0, NULL, NULL, dxpl_id)<0) { + H5I_dec_ref(tmp_sid); + H5I_dec_ref(tmp_did); + tmp_sid = tmp_did = -1; + H5E_clear(); + continue; + } /* end if */ + + /* Create a new conversion path */ + if (NULL==(new_path=H5FL_CALLOC(H5T_path_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + HDstrncpy(new_path->name, name, H5T_NAMELEN); + new_path->name[H5T_NAMELEN-1] = '\0'; + if (NULL==(new_path->src=H5T_copy(old_path->src, H5T_COPY_ALL)) || + NULL==(new_path->dst=H5T_copy(old_path->dst, H5T_COPY_ALL))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy data types"); + new_path->func = func; + new_path->is_hard = FALSE; + new_path->cdata = cdata; + + /* Replace previous path */ + H5T_g.path[i] = new_path; + new_path = NULL; /*so we don't free it on error*/ + + /* Free old path */ + H5T_print_stats(old_path, &nprint); + old_path->cdata.command = H5T_CONV_FREE; + if ((old_path->func)(tmp_sid, tmp_did, &(old_path->cdata), (hsize_t)0, 0, 0, NULL, NULL, dxpl_id)<0) { +#ifdef H5T_DEBUG + if (H5DEBUG(T)) { + fprintf (H5DEBUG(T), "H5T: conversion function 0x%08lx " + "failed to free private data for %s (ignored)\n", + (unsigned long)(old_path->func), old_path->name); + } +#endif + } /* end if */ + H5T_close(old_path->src); + H5T_close(old_path->dst); + H5FL_FREE(H5T_path_t,old_path); + + /* Release temporary atoms */ + H5I_dec_ref(tmp_sid); + H5I_dec_ref(tmp_did); + tmp_sid = tmp_did = -1; + /* We don't care about any failures during the freeing process */ + H5E_clear(); + } /* end for */ + } /* end else */ + done: - FUNC_LEAVE_API(ret_value); -} + if (ret_value<0) { + if (new_path) { + if (new_path->src) + H5T_close(new_path->src); + if (new_path->dst) + H5T_close(new_path->dst); + H5FL_FREE(H5T_path_t,new_path); + } /* end if */ + if (tmp_sid>=0) + H5I_dec_ref(tmp_sid); + if (tmp_did>=0) + H5I_dec_ref(tmp_did); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5T_register() */ /*------------------------------------------------------------------------- - * Function: H5Tset_precision - * - * Purpose: Sets the precision of a data type. The precision is - * the number of significant bits which, unless padding is - * present, is 8 times larger than the value returned by - * H5Tget_size(). - * - * If the precision is increased then the offset is decreased - * and then the size is increased to insure that significant - * bits do not "hang over" the edge of the data type. - * - * The precision property of strings is read-only. + * Function: H5Tregister * - * When decreasing the precision of a floating point type, set - * the locations and sizes of the sign, mantissa, and exponent - * fields first. + * Purpose: Register a hard or soft conversion function for a data type + * conversion path. The path is specified by the source and + * destination data types SRC_ID and DST_ID (for soft functions + * only the class of these types is important). If FUNC is a + * hard function then it replaces any previous path; if it's a + * soft function then it replaces all existing paths to which it + * applies and is used for any new path to which it applies as + * long as that path doesn't have a hard function. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke - * Wednesday, January 7, 1998 + * Friday, January 9, 1998 * * Modifications: - * Robb Matzke, 22 Dec 1998 - * Moved real work to a private function. * *------------------------------------------------------------------------- */ herr_t -H5Tset_precision(hid_t type_id, size_t prec) +H5Tregister(H5T_pers_t pers, const char *name, hid_t src_id, hid_t dst_id, + H5T_conv_t func) { - H5T_t *dt = NULL; - herr_t ret_value=SUCCEED; /* Return value */ + H5T_t *src; /*source data type descriptor */ + H5T_t *dst; /*destination data type desc */ + herr_t ret_value=SUCCEED; /*return value */ - FUNC_ENTER_API(H5Tset_precision, FAIL); - H5TRACE2("e","iz",type_id,prec); + FUNC_ENTER_API(H5Tregister, FAIL); + H5TRACE5("e","Tesiix",pers,name,src_id,dst_id,func); /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + if (H5T_PERS_HARD!=pers && H5T_PERS_SOFT!=pers) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid function persistence"); + if (!name || !*name) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "conversion must have a name for debugging"); + if (NULL==(src=H5I_object_verify(src_id,H5I_DATATYPE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (H5T_STATE_TRANSIENT!=dt->state) - HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); - if (prec <= 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "precision must be positive"); - if (H5T_ENUM==dt->type && dt->u.enumer.nmembs>0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined"); + if (NULL==(dst=H5I_object_verify(dst_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (!func) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no conversion function specified"); - /* Do the work */ - if (H5T_set_precision(dt, prec)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set precision"); + /* Go register the function */ + if(H5T_register(pers,name,src,dst,func,H5AC_ind_dxpl_id)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "can't register conversion function"); done: FUNC_LEAVE_API(ret_value); -} +} /* end H5Tregister() */ /*------------------------------------------------------------------------- - * Function: H5Tget_offset + * Function: H5T_unregister * - * Purpose: Retrieves the bit offset of the first significant bit. The - * signficant bits of an atomic datum can be offset from the - * beginning of the memory for that datum by an amount of - * padding. The `offset' property specifies the number of bits - * of padding that appear to the "right of" the value. That is, - * if we have a 32-bit datum with 16-bits of precision having - * the value 0x1122 then it will be layed out in memory as (from - * small byte address toward larger byte addresses): - * - * Big Big Little Little - * Endian Endian Endian Endian - * offset=0 offset=16 offset=0 offset=16 - * - * 0: [ pad] [0x11] [0x22] [ pad] - * 1: [ pad] [0x22] [0x11] [ pad] - * 2: [0x11] [ pad] [ pad] [0x22] - * 3: [0x22] [ pad] [ pad] [0x11] + * Purpose: Removes conversion paths that match the specified criteria. + * All arguments are optional. Missing arguments are wild cards. + * The special no-op path cannot be removed. * - * Return: Success: The offset (non-negative) + * Return: Succeess: non-negative * - * Failure: Negative + * Failure: negative * * Programmer: Robb Matzke - * Wednesday, January 7, 1998 + * Tuesday, January 13, 1998 * * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works for derived data types. + * Adapted to non-API function - QAK, 11/17/99 * *------------------------------------------------------------------------- */ -int -H5Tget_offset(hid_t type_id) +static herr_t +H5T_unregister(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, + H5T_conv_t func, hid_t dxpl_id) { - H5T_t *dt = NULL; - int ret_value; + H5T_path_t *path = NULL; /*conversion path */ + H5T_soft_t *soft = NULL; /*soft conversion information */ + int nprint=0; /*number of paths shut down */ + int i; /*counter */ + herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_API(H5Tget_offset, -1); - H5TRACE1("Is","i",type_id); + FUNC_ENTER_NOAPI(H5T_unregister, FAIL); - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an atomic data type"); - if (dt->parent) - dt = dt->parent; /*defer to parent*/ - if (H5T_COMPOUND==dt->type || H5T_OPAQUE==dt->type || H5T_ARRAY==dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for specified data type"); - - /* Offset */ - assert(H5T_is_atomic(dt)); - ret_value = (int)dt->u.atomic.offset; + /* Remove matching entries from the soft list */ + if (H5T_PERS_DONTCARE==pers || H5T_PERS_SOFT==pers) { + for (i=H5T_g.nsoft-1; i>=0; --i) { + soft = H5T_g.soft+i; + assert(soft); + if (name && *name && HDstrcmp(name, soft->name)) continue; + if (src && src->type!=soft->src) continue; + if (dst && dst->type!=soft->dst) continue; + if (func && func!=soft->func) continue; + + HDmemmove(H5T_g.soft+i, H5T_g.soft+i+1, + (H5T_g.nsoft-(i+1)) * sizeof(H5T_soft_t)); + --H5T_g.nsoft; + } + } + + /* Remove matching conversion paths, except no-op path */ + for (i=H5T_g.npaths-1; i>0; --i) { + path = H5T_g.path[i]; + assert(path); + if ((H5T_PERS_SOFT==pers && path->is_hard) || + (H5T_PERS_HARD==pers && !path->is_hard)) continue; + if (name && *name && HDstrcmp(name, path->name)) continue; + if (src && H5T_cmp(src, path->src)) continue; + if (dst && H5T_cmp(dst, path->dst)) continue; + if (func && func!=path->func) continue; + + /* Remove from table */ + HDmemmove(H5T_g.path+i, H5T_g.path+i+1, + (H5T_g.npaths-(i+1))*sizeof(H5T_path_t*)); + --H5T_g.npaths; + + /* Shut down path */ + H5T_print_stats(path, &nprint); + path->cdata.command = H5T_CONV_FREE; + if ((path->func)(FAIL, FAIL, &(path->cdata), (hsize_t)0, 0, 0, NULL, NULL, + dxpl_id)<0) { +#ifdef H5T_DEBUG + if (H5DEBUG(T)) { + fprintf(H5DEBUG(T), "H5T: conversion function 0x%08lx failed " + "to free private data for %s (ignored)\n", + (unsigned long)(path->func), path->name); + } +#endif + } + H5T_close(path->src); + H5T_close(path->dst); + H5FL_FREE(H5T_path_t,path); + H5E_clear(); /*ignore all shutdown errors*/ + } done: - FUNC_LEAVE_API(ret_value); -} + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5T_unregister() */ /*------------------------------------------------------------------------- - * Function: H5Tset_offset - * - * Purpose: Sets the bit offset of the first significant bit. The - * signficant bits of an atomic datum can be offset from the - * beginning of the memory for that datum by an amount of - * padding. The `offset' property specifies the number of bits - * of padding that appear to the "right of" the value. That is, - * if we have a 32-bit datum with 16-bits of precision having - * the value 0x1122 then it will be layed out in memory as (from - * small byte address toward larger byte addresses): - * - * Big Big Little Little - * Endian Endian Endian Endian - * offset=0 offset=16 offset=0 offset=16 - * - * 0: [ pad] [0x11] [0x22] [ pad] - * 1: [ pad] [0x22] [0x11] [ pad] - * 2: [0x11] [ pad] [ pad] [0x22] - * 3: [0x22] [ pad] [ pad] [0x11] + * Function: H5Tunregister * - * If the offset is incremented then the total size is - * incremented also if necessary to prevent significant bits of - * the value from hanging over the edge of the data type. + * Purpose: Removes conversion paths that match the specified criteria. + * All arguments are optional. Missing arguments are wild cards. + * The special no-op path cannot be removed. * - * The offset of an H5T_STRING cannot be set to anything but - * zero. + * Return: Succeess: non-negative * - * Return: Non-negative on success/Negative on failure + * Failure: negative * * Programmer: Robb Matzke - * Wednesday, January 7, 1998 + * Tuesday, January 13, 1998 * * Modifications: - * Robb Matzke, 22 Dec 1998 - * Moved real work to a private function. + * Changed to use H5T_unregister wrapper function - QAK, 11/17/99 * *------------------------------------------------------------------------- */ herr_t -H5Tset_offset(hid_t type_id, size_t offset) +H5Tunregister(H5T_pers_t pers, const char *name, hid_t src_id, hid_t dst_id, + H5T_conv_t func) { - H5T_t *dt = NULL; + H5T_t *src=NULL, *dst=NULL; /*data type descriptors */ herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_API(H5Tset_offset, FAIL); - H5TRACE2("e","iz",type_id,offset); + FUNC_ENTER_API(H5Tunregister, FAIL); + H5TRACE5("e","Tesiix",pers,name,src_id,dst_id,func); - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an atomic data type"); - if (H5T_STATE_TRANSIENT!=dt->state) - HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); - if (H5T_STRING == dt->type && offset != 0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "offset must be zero for this type"); - if (H5T_ENUM==dt->type && dt->u.enumer.nmembs>0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined"); + /* Check arguments */ + if (src_id>0 && (NULL==(src=H5I_object_verify(src_id,H5I_DATATYPE)))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "src is not a data type"); + if (dst_id>0 && (NULL==(dst=H5I_object_verify(dst_id,H5I_DATATYPE)))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dst is not a data type"); - /* Do the real work */ - if (H5T_set_offset(dt, offset)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set offset"); + if (H5T_unregister(pers,name,src,dst,func,H5AC_ind_dxpl_id)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDELETE, FAIL, "internal unregister function failed"); done: FUNC_LEAVE_API(ret_value); @@ -3756,95 +3099,111 @@ done: /*------------------------------------------------------------------------- - * Function: H5Tget_pad + * Function: H5Tfind * - * Purpose: Gets the least significant pad type and the most significant - * pad type and returns their values through the LSB and MSB - * arguments, either of which may be the null pointer. + * Purpose: Finds a conversion function that can handle a conversion from + * type SRC_ID to type DST_ID. The PCDATA argument is a pointer + * to a pointer to type conversion data which was created and + * initialized by the type conversion function of this path + * when the conversion function was installed on the path. * - * Return: Non-negative on success/Negative on failure + * Return: Success: A pointer to a suitable conversion function. + * + * Failure: NULL * * Programmer: Robb Matzke - * Friday, January 9, 1998 + * Tuesday, January 13, 1998 * * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works with derived data types. * *------------------------------------------------------------------------- */ -herr_t -H5Tget_pad(hid_t type_id, H5T_pad_t *lsb/*out*/, H5T_pad_t *msb/*out*/) +H5T_conv_t +H5Tfind(hid_t src_id, hid_t dst_id, H5T_cdata_t **pcdata) { - H5T_t *dt = NULL; - herr_t ret_value=SUCCEED; /* Return value */ + H5T_conv_t ret_value; + H5T_t *src = NULL, *dst = NULL; + H5T_path_t *path = NULL; - FUNC_ENTER_API(H5Tget_pad, FAIL); - H5TRACE3("e","ixx",type_id,lsb,msb); + FUNC_ENTER_API(H5Tfind, NULL); + H5TRACE3("x","iix",src_id,dst_id,pcdata); /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (dt->parent) - dt = dt->parent; /*defer to parent*/ - if (H5T_COMPOUND==dt->type || H5T_OPAQUE==dt->type || H5T_ARRAY==dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for specified data type"); + if (NULL == (src = H5I_object_verify(src_id,H5I_DATATYPE)) || + NULL == (dst = H5I_object_verify(dst_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); + if (!pcdata) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, NULL, "no address to receive cdata pointer"); - /* Get values */ - assert(H5T_is_atomic(dt)); - if (lsb) - *lsb = dt->u.atomic.lsb_pad; - if (msb) - *msb = dt->u.atomic.msb_pad; + /* Find it */ + if (NULL==(path=H5T_path_find(src, dst, NULL, NULL, H5AC_ind_dxpl_id))) + HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "conversion function not found"); + + if (pcdata) + *pcdata = &(path->cdata); + /* Set return value */ + ret_value = path->func; + done: FUNC_LEAVE_API(ret_value); } /*------------------------------------------------------------------------- - * Function: H5Tset_pad + * Function: H5Tconvert * - * Purpose: Sets the LSB and MSB pad types. + * Purpose: Convert NELMTS elements from type SRC_ID to type DST_ID. The + * source elements are packed in BUF and on return the + * destination will be packed in BUF. That is, the conversion + * is performed in place. The optional background buffer is an + * array of NELMTS values of destination type which are merged + * with the converted values to fill in cracks (for instance, + * BACKGROUND might be an array of structs with the `a' and `b' + * fields already initialized and the conversion of BUF supplies + * the `c' and `d' field values). The PLIST_ID a dataset transfer + * property list which is passed to the conversion functions. (It's + * currently only used to pass along the VL datatype custom allocation + * information -QAK 7/1/99) * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke - * Friday, January 9, 1998 + * Wednesday, June 10, 1998 * * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works with derived data types. - * + * Added xfer_parms argument to pass VL datatype custom allocation + * information down the chain. - QAK, 7/1/99 + * *------------------------------------------------------------------------- */ herr_t -H5Tset_pad(hid_t type_id, H5T_pad_t lsb, H5T_pad_t msb) +H5Tconvert(hid_t src_id, hid_t dst_id, hsize_t nelmts, void *buf, + void *background, hid_t dxpl_id) { - H5T_t *dt = NULL; + H5T_path_t *tpath=NULL; /*type conversion info */ + H5T_t *src=NULL, *dst=NULL; /*unatomized types */ herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Tset_pad, FAIL); - H5TRACE3("e","iTpTp",type_id,lsb,msb); + + FUNC_ENTER_API(H5Tconvert, FAIL); + H5TRACE6("e","iihxxi",src_id,dst_id,nelmts,buf,background,dxpl_id); /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + if (NULL==(src=H5I_object_verify(src_id,H5I_DATATYPE)) || + NULL==(dst=H5I_object_verify(dst_id,H5I_DATATYPE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (H5T_STATE_TRANSIENT!=dt->state) - HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); - if (lsb < 0 || lsb >= H5T_NPAD || msb < 0 || msb >= H5T_NPAD) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pad type"); - if (H5T_ENUM==dt->type && dt->u.enumer.nmembs>0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined"); - if (dt->parent) - dt = dt->parent; /*defer to parent*/ - if (H5T_COMPOUND==dt->type || H5T_OPAQUE==dt->type || H5T_ARRAY==dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for specified data type"); + if(H5P_DEFAULT == dxpl_id) + dxpl_id = H5P_DATASET_XFER_DEFAULT; + else + if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not dataset transfer property list"); - /* Commit */ - assert(H5T_is_atomic(dt)); - dt->u.atomic.lsb_pad = lsb; - dt->u.atomic.msb_pad = msb; + /* Find the conversion function */ + if (NULL==(tpath=H5T_path_find(src, dst, NULL, NULL, dxpl_id))) + HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between src and dst data types"); + + if (H5T_convert(tpath, src_id, dst_id, nelmts, 0, 0, buf, background, dxpl_id)<0) + HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed"); done: FUNC_LEAVE_API(ret_value); @@ -3852,36 +3211,37 @@ done: /*------------------------------------------------------------------------- - * Function: H5Tget_sign + * Function: H5Tget_overflow * - * Purpose: Retrieves the sign type for an integer type. + * Purpose: Returns a pointer to the current global overflow function. + * This is an application-defined function that is called + * whenever a data type conversion causes an overflow. * - * Return: Success: The sign type. + * Return: Success: Ptr to an application-defined function. * - * Failure: H5T_SGN_ERROR (Negative) + * Failure: NULL (this can happen if no overflow handling + * function is registered). * * Programmer: Robb Matzke - * Wednesday, January 7, 1998 + * Tuesday, July 7, 1998 * * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works with derived data types. + * *------------------------------------------------------------------------- */ -H5T_sign_t -H5Tget_sign(hid_t type_id) +H5T_overflow_t +H5Tget_overflow(void) { - H5T_t *dt = NULL; - H5T_sign_t ret_value; + H5T_overflow_t ret_value; /* Return value */ - FUNC_ENTER_API(H5Tget_sign, H5T_SGN_ERROR); - H5TRACE1("Ts","i",type_id); + FUNC_ENTER_API(H5Tget_overflow, NULL); + H5TRACE0("x",""); - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_SGN_ERROR, "not an integer data type"); - - ret_value = H5T_get_sign(dt); + if (NULL==H5T_overflow_g) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNINITIALIZED, NULL, "no overflow handling function is registered"); + + /* Set return value */ + ret_value=H5T_overflow_g; done: FUNC_LEAVE_API(ret_value); @@ -3889,3993 +3249,870 @@ done: /*------------------------------------------------------------------------- - * Function: H5T_get_sign - * - * Purpose: Private function for H5Tget_sign. Retrieves the sign type - * for an integer type. + * Function: H5Tset_overflow * - * Return: Success: The sign type. + * Purpose: Sets the overflow handler to be the specified function. FUNC + * will be called for all data type conversions that result in + * an overflow. See the definition of `H5T_overflow_t' for + * documentation of arguments and return values. The NULL + * pointer may be passed to remove the overflow handler. * - * Failure: H5T_SGN_ERROR (Negative) + * Return: Non-negative on success/Negative on failure * - * Programmer: Raymond Lu - * October 8, 2002 + * Programmer: Robb Matzke + * Tuesday, July 7, 1998 * * Modifications: * *------------------------------------------------------------------------- */ -H5T_sign_t -H5T_get_sign(H5T_t *dt) +herr_t +H5Tset_overflow(H5T_overflow_t func) { - H5T_sign_t ret_value; - - FUNC_ENTER_NOAPI(H5T_get_sign, H5T_SGN_ERROR); - - assert(dt); + herr_t ret_value=SUCCEED; /* Return value */ - /* Defer to parent */ - while(dt->parent) - dt = dt->parent; + FUNC_ENTER_API(H5Tset_overflow, FAIL); + H5TRACE1("e","x",func); - /* Check args */ - if (H5T_INTEGER!=dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5T_SGN_ERROR, "operation not defined for data type class"); - - /* Sign */ - ret_value = dt->u.atomic.u.i.sign; + H5T_overflow_g = func; done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_API(ret_value); } +/*------------------------------------------------------------------------- + * API functions are above; library-private functions are below... + *------------------------------------------------------------------------- + */ + /*------------------------------------------------------------------------- - * Function: H5Tset_sign + * Function: H5T_create * - * Purpose: Sets the sign property for an integer. + * Purpose: Creates a new data type and initializes it to reasonable + * values. The new data type is SIZE bytes and an instance of + * the class TYPE. * - * Return: Non-negative on success/Negative on failure + * Return: Success: Pointer to the new type. + * + * Failure: NULL * * Programmer: Robb Matzke - * Wednesday, January 7, 1998 + * Friday, December 5, 1997 * * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works with derived data types. * *------------------------------------------------------------------------- */ -herr_t -H5Tset_sign(hid_t type_id, H5T_sign_t sign) +H5T_t * +H5T_create(H5T_class_t type, size_t size) { H5T_t *dt = NULL; - herr_t ret_value=SUCCEED; /* Return value */ + hid_t subtype; + H5T_t *ret_value; - FUNC_ENTER_API(H5Tset_sign, FAIL); - H5TRACE2("e","iTs",type_id,sign); + FUNC_ENTER_NOAPI(H5T_create, NULL); - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an integer data type"); - if (H5T_STATE_TRANSIENT!=dt->state) - HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); - if (sign < 0 || sign >= H5T_NSGN) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "illegal sign type"); - if (H5T_ENUM==dt->type && dt->u.enumer.nmembs>0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined"); - if (dt->parent) - dt = dt->parent; /*defer to parent*/ - if (H5T_INTEGER!=dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); - - /* Commit */ - dt->u.atomic.u.i.sign = sign; + assert(size > 0); -done: - FUNC_LEAVE_API(ret_value); -} + switch (type) { + case H5T_INTEGER: + case H5T_FLOAT: + case H5T_TIME: + case H5T_STRING: + case H5T_BITFIELD: + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, NULL, "type class is not appropriate - use H5Tcopy()"); - -/*------------------------------------------------------------------------- - * Function: H5Tget_fields - * - * Purpose: Returns information about the locations of the various bit - * fields of a floating point data type. The field positions - * are bit positions in the significant region of the data type. - * Bits are numbered with the least significant bit number zero. - * - * Any (or even all) of the arguments can be null pointers. - * - * Return: Success: Non-negative, field locations and sizes are - * returned through the arguments. - * - * Failure: Negative - * - * Programmer: Robb Matzke - * Wednesday, January 7, 1998 - * - * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works with derived data types. - *------------------------------------------------------------------------- - */ -herr_t -H5Tget_fields(hid_t type_id, size_t *spos/*out*/, - size_t *epos/*out*/, size_t *esize/*out*/, - size_t *mpos/*out*/, size_t *msize/*out*/) -{ - H5T_t *dt = NULL; - herr_t ret_value=SUCCEED; /* Return value */ + case H5T_OPAQUE: + case H5T_COMPOUND: + if (NULL==(dt = H5FL_CALLOC(H5T_t))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + dt->type = type; + break; - FUNC_ENTER_API(H5Tget_fields, FAIL); - H5TRACE6("e","ixxxxx",type_id,spos,epos,esize,mpos,msize); + case H5T_ENUM: + if (sizeof(char)==size) { + subtype = H5T_NATIVE_SCHAR_g; + } else if (sizeof(short)==size) { + subtype = H5T_NATIVE_SHORT_g; + } else if (sizeof(int)==size) { + subtype = H5T_NATIVE_INT_g; + } else if (sizeof(long)==size) { + subtype = H5T_NATIVE_LONG_g; + } else if (sizeof(long_long)==size) { + subtype = H5T_NATIVE_LLONG_g; + } else { + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "no applicable native integer type"); + } + if (NULL==(dt = H5FL_CALLOC(H5T_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + dt->type = type; + if (NULL==(dt->parent=H5T_copy(H5I_object(subtype), H5T_COPY_ALL))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy base data type"); + break; - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (dt->parent) - dt = dt->parent; /*defer to parent*/ - if (H5T_FLOAT != dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); - - /* Get values */ - if (spos) *spos = dt->u.atomic.u.f.sign; - if (epos) *epos = dt->u.atomic.u.f.epos; - if (esize) *esize = dt->u.atomic.u.f.esize; - if (mpos) *mpos = dt->u.atomic.u.f.mpos; - if (msize) *msize = dt->u.atomic.u.f.msize; + case H5T_VLEN: /* Variable length datatype */ + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, NULL, "base type required - use H5Tvlen_create()"); -done: - FUNC_LEAVE_API(ret_value); -} + case H5T_ARRAY: /* Array datatype */ + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, NULL, "base type required - use H5Tarray_create()"); - -/*------------------------------------------------------------------------- - * Function: H5Tset_fields - * - * Purpose: Sets the locations and sizes of the various floating point - * bit fields. The field positions are bit positions in the - * significant region of the data type. Bits are numbered with - * the least significant bit number zero. - * - * Fields are not allowed to extend beyond the number of bits of - * precision, nor are they allowed to overlap with one another. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Wednesday, January 7, 1998 - * - * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works for derived data types. - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tset_fields(hid_t type_id, size_t spos, size_t epos, size_t esize, - size_t mpos, size_t msize) -{ - H5T_t *dt = NULL; - herr_t ret_value=SUCCEED; /* Return value */ + default: + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, NULL, "unknown data type class"); + } - FUNC_ENTER_API(H5Tset_fields, FAIL); - H5TRACE6("e","izzzzz",type_id,spos,epos,esize,mpos,msize); + dt->ent.header = HADDR_UNDEF; + dt->size = size; - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (H5T_STATE_TRANSIENT!=dt->state) - HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); - if (dt->parent) - dt = dt->parent; /*defer to parent*/ - if (H5T_FLOAT != dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); - if (epos + esize > dt->u.atomic.prec) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "exponent bit field size/location is invalid"); - if (mpos + msize > dt->u.atomic.prec) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mantissa bit field size/location is invalid"); - if (spos >= dt->u.atomic.prec) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sign location is not valid"); - - /* Check for overlap */ - if (spos >= epos && spos < epos + esize) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sign bit appears within exponent field"); - if (spos >= mpos && spos < mpos + msize) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sign bit appears within mantissa field"); - if ((mpos < epos && mpos + msize > epos) || - (epos < mpos && epos + esize > mpos)) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "exponent and mantissa fields overlap"); - - /* Commit */ - dt->u.atomic.u.f.sign = spos; - dt->u.atomic.u.f.epos = epos; - dt->u.atomic.u.f.mpos = mpos; - dt->u.atomic.u.f.esize = esize; - dt->u.atomic.u.f.msize = msize; + /* Set return value */ + ret_value=dt; done: - FUNC_LEAVE_API(ret_value); + if(ret_value==NULL) { + if(dt!=NULL) + H5FL_FREE(H5T_t,dt); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value); } /*------------------------------------------------------------------------- - * Function: H5Tget_ebias + * Function: H5T_isa * - * Purpose: Retrieves the exponent bias of a floating-point type. + * Purpose: Determines if an object has the requisite messages for being + * a data type. * - * Return: Success: The bias + * Return: Success: TRUE if the required data type messages are + * present; FALSE otherwise. * - * Failure: 0 + * Failure: FAIL if the existence of certain messages + * cannot be determined. * * Programmer: Robb Matzke - * Wednesday, January 7, 1998 + * Monday, November 2, 1998 * * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works with derived data types. + * *------------------------------------------------------------------------- */ -size_t -H5Tget_ebias(hid_t type_id) +htri_t +H5T_isa(H5G_entry_t *ent, hid_t dxpl_id) { - H5T_t *dt = NULL; - size_t ret_value; - - FUNC_ENTER_API(H5Tget_ebias, 0); - H5TRACE1("z","i",type_id); - - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a data type"); - if (dt->parent) - dt = dt->parent; /*defer to parent*/ - if (H5T_FLOAT != dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, 0, "operation not defined for data type class"); + htri_t ret_value; - /* bias */ - H5_ASSIGN_OVERFLOW(ret_value,dt->u.atomic.u.f.ebias,uint64_t,size_t); + FUNC_ENTER_NOAPI(H5T_isa, FAIL); + assert(ent); + + if ((ret_value=H5O_exists(ent, H5O_DTYPE, 0, dxpl_id))<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to read object header"); done: - FUNC_LEAVE_API(ret_value); + FUNC_LEAVE_NOAPI(ret_value); } /*------------------------------------------------------------------------- - * Function: H5Tset_ebias + * Function: H5T_open * - * Purpose: Sets the exponent bias of a floating-point type. + * Purpose: Open a named data type. * - * Return: Non-negative on success/Negative on failure + * Return: Success: Ptr to a new data type. + * + * Failure: NULL * * Programmer: Robb Matzke - * Wednesday, January 7, 1998 + * Monday, June 1, 1998 * * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works with derived data types. + * Changed to use H5T_open_oid - QAK - 3/17/99 * *------------------------------------------------------------------------- */ -herr_t -H5Tset_ebias(hid_t type_id, size_t ebias) +static H5T_t * +H5T_open (H5G_entry_t *loc, const char *name, hid_t dxpl_id) { - H5T_t *dt = NULL; - herr_t ret_value=SUCCEED; /* Return value */ + H5T_t *dt; + H5G_entry_t ent; + H5T_t *ret_value; + + FUNC_ENTER_NOAPI(H5T_open, NULL); - FUNC_ENTER_API(H5Tset_ebias, FAIL); - H5TRACE2("e","iz",type_id,ebias); + assert (loc); + assert (name && *name); - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (H5T_STATE_TRANSIENT!=dt->state) - HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); - if (dt->parent) - dt = dt->parent; /*defer to parent*/ - if (H5T_FLOAT != dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); + /* + * Find the named data type object header and read the data type message + * from it. + */ + if (H5G_find (loc, name, NULL, &ent/*out*/, dxpl_id)<0) + HGOTO_ERROR (H5E_DATATYPE, H5E_NOTFOUND, NULL, "not found"); + + /* Open the datatype object */ + if ((dt=H5T_open_oid(&ent, dxpl_id)) ==NULL) + HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "not found"); - /* Commit */ - dt->u.atomic.u.f.ebias = ebias; + /* Set return value */ + ret_value=dt; done: - FUNC_LEAVE_API(ret_value); + FUNC_LEAVE_NOAPI(ret_value); } /*------------------------------------------------------------------------- - * Function: H5Tget_norm + * Function: H5T_open_oid * - * Purpose: Returns the mantisssa normalization of a floating-point data - * type. + * Purpose: Open a named data type. * - * Return: Success: Normalization ID + * Return: Success: Ptr to a new data type. * - * Failure: H5T_NORM_ERROR (Negative) + * Failure: NULL * - * Programmer: Robb Matzke - * Wednesday, January 7, 1998 + * Programmer: Quincey Koziol + * Wednesday, March 17, 1999 * * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works with derived data types. * *------------------------------------------------------------------------- */ -H5T_norm_t -H5Tget_norm(hid_t type_id) +H5T_t * +H5T_open_oid (H5G_entry_t *ent, hid_t dxpl_id) { - H5T_t *dt = NULL; - H5T_norm_t ret_value; + H5T_t *dt=NULL; + H5T_t *ret_value; + + FUNC_ENTER_NOAPI(H5T_open_oid, NULL); + + assert (ent); - FUNC_ENTER_API(H5Tget_norm, H5T_NORM_ERROR); - H5TRACE1("Tn","i",type_id); + if (H5O_open (ent)<0) + HGOTO_ERROR (H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open named data type"); + if (NULL==(dt=H5O_read (ent, H5O_DTYPE, 0, NULL, dxpl_id))) + HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to load type message from object header"); - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NORM_ERROR, "not a data type"); - if (dt->parent) - dt = dt->parent; /*defer to parent*/ - if (H5T_FLOAT != dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5T_NORM_ERROR, "operation not defined for data type class"); - - /* norm */ - ret_value = dt->u.atomic.u.f.norm; + /* Mark the type as named and open */ + dt->state = H5T_STATE_OPEN; + /* Shallow copy (take ownership) of the group entry object */ + H5G_ent_copy(&(dt->ent),ent,H5G_COPY_SHALLOW); + + /* Set return value */ + ret_value=dt; done: - FUNC_LEAVE_API(ret_value); + if(ret_value==NULL) { + if(dt==NULL) + H5O_close(ent); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value); } /*------------------------------------------------------------------------- - * Function: H5Tset_norm + * Function: H5T_copy + * + * Purpose: Copies datatype OLD_DT. The resulting data type is not + * locked and is a transient type. * - * Purpose: Sets the mantissa normalization method for a floating point - * data type. + * Return: Success: Pointer to a new copy of the OLD_DT argument. * - * Return: Non-negative on success/Negative on failure + * Failure: NULL * * Programmer: Robb Matzke - * Wednesday, January 7, 1998 + * Thursday, December 4, 1997 * * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works for derived data types. * - *------------------------------------------------------------------------- - */ -herr_t -H5Tset_norm(hid_t type_id, H5T_norm_t norm) -{ - H5T_t *dt = NULL; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Tset_norm, FAIL); - H5TRACE2("e","iTn",type_id,norm); - - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (H5T_STATE_TRANSIENT!=dt->state) - HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); - if (norm < 0 || norm > H5T_NORM_NONE) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "illegal normalization"); - if (dt->parent) - dt = dt->parent; /*defer to parent*/ - if (H5T_FLOAT != dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); - - /* Commit */ - dt->u.atomic.u.f.norm = norm; - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tget_inpad - * - * Purpose: If any internal bits of a floating point type are unused - * (that is, those significant bits which are not part of the - * sign, exponent, or mantissa) then they will be filled - * according to the value of this property. - * - * Return: Success: The internal padding type. + * Robb Matzke, 4 Jun 1998 + * Added the METHOD argument. If it's H5T_COPY_TRANSIENT then the + * result will be an unlocked transient type. Otherwise if it's + * H5T_COPY_ALL then the result is a named type if the original is a + * named type, but the result is not opened. Finally, if it's + * H5T_COPY_REOPEN and the original type is a named type then the result + * is a named type and the type object header is opened again. The + * H5T_COPY_REOPEN method is used when returning a named type to the + * application. * - * Failure: H5T_PAD_ERROR (Negative) + * Robb Matzke, 22 Dec 1998 + * Now able to copy enumeration data types. * - * Programmer: Robb Matzke - * Friday, January 9, 1998 + * Robb Matzke, 20 May 1999 + * Now able to copy opaque types. * - * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works for derived data types. + * Pedro Vicente, 21 Sep 2002 + * Added a deep copy of the symbol table entry * *------------------------------------------------------------------------- */ -H5T_pad_t -H5Tget_inpad(hid_t type_id) +H5T_t * +H5T_copy(const H5T_t *old_dt, H5T_copy_t method) { - H5T_t *dt = NULL; - H5T_pad_t ret_value; + H5T_t *new_dt=NULL, *tmp=NULL; + int i; + char *s; + H5T_t *ret_value; - FUNC_ENTER_API(H5Tget_inpad, H5T_PAD_ERROR); - H5TRACE1("Tp","i",type_id); + FUNC_ENTER_NOAPI(H5T_copy, NULL); - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_PAD_ERROR, "not a data type"); - if (dt->parent) - dt = dt->parent; /*defer to parent*/ - if (H5T_FLOAT != dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5T_PAD_ERROR, "operation not defined for data type class"); - - /* pad */ - ret_value = dt->u.atomic.u.f.pad; + /* check args */ + assert(old_dt); -done: - FUNC_LEAVE_API(ret_value); -} + /* Allocate space */ + if (NULL==(new_dt = H5FL_MALLOC(H5T_t))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - -/*------------------------------------------------------------------------- - * Function: H5Tset_inpad - * - * Purpose: If any internal bits of a floating point type are unused - * (that is, those significant bits which are not part of the - * sign, exponent, or mantissa) then they will be filled - * according to the value of this property. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Friday, January 9, 1998 - * - * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works for derived data types. - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tset_inpad(hid_t type_id, H5T_pad_t pad) -{ - H5T_t *dt = NULL; - herr_t ret_value=SUCCEED; /* Return value */ + /* Copy actual information */ + *new_dt = *old_dt; + + /* Copy parent information */ + if (new_dt->parent) + new_dt->parent = H5T_copy(new_dt->parent, method); - FUNC_ENTER_API(H5Tset_inpad, FAIL); - H5TRACE2("e","iTp",type_id,pad); + /* Check what sort of copy we are making */ + switch (method) { + case H5T_COPY_TRANSIENT: + /* + * Return an unlocked transient type. + */ + new_dt->state = H5T_STATE_TRANSIENT; + HDmemset (&(new_dt->ent), 0, sizeof(new_dt->ent)); + new_dt->ent.header = HADDR_UNDEF; + break; + + case H5T_COPY_ALL: + /* + * Return a transient type (locked or unlocked) or an unopened named + * type. Immutable transient types are degraded to read-only. + */ + if (H5T_STATE_OPEN==new_dt->state) { + new_dt->state = H5T_STATE_NAMED; + } else if (H5T_STATE_IMMUTABLE==new_dt->state) { + new_dt->state = H5T_STATE_RDONLY; + } + break; - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (H5T_STATE_TRANSIENT!=dt->state) - HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); - if (pad < 0 || pad >= H5T_NPAD) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "illegal internal pad type"); - if (dt->parent) - dt = dt->parent; /*defer to parent*/ - if (H5T_FLOAT != dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); + case H5T_COPY_REOPEN: + /* + * Return a transient type (locked or unlocked) or an opened named + * type. + */ + if (H5F_addr_defined(new_dt->ent.header)) { + if (H5O_open (&(new_dt->ent))<0) + HGOTO_ERROR (H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reopen named data type"); + new_dt->state = H5T_STATE_OPEN; + } + break; + } /* end switch */ - /* Commit */ - dt->u.atomic.u.f.pad = pad; - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tget_cset - * - * Purpose: HDF5 is able to distinguish between character sets of - * different nationalities and to convert between them to the - * extent possible. - * - * Return: Success: The character set of an H5T_STRING type. - * - * Failure: H5T_CSET_ERROR (Negative) - * - * Programmer: Robb Matzke - * Friday, January 9, 1998 - * - * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works for derived data types. - * - *------------------------------------------------------------------------- - */ -H5T_cset_t -H5Tget_cset(hid_t type_id) -{ - H5T_t *dt = NULL; - H5T_cset_t ret_value; + switch(new_dt->type) { + case H5T_COMPOUND: + { + int accum_change=0; /* Amount of change in the offset of the fields */ - FUNC_ENTER_API(H5Tget_cset, H5T_CSET_ERROR); - H5TRACE1("Tc","i",type_id); + /* + * Copy all member fields to new type, then overwrite the + * name and type fields of each new member with copied values. + * That is, H5T_copy() is a deep copy. + */ + new_dt->u.compnd.memb = H5MM_malloc(new_dt->u.compnd.nalloc * + sizeof(H5T_cmemb_t)); + if (NULL==new_dt->u.compnd.memb) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_CSET_ERROR, "not a data type"); - /* Don't see any reason for this. Causes problem for variable-length - * string. -SLU (& QAK) */ - /*if (dt->parent) dt = dt->parent;*/ /*defer to parent*/ - if (!(H5T_STRING == dt->type || (H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type))) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5T_CSET_ERROR, "operation not defined for data type class"); - - /* result */ - if(H5T_STRING == dt->type) - ret_value = dt->u.atomic.u.s.cset; - else if(H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type) - ret_value = dt->u.vlen.cset; - else - HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, H5T_CSET_ERROR, "can't get cset info"); + HDmemcpy(new_dt->u.compnd.memb, old_dt->u.compnd.memb, + new_dt->u.compnd.nmembs * sizeof(H5T_cmemb_t)); -done: - FUNC_LEAVE_API(ret_value); -} + for (i=0; iu.compnd.nmembs; i++) { + int j; + int old_match; - -/*------------------------------------------------------------------------- - * Function: H5Tset_cset - * - * Purpose: HDF5 is able to distinguish between character sets of - * different nationalities and to convert between them to the - * extent possible. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Friday, January 9, 1998 - * - * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works with derived data types. - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tset_cset(hid_t type_id, H5T_cset_t cset) -{ - H5T_t *dt = NULL; - herr_t ret_value=SUCCEED; /* Return value */ + s = new_dt->u.compnd.memb[i].name; + new_dt->u.compnd.memb[i].name = H5MM_xstrdup(s); + tmp = H5T_copy (old_dt->u.compnd.memb[i].type, method); + new_dt->u.compnd.memb[i].type = tmp; - FUNC_ENTER_API(H5Tset_cset, FAIL); - H5TRACE2("e","iTc",type_id,cset); + /* Apply the accumulated size change to the offset of the field */ + new_dt->u.compnd.memb[i].offset += accum_change; - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (H5T_STATE_TRANSIENT!=dt->state) - HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); - if (cset < 0 || cset >= H5T_NCSET) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "illegal character set type"); - /* Don't see any reason for this. Causes problem for variable-length - * string. -SLU (& QAK) */ - /*if (dt->parent) dt = dt->parent;*/ /*defer to parent*/ - if (!(H5T_STRING == dt->type || (H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type))) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); - - /* Commit */ - if(H5T_STRING == dt->type) - dt->u.atomic.u.s.cset = cset; - else if(H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type) - dt->u.vlen.cset = cset; - else - HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "can't set cset info"); + if(old_dt->u.compnd.sorted != H5T_SORT_VALUE) { + for (old_match=-1, j=0; ju.compnd.nmembs; j++) { + if(!HDstrcmp(new_dt->u.compnd.memb[i].name,old_dt->u.compnd.memb[j].name)) { + old_match=j; + break; + } /* end if */ + } /* end for */ -done: - FUNC_LEAVE_API(ret_value); -} + /* check if we couldn't find a match */ + if(old_match<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "fields in datatype corrupted"); + } /* end if */ + else { + old_match=i; + } /* end else */ - -/*------------------------------------------------------------------------- - * Function: H5Tget_strpad - * - * Purpose: The method used to store character strings differs with the - * programming language: C usually null terminates strings while - * Fortran left-justifies and space-pads strings. This property - * defines the storage mechanism for the string. - * - * Return: Success: The character set of an H5T_STRING type. - * - * Failure: H5T_STR_ERROR (Negative) - * - * Programmer: Robb Matzke - * Friday, January 9, 1998 - * - * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works for derived data types. - * - *------------------------------------------------------------------------- - */ -H5T_str_t -H5Tget_strpad(hid_t type_id) -{ - H5T_t *dt = NULL; - H5T_str_t ret_value; + /* If the field changed size, add that change to the accumulated size change */ + if(new_dt->u.compnd.memb[i].type->size != old_dt->u.compnd.memb[old_match].type->size) { + /* Adjust the size of the member */ + new_dt->u.compnd.memb[i].size = (old_dt->u.compnd.memb[old_match].size*tmp->size)/old_dt->u.compnd.memb[old_match].type->size; - FUNC_ENTER_API(H5Tget_strpad, H5T_STR_ERROR); - H5TRACE1("Tz","i",type_id); + accum_change += (new_dt->u.compnd.memb[i].type->size - old_dt->u.compnd.memb[old_match].type->size); + } /* end if */ + } /* end for */ - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_STR_ERROR, "not a data type"); - /* Don't see any reason for this. Causes problem for variable-length - * string. -SLU (& QAK) */ - /* if (dt->parent) dt = dt->parent;*/ /*defer to parent*/ - if (!(H5T_STRING == dt->type || (H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type))) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5T_STR_ERROR, "operation not defined for data type class"); - - /* result */ - if(H5T_STRING == dt->type) - ret_value = dt->u.atomic.u.s.pad; - else if(H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type) - ret_value = dt->u.vlen.pad; - else - HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, H5T_STR_ERROR, "can't get strpad info"); + /* Apply the accumulated size change to the size of the compound struct */ + new_dt->size += accum_change; -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tset_strpad - * - * Purpose: The method used to store character strings differs with the - * programming language: C usually null terminates strings while - * Fortran left-justifies and space-pads strings. This property - * defines the storage mechanism for the string. - * - * When converting from a long string to a short string if the - * short string is H5T_STR_NULLPAD or H5T_STR_SPACEPAD then the - * string is simply truncated; otherwise if the short string is - * H5T_STR_NULLTERM it will be truncated and a null terminator - * is appended. - * - * When converting from a short string to a long string, the - * long string is padded on the end by appending nulls or - * spaces. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Friday, January 9, 1998 - * - * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works for derived data types. - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tset_strpad(hid_t type_id, H5T_str_t strpad) -{ - H5T_t *dt = NULL; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Tset_strpad, FAIL); - H5TRACE2("e","iTz",type_id,strpad); - - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (H5T_STATE_TRANSIENT!=dt->state) - HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); - if (strpad < 0 || strpad >= H5T_NSTR) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "illegal string pad type"); - /* Don't see any reason for this. Causes problem for variable-length - * string. -SLU (& QAK) */ - /* if (dt->parent) dt = dt->parent;*/ /*defer to parent*/ - if (!(H5T_STRING == dt->type || (H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type))) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); - - /* Commit */ - if(H5T_STRING == dt->type) - dt->u.atomic.u.s.pad = strpad; - else if(H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type) - dt->u.vlen.pad = strpad; - else - HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, H5T_STR_ERROR, "can't set strpad info"); - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tget_nmembers - * - * Purpose: Determines how many members TYPE_ID has. The type must be - * either a compound data type or an enumeration data type. - * - * Return: Success: Number of members defined in the data type. - * - * Failure: Negative - * - * Errors: - * - * Programmer: Robb Matzke - * Monday, December 8, 1997 - * - * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works with enumeration data types. - *------------------------------------------------------------------------- - */ -int -H5Tget_nmembers(hid_t type_id) -{ - H5T_t *dt = NULL; - int ret_value; - - FUNC_ENTER_API(H5Tget_num_members, FAIL); - H5TRACE1("Is","i",type_id); - - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - - 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); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_get_nmembers - * - * Purpose: Private function for H5Tget_nmembers. Determines how many - * members DTYPE has. The type must be either a compound data i - * type or an enumeration data type. - * - * Return: Success: Number of members defined in the data type. - * - * Failure: Negative - * - * Errors: - * - * Programmer: Raymond Lu - * October 8, 2002 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -int -H5T_get_nmembers(const H5T_t *dt) -{ - int ret_value; - - FUNC_ENTER_NOAPI(H5T_get_nmembers, FAIL); - - assert(dt); - - if (H5T_COMPOUND==dt->type) - ret_value = dt->u.compnd.nmembs; - else if (H5T_ENUM==dt->type) - ret_value = dt->u.enumer.nmembs; - else - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "operation not supported for type class"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tget_member_name - * - * Purpose: Returns the name of a member of a compound or enumeration - * data type. 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 data types. - *------------------------------------------------------------------------- - */ -char * -H5Tget_member_name(hid_t type_id, int membno) -{ - H5T_t *dt = NULL; - char *ret_value; - - FUNC_ENTER_API(H5Tget_member_name, NULL); - - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); - - if((ret_value = H5T_get_member_name(dt, membno))==NULL) - 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 data type. 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 *dt, int membno) -{ - char *ret_value; - - FUNC_ENTER_NOAPI(H5T_get_member_name, NULL); - - assert(dt); - - switch (dt->type) { - case H5T_COMPOUND: - if (membno<0 || membno>=dt->u.compnd.nmembs) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid member number"); - ret_value = H5MM_xstrdup(dt->u.compnd.memb[membno].name); - break; + } + break; case H5T_ENUM: - if (membno<0 || membno>=dt->u.enumer.nmembs) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid member number"); - ret_value = H5MM_xstrdup(dt->u.enumer.name[membno]); + /* + * Copy all member fields to new type, then overwrite the name fields + * of each new member with copied values. That is, H5T_copy() is a + * deep copy. + */ + new_dt->u.enumer.name = H5MM_malloc(new_dt->u.enumer.nalloc * + sizeof(char*)); + new_dt->u.enumer.value = H5MM_malloc(new_dt->u.enumer.nalloc * + new_dt->size); + if (NULL==new_dt->u.enumer.value) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + HDmemcpy(new_dt->u.enumer.value, old_dt->u.enumer.value, + new_dt->u.enumer.nmembs * new_dt->size); + for (i=0; iu.enumer.nmembs; i++) { + s = old_dt->u.enumer.name[i]; + new_dt->u.enumer.name[i] = H5MM_xstrdup(s); + } break; - - default: - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "operation not supported for type class"); - } - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tget_member_index - * - * Purpose: Returns the index of a member in a compound or enumeration - * data type 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; - int nmembs, i; - FUNC_ENTER_API(H5Tget_member_index, FAIL); - H5TRACE2("Is","is",type_id,name); - - /* Check arguments */ - assert(name); - if(NULL==(dt=H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - - /* Locate member by name */ - switch (dt->type) { - case H5T_COMPOUND: - nmembs = dt->u.compnd.nmembs; - for(i=0; iu.compnd.memb[i].name, name)) - HGOTO_DONE(i); - } - break; - case H5T_ENUM: - nmembs = dt->u.enumer.nmembs; - for(i=0; iu.enumer.name[i], name)) - HGOTO_DONE(i); + case H5T_VLEN: + if(method==H5T_COPY_TRANSIENT || method==H5T_COPY_REOPEN) { + /* H5T_copy converts any VL type into a memory VL type */ + if (H5T_vlen_mark(new_dt, NULL, H5T_VLEN_MEMORY)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid VL location"); } break; - default: - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "operation not supported for this type"); - } - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tget_member_offset - * - * Purpose: Returns the byte offset of the beginning of a member with - * respect to the beginning of the compound data type datum. - * - * Return: Success: Byte offset. - * - * Failure: Zero. Zero is a valid offset, but this - * function will fail only if a call to - * H5Tget_member_dims() fails with the same - * arguments. - * - * Programmer: Robb Matzke - * Wednesday, January 7, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -size_t -H5Tget_member_offset(hid_t type_id, int membno) -{ - H5T_t *dt = NULL; - size_t ret_value; - - FUNC_ENTER_API(H5Tget_member_offset, 0); - H5TRACE2("z","iIs",type_id,membno); - - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)) || H5T_COMPOUND != dt->type) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a compound data type"); - if (membno < 0 || membno >= dt->u.compnd.nmembs) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid member number"); - - /* Value */ - ret_value = H5T_get_member_offset(dt, membno); - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_get_member_offset - * - * Purpose: Private function for H5Tget_member_offset. Returns the byte - * offset of the beginning of a member with respect to the i - * beginning of the compound data type datum. - * - * Return: Success: Byte offset. - * - * Failure: Zero. Zero is a valid offset, but this - * function will fail only if a call to - * H5Tget_member_dims() fails with the same - * arguments. - * - * Programmer: Raymond Lu - * October 8, 2002 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -size_t -H5T_get_member_offset(H5T_t *dt, int membno) -{ - size_t ret_value; - - FUNC_ENTER_NOAPI(H5T_get_member_offset, 0); - - assert(dt); - assert(membno >= 0 && membno < dt->u.compnd.nmembs); - - /* Value */ - ret_value = dt->u.compnd.memb[membno].offset; -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tget_member_class - * - * Purpose: Returns the datatype class of a member of a compound datatype. - * - * Return: Success: Non-negative - * - * Failure: H5T_NO_CLASS - * - * Programmer: Quincey Koziol - * Thursday, November 9, 2000 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5T_class_t -H5Tget_member_class(hid_t type_id, int membno) -{ - H5T_t *dt = NULL; - H5T_class_t ret_value; - - FUNC_ENTER_API(H5Tget_member_class, H5T_NO_CLASS); - H5TRACE2("Tt","iIs",type_id,membno); - - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)) || H5T_COMPOUND != dt->type) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a compound data type"); - if (membno < 0 || membno >= dt->u.compnd.nmembs) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5T_NO_CLASS, "invalid member number"); + case H5T_OPAQUE: + /* + * Copy the tag name. + */ + new_dt->u.opaque.tag = HDstrdup(new_dt->u.opaque.tag); + break; - /* Value */ - ret_value = dt->u.compnd.memb[membno].type->type; + case H5T_ARRAY: + /* Re-compute the array's size, in case it's base type changed size */ + new_dt->size=new_dt->u.array.nelem*new_dt->parent->size; + break; -done: - FUNC_LEAVE_API(ret_value); -} /* end H5Tget_member_class() */ - - - -/*------------------------------------------------------------------------- - * Function: H5Tget_member_type - * - * Purpose: Returns the data type of the specified member. The caller - * should invoke H5Tclose() to release resources associated with - * the type. - * - * Return: Success: An OID of a copy of the member data type; - * modifying the returned data type does not - * modify the member type. - * - * Failure: Negative - * - * Programmer: Robb Matzke - * Wednesday, January 7, 1998 - * - * Modifications: - * - * Robb Matzke, 4 Jun 1998 - * If the member type is a named type then this function returns a - * handle to the re-opened named type. - * - *------------------------------------------------------------------------- - */ -hid_t -H5Tget_member_type(hid_t type_id, int membno) -{ - H5T_t *dt = NULL, *memb_dt = NULL; - hid_t ret_value; - - FUNC_ENTER_API(H5Tget_member_type, FAIL); - H5TRACE2("i","iIs",type_id,membno); - - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)) || H5T_COMPOUND != dt->type) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound data type"); - if (membno < 0 || membno >= dt->u.compnd.nmembs) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid member number"); - if ((memb_dt=H5T_get_member_type(dt, membno))==NULL) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to retrieve member type"); - if ((ret_value = H5I_register(H5I_DATATYPE, memb_dt)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable register data type atom"); - -done: - if(ret_value<0) { - if(memb_dt!=NULL) - H5T_close(memb_dt); - } /* end if */ - - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_get_member_type - * - * Purpose: Private function for H5Tget_member_type. Returns the data - * type of the specified member. - * - * Return: Success: A copy of the member data type; - * modifying the returned data type does not - * modify the member type. - * - * Failure: NULL - * - * Programmer: Raymond Lu - * October 8, 2002 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5T_t * -H5T_get_member_type(H5T_t *dt, int membno) -{ - H5T_t *ret_value = NULL; - - FUNC_ENTER_NOAPI(H5T_get_member_type, NULL); - - assert(dt); - assert(membno >=0 && membno < dt->u.compnd.nmembs); - - /* Copy data type into an atom */ - if (NULL == (ret_value = H5T_copy(dt->u.compnd.memb[membno].type, H5T_COPY_REOPEN))) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy member data type"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - - -/*------------------------------------------------------------------------- - * Function: H5Tinsert - * - * 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. - * - * Return: Success: Non-negative, the PARENT_ID compound data - * type is modified to include a copy of the - * member type MEMBER_ID. - * - * Failure: Negative - * - * Errors: - * - * Programmer: Robb Matzke - * Monday, December 8, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tinsert(hid_t parent_id, const char *name, size_t offset, hid_t member_id) -{ - H5T_t *parent = NULL; /*the compound parent data type */ - H5T_t *member = NULL; /*the atomic member type */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Tinsert, FAIL); - H5TRACE4("e","iszi",parent_id,name,offset,member_id); - - /* Check args */ - if (parent_id==member_id) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "can't insert compound datatype within itself"); - if (NULL == (parent = H5I_object_verify(parent_id,H5I_DATATYPE)) || H5T_COMPOUND != parent->type) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound data type"); - if (H5T_STATE_TRANSIENT!=parent->state) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent type read-only"); - if (!name || !*name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no member name"); - if (NULL == (member = H5I_object_verify(member_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - - /* Insert */ - if (H5T_insert(parent, name, offset, member) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "unable to insert member"); - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tpack - * - * Purpose: Recursively removes padding from within a compound data type - * to make it more efficient (space-wise) to store that data. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Wednesday, January 7, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tpack(hid_t type_id) -{ - H5T_t *dt = NULL; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Tpack, FAIL); - H5TRACE1("e","i",type_id); - - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)) || H5T_COMPOUND != dt->type) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound data type"); - if (H5T_STATE_TRANSIENT!=dt->state) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "data type is read-only"); - - /* Pack */ - if (H5T_pack(dt) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack compound data type"); - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tenum_create - * - * Purpose: Create a new enumeration data type based on the specified - * TYPE, which must be an integer type. - * - * Return: Success: ID of new enumeration data type - * - * Failure: Negative - * - * Programmer: Robb Matzke - * Tuesday, December 22, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -hid_t -H5Tenum_create(hid_t parent_id) -{ - H5T_t *parent = NULL; /*base integer data type */ - H5T_t *dt = NULL; /*new enumeration data type */ - hid_t ret_value; /*return value */ - - FUNC_ENTER_API(H5Tenum_create, FAIL); - H5TRACE1("i","i",parent_id); - - /* Check args */ - if (NULL==(parent=H5I_object_verify(parent_id,H5I_DATATYPE)) || H5T_INTEGER!=parent->type) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an integer data type"); - - /* Build new type */ - if((dt=H5T_enum_create(parent))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "cannot create enum type"); - /* Atomize the type */ - if ((ret_value=H5I_register(H5I_DATATYPE, dt))<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data type atom"); - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_enum_create - * - * Purpose: Private function for H5Tenum_create. Create a new - * enumeration data type based on the specified - * TYPE, which must be an integer type. - * - * Return: Success: new enumeration data type - * - * Failure: NULL - * - * Programmer: Raymond Lu - * October 9, 2002 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5T_t * -H5T_enum_create(H5T_t *parent) -{ - H5T_t *ret_value; /*new enumeration data type */ - - FUNC_ENTER_NOAPI(H5T_enum_create, NULL); - - assert(parent); - - /* Build new type */ - if (NULL==(ret_value = H5FL_CALLOC(H5T_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - ret_value->type = H5T_ENUM; - ret_value->parent = H5T_copy(parent, H5T_COPY_ALL); - assert(ret_value->parent); - ret_value->size = ret_value->parent->size; - ret_value->ent.header = HADDR_UNDEF; - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - - -/*------------------------------------------------------------------------- - * Function: H5Tenum_insert - * - * Purpose: Insert a new enumeration data type member into an enumeration - * type. TYPE is the enumeration type, NAME is the name of the - * new member, and VALUE points to the value of the new member. - * The NAME and VALUE must both be unique within the TYPE. VALUE - * points to data which is of the data type defined when the - * enumeration type was created. - * - * Return: Success: non-negative - * - * Failure: negative - * - * Programmer: Robb Matzke - * Wednesday, December 23, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tenum_insert(hid_t type, const char *name, void *value) -{ - H5T_t *dt=NULL; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Tenum_insert, FAIL); - H5TRACE3("e","isx",type,name,value); - - /* Check args */ - if (NULL==(dt=H5I_object_verify(type,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (H5T_ENUM!=dt->type) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an enumeration data type"); - if (!name || !*name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified"); - if (!value) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no value specified"); - - /* Do work */ - if (H5T_enum_insert(dt, name, value)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to insert new enumeration member"); - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tget_super - * - * Purpose: Returns the type from which TYPE is derived. In the case of - * an enumeration type the return value is an integer type. - * - * Return: Success: Type ID for base data type. - * - * Failure: negative - * - * Programmer: Robb Matzke - * Wednesday, December 23, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -hid_t -H5Tget_super(hid_t type) -{ - H5T_t *dt=NULL, *super=NULL; - hid_t ret_value; - - FUNC_ENTER_API(H5Tget_super, FAIL); - H5TRACE1("i","i",type); - - if (NULL==(dt=H5I_object_verify(type,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if((super=H5T_get_super(dt))==NULL) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "not a data type"); - if ((ret_value=H5I_register(H5I_DATATYPE, super))<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register parent data type"); - -done: - if(ret_value<0) { - if(super!=NULL) - H5T_close(super); - } /* end if */ - - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_get_super - * - * Purpose: Private function for H5Tget_super. Returns the type from - * which TYPE is derived. In the case of an enumeration type - * the return value is an integer type. - * - * Return: Success: Data type for base data type. - * - * Failure: NULL - * - * Programmer: Raymond Lu - * October 9, 2002 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5T_t * -H5T_get_super(H5T_t *dt) -{ - H5T_t *ret_value=NULL; - - FUNC_ENTER_NOAPI(H5T_get_super, NULL); - - assert(dt); - - if (!dt->parent) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a derived data type"); - if (NULL==(ret_value=H5T_copy(dt->parent, H5T_COPY_ALL))) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy parent data type"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tget_member_value - * - * Purpose: Return the value for an enumeration data type member. - * - * Return: Success: non-negative with the member value copied - * into the memory pointed to by VALUE. - * - * Failure: negative, VALUE memory is undefined. - * - * Programmer: Robb Matzke - * Wednesday, December 23, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tget_member_value(hid_t type, int membno, void *value/*out*/) -{ - H5T_t *dt=NULL; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Tget_member_value, FAIL); - H5TRACE3("e","iIsx",type,membno,value); - - if (NULL==(dt=H5I_object_verify(type,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (H5T_ENUM!=dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); - if (membno<0 || membno>=dt->u.enumer.nmembs) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid member number"); - if (!value) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null value buffer"); - - if (H5T_get_member_value(dt, membno, value)<0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get member value"); -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_get_member_value - * - * Purpose: Private function for H5T_get_member_value. Return the - * value for an enumeration data type member. - * - * Return: Success: non-negative with the member value copied - * into the memory pointed to by VALUE. - * - * Failure: negative, VALUE memory is undefined. - * - * Programmer: Raymond Lu - * October 9, 2002 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5T_get_member_value(H5T_t *dt, int membno, void *value/*out*/) -{ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5T_get_member_value, FAIL); - - assert(dt); - assert(value); - - HDmemcpy(value, dt->u.enumer.value + membno*dt->size, dt->size); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - - -/*------------------------------------------------------------------------- - * Function: H5Tenum_nameof - * - * Purpose: Finds the symbol name that corresponds to the specified VALUE - * of an enumeration data type TYPE. At most SIZE characters of - * the symbol name are copied into the NAME buffer. If the - * entire symbol anem and null terminator do not fit in the NAME - * buffer then as many characters as possible are copied (not - * null terminated) and the function fails. - * - * Return: Success: Non-negative. - * - * Failure: Negative, first character of NAME is set to - * null if SIZE allows it. - * - * Programmer: Robb Matzke - * Monday, January 4, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tenum_nameof(hid_t type, void *value, char *name/*out*/, size_t size) -{ - H5T_t *dt = NULL; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Tenum_nameof, FAIL); - H5TRACE4("e","ixxz",type,value,name,size); - - /* Check args */ - if (NULL==(dt=H5I_object_verify(type,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (H5T_ENUM!=dt->type) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an enumeration data type"); - if (!value) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no value supplied"); - if (!name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name buffer supplied"); - - if (NULL==H5T_enum_nameof(dt, value, name, size)) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "nameof query failed"); - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tenum_valueof - * - * Purpose: Finds the value that corresponds to the specified NAME f an - * enumeration TYPE. The VALUE argument should be at least as - * large as the value of H5Tget_size(type) in order to hold the - * result. - * - * Return: Success: Non-negative - * - * Failure: Negative - * - * Programmer: Robb Matzke - * Monday, January 4, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tenum_valueof(hid_t type, const char *name, void *value/*out*/) -{ - H5T_t *dt = NULL; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Tenum_valueof, FAIL); - H5TRACE3("e","isx",type,name,value); - - /* Check args */ - if (NULL==(dt=H5I_object_verify(type,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (H5T_ENUM!=dt->type) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an enumeration data type"); - if (!name || !*name) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name"); - if (!value) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no value buffer"); - - if (H5T_enum_valueof(dt, name, value)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "valueof query failed"); - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_vlen_create - * - * Purpose: Create a new variable-length data type based on the specified - * BASE_TYPE. - * - * Return: Success: new VL data type - * - * Failure: NULL - * - * Programmer: Quincey Koziol - * Tuesday, November 20, 2001 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static H5T_t * -H5T_vlen_create(H5T_t *base) -{ - H5T_t *dt = NULL; /*new VL data type */ - H5T_t *ret_value; /*return value */ - - FUNC_ENTER_NOINIT(H5T_vlen_create); - - /* Check args */ - assert(base); - - /* Build new type */ - if (NULL==(dt = H5FL_CALLOC(H5T_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - dt->ent.header = HADDR_UNDEF; - dt->type = H5T_VLEN; - - /* - * Force conversions (i.e. memory to memory conversions should duplicate - * data, not point to the same VL sequences) - */ - dt->force_conv = TRUE; - dt->parent = H5T_copy(base, H5T_COPY_ALL); - - /* This is a sequence, not a string */ - dt->u.vlen.type = H5T_VLEN_SEQUENCE; - - /* Set up VL information */ - if (H5T_vlen_mark(dt, NULL, H5T_VLEN_MEMORY)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid VL location"); - - /* Set return value */ - ret_value=dt; - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tvlen_create - * - * Purpose: Create a new variable-length data type based on the specified - * BASE_TYPE. - * - * Return: Success: ID of new VL data type - * - * Failure: Negative - * - * Programmer: Quincey Koziol - * Thursday, May 20, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -hid_t -H5Tvlen_create(hid_t base_id) -{ - H5T_t *base = NULL; /*base data type */ - H5T_t *dt = NULL; /*new data type */ - hid_t ret_value; /*return value */ - - FUNC_ENTER_API(H5Tvlen_create, FAIL); - H5TRACE1("i","i",base_id); - - /* Check args */ - if (NULL==(base=H5I_object_verify(base_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype"); - - /* Create up VL datatype */ - if ((dt=H5T_vlen_create(base))==NULL) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid VL location"); - - /* Atomize the type */ - if ((ret_value=H5I_register(H5I_DATATYPE, dt))<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype"); - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tset_tag - * - * Purpose: Tag an opaque datatype with a unique ASCII identifier. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Thursday, May 20, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tset_tag(hid_t type_id, const char *tag) -{ - H5T_t *dt=NULL; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Tset_tag, FAIL); - H5TRACE2("e","is",type_id,tag); - - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (H5T_STATE_TRANSIENT!=dt->state) - HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); - if (H5T_OPAQUE!=dt->type) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an opaque data type"); - if (!tag) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no tag"); - - /* Commit */ - H5MM_xfree(dt->u.opaque.tag); - dt->u.opaque.tag = H5MM_strdup(tag); - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tget_tag - * - * Purpose: Get tha tag associated with an opaque datatype. - * - * Return: A pointer to an allocated string. The caller should free - * the string. NULL is returned for errors. - * - * Programmer: Robb Matzke - * Thursday, May 20, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -char * -H5Tget_tag(hid_t type_id) -{ - H5T_t *dt=NULL; - char *ret_value; - - FUNC_ENTER_API(H5Tget_tag, NULL); - - /* Check args */ - if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); - - if (dt->parent) - dt = dt->parent; /*defer to parent*/ - if (H5T_OPAQUE != dt->type) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "operation not defined for data type class"); - - /* result */ - if (NULL==(ret_value=H5MM_strdup(dt->u.opaque.tag))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_register - * - * Purpose: Register a hard or soft conversion function for a data type - * conversion path. The path is specified by the source and - * destination data types SRC_ID and DST_ID (for soft functions - * only the class of these types is important). If FUNC is a - * hard function then it replaces any previous path; if it's a - * soft function then it replaces all existing paths to which it - * applies and is used for any new path to which it applies as - * long as that path doesn't have a hard function. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Friday, January 9, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5T_register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, - H5T_conv_t func, hid_t dxpl_id) -{ - hid_t tmp_sid=-1, tmp_did=-1;/*temporary data type IDs */ - H5T_path_t *old_path=NULL; /*existing conversion path */ - H5T_path_t *new_path=NULL; /*new conversion path */ - H5T_cdata_t cdata; /*temporary conversion data */ - int nprint=0; /*number of paths shut down */ - int i; /*counter */ - herr_t ret_value=SUCCEED; /*return value */ - - FUNC_ENTER_NOINIT(H5T_register); - - /* Check args */ - assert(src); - assert(dst); - assert(func); - assert(H5T_PERS_HARD==pers || H5T_PERS_SOFT==pers); - assert(name && *name); - - if (H5T_PERS_HARD==pers) { - /* Locate or create a new conversion path */ - if (NULL==(new_path=H5T_path_find(src, dst, name, func, dxpl_id))) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to locate/allocate conversion path"); - - /* - * Notify all other functions to recalculate private data since some - * functions might cache a list of conversion functions. For - * instance, the compound type converter caches a list of conversion - * functions for the members, so adding a new function should cause - * the list to be recalculated to use the new function. - */ - for (i=0; icdata.recalc = TRUE; - } /* end for */ - - } else { - /* Add function to end of soft list */ - if (H5T_g.nsoft>=H5T_g.asoft) { - size_t na = MAX(32, 2*H5T_g.asoft); - H5T_soft_t *x = H5MM_realloc(H5T_g.soft, na*sizeof(H5T_soft_t)); - - if (!x) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - H5T_g.asoft = (int)na; - H5T_g.soft = x; - } /* end if */ - HDstrncpy (H5T_g.soft[H5T_g.nsoft].name, name, H5T_NAMELEN); - H5T_g.soft[H5T_g.nsoft].name[H5T_NAMELEN-1] = '\0'; - H5T_g.soft[H5T_g.nsoft].src = src->type; - H5T_g.soft[H5T_g.nsoft].dst = dst->type; - H5T_g.soft[H5T_g.nsoft].func = func; - H5T_g.nsoft++; - - /* - * Any existing path (except the no-op path) to which this new soft - * conversion function applies should be replaced by a new path that - * uses this function. - */ - for (i=1; iis_hard || - old_path->src->type!=src->type || - old_path->dst->type!=dst->type) { - continue; - } - if ((tmp_sid = H5I_register(H5I_DATATYPE, H5T_copy(old_path->src, H5T_COPY_ALL)))<0 || - (tmp_did = H5I_register(H5I_DATATYPE, H5T_copy(old_path->dst, H5T_COPY_ALL)))<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data types for conv query"); - HDmemset(&cdata, 0, sizeof cdata); - cdata.command = H5T_CONV_INIT; - if ((func)(tmp_sid, tmp_did, &cdata, (hsize_t)0, 0, 0, NULL, NULL, dxpl_id)<0) { - H5I_dec_ref(tmp_sid); - H5I_dec_ref(tmp_did); - tmp_sid = tmp_did = -1; - H5E_clear(); - continue; - } /* end if */ - - /* Create a new conversion path */ - if (NULL==(new_path=H5FL_CALLOC(H5T_path_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - HDstrncpy(new_path->name, name, H5T_NAMELEN); - new_path->name[H5T_NAMELEN-1] = '\0'; - if (NULL==(new_path->src=H5T_copy(old_path->src, H5T_COPY_ALL)) || - NULL==(new_path->dst=H5T_copy(old_path->dst, H5T_COPY_ALL))) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy data types"); - new_path->func = func; - new_path->is_hard = FALSE; - new_path->cdata = cdata; - - /* Replace previous path */ - H5T_g.path[i] = new_path; - new_path = NULL; /*so we don't free it on error*/ - - /* Free old path */ - H5T_print_stats(old_path, &nprint); - old_path->cdata.command = H5T_CONV_FREE; - if ((old_path->func)(tmp_sid, tmp_did, &(old_path->cdata), (hsize_t)0, 0, 0, NULL, NULL, dxpl_id)<0) { -#ifdef H5T_DEBUG - if (H5DEBUG(T)) { - fprintf (H5DEBUG(T), "H5T: conversion function 0x%08lx " - "failed to free private data for %s (ignored)\n", - (unsigned long)(old_path->func), old_path->name); - } -#endif - } /* end if */ - H5T_close(old_path->src); - H5T_close(old_path->dst); - H5FL_FREE(H5T_path_t,old_path); - - /* Release temporary atoms */ - H5I_dec_ref(tmp_sid); - H5I_dec_ref(tmp_did); - tmp_sid = tmp_did = -1; - - /* We don't care about any failures during the freeing process */ - H5E_clear(); - } /* end for */ - } /* end else */ - -done: - if (ret_value<0) { - if (new_path) { - if (new_path->src) - H5T_close(new_path->src); - if (new_path->dst) - H5T_close(new_path->dst); - H5FL_FREE(H5T_path_t,new_path); - } /* end if */ - if (tmp_sid>=0) - H5I_dec_ref(tmp_sid); - if (tmp_did>=0) - H5I_dec_ref(tmp_did); - } /* end if */ - - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5T_register() */ - - -/*------------------------------------------------------------------------- - * Function: H5Tregister - * - * Purpose: Register a hard or soft conversion function for a data type - * conversion path. The path is specified by the source and - * destination data types SRC_ID and DST_ID (for soft functions - * only the class of these types is important). If FUNC is a - * hard function then it replaces any previous path; if it's a - * soft function then it replaces all existing paths to which it - * applies and is used for any new path to which it applies as - * long as that path doesn't have a hard function. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Friday, January 9, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tregister(H5T_pers_t pers, const char *name, hid_t src_id, hid_t dst_id, - H5T_conv_t func) -{ - H5T_t *src; /*source data type descriptor */ - H5T_t *dst; /*destination data type desc */ - herr_t ret_value=SUCCEED; /*return value */ - - FUNC_ENTER_API(H5Tregister, FAIL); - H5TRACE5("e","Tesiix",pers,name,src_id,dst_id,func); - - /* Check args */ - if (H5T_PERS_HARD!=pers && H5T_PERS_SOFT!=pers) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid function persistence"); - if (!name || !*name) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "conversion must have a name for debugging"); - if (NULL==(src=H5I_object_verify(src_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (NULL==(dst=H5I_object_verify(dst_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (!func) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no conversion function specified"); - - /* Go register the function */ - if(H5T_register(pers,name,src,dst,func,H5AC_ind_dxpl_id)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "can't register conversion function"); - -done: - FUNC_LEAVE_API(ret_value); -} /* end H5Tregister() */ - - -/*------------------------------------------------------------------------- - * Function: H5T_unregister - * - * Purpose: Removes conversion paths that match the specified criteria. - * All arguments are optional. Missing arguments are wild cards. - * The special no-op path cannot be removed. - * - * Return: Succeess: non-negative - * - * Failure: negative - * - * Programmer: Robb Matzke - * Tuesday, January 13, 1998 - * - * Modifications: - * Adapted to non-API function - QAK, 11/17/99 - * - *------------------------------------------------------------------------- - */ -herr_t -H5T_unregister(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, - H5T_conv_t func, hid_t dxpl_id) -{ - H5T_path_t *path = NULL; /*conversion path */ - H5T_soft_t *soft = NULL; /*soft conversion information */ - int nprint=0; /*number of paths shut down */ - int i; /*counter */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5T_unregister, FAIL); - - /* Remove matching entries from the soft list */ - if (H5T_PERS_DONTCARE==pers || H5T_PERS_SOFT==pers) { - for (i=H5T_g.nsoft-1; i>=0; --i) { - soft = H5T_g.soft+i; - assert(soft); - if (name && *name && HDstrcmp(name, soft->name)) continue; - if (src && src->type!=soft->src) continue; - if (dst && dst->type!=soft->dst) continue; - if (func && func!=soft->func) continue; - - HDmemmove(H5T_g.soft+i, H5T_g.soft+i+1, - (H5T_g.nsoft-(i+1)) * sizeof(H5T_soft_t)); - --H5T_g.nsoft; - } - } - - /* Remove matching conversion paths, except no-op path */ - for (i=H5T_g.npaths-1; i>0; --i) { - path = H5T_g.path[i]; - assert(path); - if ((H5T_PERS_SOFT==pers && path->is_hard) || - (H5T_PERS_HARD==pers && !path->is_hard)) continue; - if (name && *name && HDstrcmp(name, path->name)) continue; - if (src && H5T_cmp(src, path->src)) continue; - if (dst && H5T_cmp(dst, path->dst)) continue; - if (func && func!=path->func) continue; - - /* Remove from table */ - HDmemmove(H5T_g.path+i, H5T_g.path+i+1, - (H5T_g.npaths-(i+1))*sizeof(H5T_path_t*)); - --H5T_g.npaths; - - /* Shut down path */ - H5T_print_stats(path, &nprint); - path->cdata.command = H5T_CONV_FREE; - if ((path->func)(FAIL, FAIL, &(path->cdata), (hsize_t)0, 0, 0, NULL, NULL, - dxpl_id)<0) { -#ifdef H5T_DEBUG - if (H5DEBUG(T)) { - fprintf(H5DEBUG(T), "H5T: conversion function 0x%08lx failed " - "to free private data for %s (ignored)\n", - (unsigned long)(path->func), path->name); - } -#endif - } - H5T_close(path->src); - H5T_close(path->dst); - H5FL_FREE(H5T_path_t,path); - H5E_clear(); /*ignore all shutdown errors*/ - } - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5T_unregister() */ - - -/*------------------------------------------------------------------------- - * Function: H5Tunregister - * - * Purpose: Removes conversion paths that match the specified criteria. - * All arguments are optional. Missing arguments are wild cards. - * The special no-op path cannot be removed. - * - * Return: Succeess: non-negative - * - * Failure: negative - * - * Programmer: Robb Matzke - * Tuesday, January 13, 1998 - * - * Modifications: - * Changed to use H5T_unregister wrapper function - QAK, 11/17/99 - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tunregister(H5T_pers_t pers, const char *name, hid_t src_id, hid_t dst_id, - H5T_conv_t func) -{ - H5T_t *src=NULL, *dst=NULL; /*data type descriptors */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Tunregister, FAIL); - H5TRACE5("e","Tesiix",pers,name,src_id,dst_id,func); - - /* Check arguments */ - if (src_id>0 && (NULL==(src=H5I_object_verify(src_id,H5I_DATATYPE)))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "src is not a data type"); - if (dst_id>0 && (NULL==(dst=H5I_object_verify(dst_id,H5I_DATATYPE)))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dst is not a data type"); - - if (H5T_unregister(pers,name,src,dst,func,H5AC_ind_dxpl_id)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDELETE, FAIL, "internal unregister function failed"); - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tfind - * - * Purpose: Finds a conversion function that can handle a conversion from - * type SRC_ID to type DST_ID. The PCDATA argument is a pointer - * to a pointer to type conversion data which was created and - * initialized by the type conversion function of this path - * when the conversion function was installed on the path. - * - * Return: Success: A pointer to a suitable conversion function. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Tuesday, January 13, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5T_conv_t -H5Tfind(hid_t src_id, hid_t dst_id, H5T_cdata_t **pcdata) -{ - H5T_conv_t ret_value; - H5T_t *src = NULL, *dst = NULL; - H5T_path_t *path = NULL; - - FUNC_ENTER_API(H5Tfind, NULL); - H5TRACE3("x","iix",src_id,dst_id,pcdata); - - /* Check args */ - if (NULL == (src = H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL == (dst = H5I_object_verify(dst_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); - if (!pcdata) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, NULL, "no address to receive cdata pointer"); - - /* Find it */ - if (NULL==(path=H5T_path_find(src, dst, NULL, NULL, H5AC_ind_dxpl_id))) - HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "conversion function not found"); - - if (pcdata) - *pcdata = &(path->cdata); - - /* Set return value */ - ret_value = path->func; - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tconvert - * - * Purpose: Convert NELMTS elements from type SRC_ID to type DST_ID. The - * source elements are packed in BUF and on return the - * destination will be packed in BUF. That is, the conversion - * is performed in place. The optional background buffer is an - * array of NELMTS values of destination type which are merged - * with the converted values to fill in cracks (for instance, - * BACKGROUND might be an array of structs with the `a' and `b' - * fields already initialized and the conversion of BUF supplies - * the `c' and `d' field values). The PLIST_ID a dataset transfer - * property list which is passed to the conversion functions. (It's - * currently only used to pass along the VL datatype custom allocation - * information -QAK 7/1/99) - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Wednesday, June 10, 1998 - * - * Modifications: - * Added xfer_parms argument to pass VL datatype custom allocation - * information down the chain. - QAK, 7/1/99 - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tconvert(hid_t src_id, hid_t dst_id, hsize_t nelmts, void *buf, - void *background, hid_t dxpl_id) -{ - H5T_path_t *tpath=NULL; /*type conversion info */ - H5T_t *src=NULL, *dst=NULL; /*unatomized types */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Tconvert, FAIL); - H5TRACE6("e","iihxxi",src_id,dst_id,nelmts,buf,background,dxpl_id); - - /* Check args */ - if (NULL==(src=H5I_object_verify(src_id,H5I_DATATYPE)) || - NULL==(dst=H5I_object_verify(dst_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if(H5P_DEFAULT == dxpl_id) - dxpl_id = H5P_DATASET_XFER_DEFAULT; - else - if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not dataset transfer property list"); - - /* Find the conversion function */ - if (NULL==(tpath=H5T_path_find(src, dst, NULL, NULL, dxpl_id))) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert between src and dst data types"); - - if (H5T_convert(tpath, src_id, dst_id, nelmts, 0, 0, buf, background, dxpl_id)<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed"); - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tget_overflow - * - * Purpose: Returns a pointer to the current global overflow function. - * This is an application-defined function that is called - * whenever a data type conversion causes an overflow. - * - * Return: Success: Ptr to an application-defined function. - * - * Failure: NULL (this can happen if no overflow handling - * function is registered). - * - * Programmer: Robb Matzke - * Tuesday, July 7, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5T_overflow_t -H5Tget_overflow(void) -{ - H5T_overflow_t ret_value; /* Return value */ - - FUNC_ENTER_API(H5Tget_overflow, NULL); - H5TRACE0("x",""); - - if (NULL==H5T_overflow_g) - HGOTO_ERROR(H5E_DATATYPE, H5E_UNINITIALIZED, NULL, "no overflow handling function is registered"); - - /* Set return value */ - ret_value=H5T_overflow_g; - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tset_overflow - * - * Purpose: Sets the overflow handler to be the specified function. FUNC - * will be called for all data type conversions that result in - * an overflow. See the definition of `H5T_overflow_t' for - * documentation of arguments and return values. The NULL - * pointer may be passed to remove the overflow handler. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Tuesday, July 7, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tset_overflow(H5T_overflow_t func) -{ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Tset_overflow, FAIL); - H5TRACE1("e","x",func); - - H5T_overflow_g = func; - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * API functions are above; library-private functions are below... - *------------------------------------------------------------------------- - */ - -/*------------------------------------------------------------------------- - * Function: H5T_create - * - * Purpose: Creates a new data type and initializes it to reasonable - * values. The new data type is SIZE bytes and an instance of - * the class TYPE. - * - * Return: Success: Pointer to the new type. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Friday, December 5, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5T_t * -H5T_create(H5T_class_t type, size_t size) -{ - H5T_t *dt = NULL; - hid_t subtype; - H5T_t *ret_value; - - FUNC_ENTER_NOAPI(H5T_create, NULL); - - assert(size > 0); - - switch (type) { - case H5T_INTEGER: - case H5T_FLOAT: - case H5T_TIME: - case H5T_STRING: - case H5T_BITFIELD: - HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, NULL, "type class is not appropriate - use H5Tcopy()"); - - case H5T_OPAQUE: - case H5T_COMPOUND: - if (NULL==(dt = H5FL_CALLOC(H5T_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - dt->type = type; - break; - - case H5T_ENUM: - if (sizeof(char)==size) { - subtype = H5T_NATIVE_SCHAR_g; - } else if (sizeof(short)==size) { - subtype = H5T_NATIVE_SHORT_g; - } else if (sizeof(int)==size) { - subtype = H5T_NATIVE_INT_g; - } else if (sizeof(long)==size) { - subtype = H5T_NATIVE_LONG_g; - } else if (sizeof(long_long)==size) { - subtype = H5T_NATIVE_LLONG_g; - } else { - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "no applicable native integer type"); - } - if (NULL==(dt = H5FL_CALLOC(H5T_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - dt->type = type; - if (NULL==(dt->parent=H5T_copy(H5I_object(subtype), H5T_COPY_ALL))) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy base data type"); - break; - - case H5T_VLEN: /* Variable length datatype */ - HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, NULL, "base type required - use H5Tvlen_create()"); - - case H5T_ARRAY: /* Array datatype */ - HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, NULL, "base type required - use H5Tarray_create()"); - - default: - HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, NULL, "unknown data type class"); - } - - dt->ent.header = HADDR_UNDEF; - dt->size = size; - - /* Set return value */ - ret_value=dt; - -done: - if(ret_value==NULL) { - if(dt!=NULL) - H5FL_FREE(H5T_t,dt); - } /* end if */ - - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_isa - * - * Purpose: Determines if an object has the requisite messages for being - * a data type. - * - * Return: Success: TRUE if the required data type messages are - * present; FALSE otherwise. - * - * Failure: FAIL if the existence of certain messages - * cannot be determined. - * - * Programmer: Robb Matzke - * Monday, November 2, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -htri_t -H5T_isa(H5G_entry_t *ent, hid_t dxpl_id) -{ - htri_t ret_value; - - FUNC_ENTER_NOAPI(H5T_isa, FAIL); - assert(ent); - - if ((ret_value=H5O_exists(ent, H5O_DTYPE, 0, dxpl_id))<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to read object header"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_open - * - * Purpose: Open a named data type. - * - * Return: Success: Ptr to a new data type. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Monday, June 1, 1998 - * - * Modifications: - * Changed to use H5T_open_oid - QAK - 3/17/99 - * - *------------------------------------------------------------------------- - */ -H5T_t * -H5T_open (H5G_entry_t *loc, const char *name, hid_t dxpl_id) -{ - H5T_t *dt; - H5G_entry_t ent; - H5T_t *ret_value; - - FUNC_ENTER_NOAPI(H5T_open, NULL); - - assert (loc); - assert (name && *name); - - /* - * Find the named data type object header and read the data type message - * from it. - */ - if (H5G_find (loc, name, NULL, &ent/*out*/, dxpl_id)<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_NOTFOUND, NULL, "not found"); - - /* Open the datatype object */ - if ((dt=H5T_open_oid(&ent, dxpl_id)) ==NULL) - HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "not found"); - - /* Set return value */ - ret_value=dt; - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_open_oid - * - * Purpose: Open a named data type. - * - * Return: Success: Ptr to a new data type. - * - * Failure: NULL - * - * Programmer: Quincey Koziol - * Wednesday, March 17, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5T_t * -H5T_open_oid (H5G_entry_t *ent, hid_t dxpl_id) -{ - H5T_t *dt=NULL; - H5T_t *ret_value; - - FUNC_ENTER_NOAPI(H5T_open_oid, NULL); - - assert (ent); - - if (H5O_open (ent)<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open named data type"); - if (NULL==(dt=H5O_read (ent, H5O_DTYPE, 0, NULL, dxpl_id))) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to load type message from object header"); - - /* Mark the type as named and open */ - dt->state = H5T_STATE_OPEN; - /* Shallow copy (take ownership) of the group entry object */ - H5G_ent_copy(&(dt->ent),ent,H5G_COPY_SHALLOW); - - /* Set return value */ - ret_value=dt; - -done: - if(ret_value==NULL) { - if(dt==NULL) - H5O_close(ent); - } /* end if */ - - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_copy - * - * Purpose: Copies datatype OLD_DT. The resulting data type is not - * locked and is a transient type. - * - * Return: Success: Pointer to a new copy of the OLD_DT argument. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Thursday, December 4, 1997 - * - * Modifications: - * - * Robb Matzke, 4 Jun 1998 - * Added the METHOD argument. If it's H5T_COPY_TRANSIENT then the - * result will be an unlocked transient type. Otherwise if it's - * H5T_COPY_ALL then the result is a named type if the original is a - * named type, but the result is not opened. Finally, if it's - * H5T_COPY_REOPEN and the original type is a named type then the result - * is a named type and the type object header is opened again. The - * H5T_COPY_REOPEN method is used when returning a named type to the - * application. - * - * Robb Matzke, 22 Dec 1998 - * Now able to copy enumeration data types. - * - * Robb Matzke, 20 May 1999 - * Now able to copy opaque types. - * - * Pedro Vicente, 21 Sep 2002 - * Added a deep copy of the symbol table entry - * - *------------------------------------------------------------------------- - */ -H5T_t * -H5T_copy(const H5T_t *old_dt, H5T_copy_t method) -{ - H5T_t *new_dt=NULL, *tmp=NULL; - int i; - char *s; - H5T_t *ret_value; - - FUNC_ENTER_NOAPI(H5T_copy, NULL); - - /* check args */ - assert(old_dt); - - /* Allocate space */ - if (NULL==(new_dt = H5FL_MALLOC(H5T_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - - /* Copy actual information */ - *new_dt = *old_dt; - - /* Copy parent information */ - if (new_dt->parent) - new_dt->parent = H5T_copy(new_dt->parent, method); - - /* Check what sort of copy we are making */ - switch (method) { - case H5T_COPY_TRANSIENT: - /* - * Return an unlocked transient type. - */ - new_dt->state = H5T_STATE_TRANSIENT; - HDmemset (&(new_dt->ent), 0, sizeof(new_dt->ent)); - new_dt->ent.header = HADDR_UNDEF; - break; - - case H5T_COPY_ALL: - /* - * Return a transient type (locked or unlocked) or an unopened named - * type. Immutable transient types are degraded to read-only. - */ - if (H5T_STATE_OPEN==new_dt->state) { - new_dt->state = H5T_STATE_NAMED; - } else if (H5T_STATE_IMMUTABLE==new_dt->state) { - new_dt->state = H5T_STATE_RDONLY; - } - break; - - case H5T_COPY_REOPEN: - /* - * Return a transient type (locked or unlocked) or an opened named - * type. - */ - if (H5F_addr_defined(new_dt->ent.header)) { - if (H5O_open (&(new_dt->ent))<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reopen named data type"); - new_dt->state = H5T_STATE_OPEN; - } - break; - } /* end switch */ - - switch(new_dt->type) { - case H5T_COMPOUND: - { - int accum_change=0; /* Amount of change in the offset of the fields */ - - /* - * Copy all member fields to new type, then overwrite the - * name and type fields of each new member with copied values. - * That is, H5T_copy() is a deep copy. - */ - new_dt->u.compnd.memb = H5MM_malloc(new_dt->u.compnd.nalloc * - sizeof(H5T_cmemb_t)); - if (NULL==new_dt->u.compnd.memb) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - - HDmemcpy(new_dt->u.compnd.memb, old_dt->u.compnd.memb, - new_dt->u.compnd.nmembs * sizeof(H5T_cmemb_t)); - - for (i=0; iu.compnd.nmembs; i++) { - int j; - int old_match; - - s = new_dt->u.compnd.memb[i].name; - new_dt->u.compnd.memb[i].name = H5MM_xstrdup(s); - tmp = H5T_copy (old_dt->u.compnd.memb[i].type, method); - new_dt->u.compnd.memb[i].type = tmp; - - /* Apply the accumulated size change to the offset of the field */ - new_dt->u.compnd.memb[i].offset += accum_change; - - if(old_dt->u.compnd.sorted != H5T_SORT_VALUE) { - for (old_match=-1, j=0; ju.compnd.nmembs; j++) { - if(!HDstrcmp(new_dt->u.compnd.memb[i].name,old_dt->u.compnd.memb[j].name)) { - old_match=j; - break; - } /* end if */ - } /* end for */ - - /* check if we couldn't find a match */ - if(old_match<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "fields in datatype corrupted"); - } /* end if */ - else { - old_match=i; - } /* end else */ - - /* If the field changed size, add that change to the accumulated size change */ - if(new_dt->u.compnd.memb[i].type->size != old_dt->u.compnd.memb[old_match].type->size) { - /* Adjust the size of the member */ - new_dt->u.compnd.memb[i].size = (old_dt->u.compnd.memb[old_match].size*tmp->size)/old_dt->u.compnd.memb[old_match].type->size; - - accum_change += (new_dt->u.compnd.memb[i].type->size - old_dt->u.compnd.memb[old_match].type->size); - } /* end if */ - } /* end for */ - - /* Apply the accumulated size change to the size of the compound struct */ - new_dt->size += accum_change; - - } - break; - - case H5T_ENUM: - /* - * Copy all member fields to new type, then overwrite the name fields - * of each new member with copied values. That is, H5T_copy() is a - * deep copy. - */ - new_dt->u.enumer.name = H5MM_malloc(new_dt->u.enumer.nalloc * - sizeof(char*)); - new_dt->u.enumer.value = H5MM_malloc(new_dt->u.enumer.nalloc * - new_dt->size); - if (NULL==new_dt->u.enumer.value) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - HDmemcpy(new_dt->u.enumer.value, old_dt->u.enumer.value, - new_dt->u.enumer.nmembs * new_dt->size); - for (i=0; iu.enumer.nmembs; i++) { - s = old_dt->u.enumer.name[i]; - new_dt->u.enumer.name[i] = H5MM_xstrdup(s); - } - break; - - case H5T_VLEN: - if(method==H5T_COPY_TRANSIENT || method==H5T_COPY_REOPEN) { - /* H5T_copy converts any VL type into a memory VL type */ - if (H5T_vlen_mark(new_dt, NULL, H5T_VLEN_MEMORY)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid VL location"); - } - break; - - case H5T_OPAQUE: - /* - * Copy the tag name. - */ - new_dt->u.opaque.tag = HDstrdup(new_dt->u.opaque.tag); - break; - - case H5T_ARRAY: - /* Re-compute the array's size, in case it's base type changed size */ - new_dt->size=new_dt->u.array.nelem*new_dt->parent->size; - break; - - default: - break; - } /* end switch */ - - /* Deep copy of the symbol table entry */ - if (H5G_ent_copy(&(new_dt->ent), &(old_dt->ent),H5G_COPY_DEEP)<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to copy entry"); - - /* Set return value */ - ret_value=new_dt; - -done: - if(ret_value==NULL) { - if(new_dt!=NULL) - H5FL_FREE (H5T_t,new_dt); - } /* end if */ - - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_commit - * - * Purpose: Commit a type, giving it a name and causing it to become - * immutable. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Monday, June 1, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5T_commit (H5G_entry_t *loc, const char *name, H5T_t *type, hid_t dxpl_id) -{ - H5F_t *file = NULL; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5T_commit, FAIL); - - assert (loc); - assert (name && *name); - assert (type); - - /* - * Check arguments. We cannot commit an immutable type because H5Tclose() - * normally fails on such types (try H5Tclose(H5T_NATIVE_INT)) but closing - * a named type should always succeed. - */ - if (H5T_STATE_NAMED==type->state || H5T_STATE_OPEN==type->state) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "data type is already committed"); - if (H5T_STATE_IMMUTABLE==type->state) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "data type is immutable"); - - /* Check for a "sensible" datatype to store on disk */ - if(H5T_is_sensible(type)!=TRUE) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "datatype is not sensible"); - - /* Find the insertion file */ - if (NULL==(file=H5G_insertion_file(loc, name, dxpl_id))) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to find insertion point"); - - /* - * Create the object header and open it for write access. Insert the data - * type message and then give the object header a name. - */ - if (H5O_create (file, dxpl_id, 64, &(type->ent))<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create data type object header"); - if (H5O_modify (&(type->ent), H5O_DTYPE, 0, H5O_FLAG_CONSTANT, 1, type, dxpl_id)<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to update type header message"); - if (H5G_insert (loc, name, &(type->ent), dxpl_id)<0) - HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to name data type"); - type->state = H5T_STATE_OPEN; - -done: - if (ret_value<0) { - if ((type->state==H5T_STATE_TRANSIENT || type->state==H5T_STATE_RDONLY) && H5F_addr_defined(type->ent.header)) { - H5O_close(&(type->ent)); - type->ent.header = HADDR_UNDEF; - } - } - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_lock - * - * Purpose: Lock a transient data type making it read-only. If IMMUTABLE - * is set then the type cannot be closed except when the library - * itself closes. - * - * This function is a no-op if the type is not transient or if - * the type is already read-only or immutable. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Thursday, June 4, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5T_lock (H5T_t *dt, hbool_t immutable) -{ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5T_lock, FAIL); - assert (dt); - - switch (dt->state) { - case H5T_STATE_TRANSIENT: - dt->state = immutable ? H5T_STATE_IMMUTABLE : H5T_STATE_RDONLY; - break; - case H5T_STATE_RDONLY: - if (immutable) dt->state = H5T_STATE_IMMUTABLE; - break; - case H5T_STATE_IMMUTABLE: - case H5T_STATE_NAMED: - case H5T_STATE_OPEN: - /*void*/ - break; - } - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_release - * - * Purpose: Frees all memory associated with a datatype, but does not - * free the H5T_t structure (which should be done in H5T_close). - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Monday, January 6, 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5T_free(H5T_t *dt) -{ - int i; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5T_free, FAIL); - - assert(dt); - - /* - * If a named type is being closed then close the object header also. - */ - if (H5T_STATE_OPEN==dt->state) { - assert (H5F_addr_defined(dt->ent.header)); - if (H5O_close(&(dt->ent))<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close data type object header"); - dt->state = H5T_STATE_NAMED; - } - - /* - * Don't free locked datatypes. - */ - if (H5T_STATE_IMMUTABLE==dt->state) - HGOTO_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to close immutable datatype"); - - /* Close the datatype */ - switch (dt->type) { - case H5T_COMPOUND: - for (i=0; iu.compnd.nmembs; i++) { - H5MM_xfree(dt->u.compnd.memb[i].name); - H5T_close(dt->u.compnd.memb[i].type); - } - H5MM_xfree(dt->u.compnd.memb); - break; - - case H5T_ENUM: - for (i=0; iu.enumer.nmembs; i++) - H5MM_xfree(dt->u.enumer.name[i]); - H5MM_xfree(dt->u.enumer.name); - H5MM_xfree(dt->u.enumer.value); - break; - - case H5T_OPAQUE: - H5MM_xfree(dt->u.opaque.tag); - break; - - default: - break; - } - - /* Free the ID to name info */ - H5G_free_ent_name(&(dt->ent)); - - /* Close the parent */ - if (dt->parent && H5T_close(dt->parent)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close parent data type"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5T_free() */ - - -/*------------------------------------------------------------------------- - * Function: H5T_close - * - * Purpose: Frees a data type and all associated memory. If the data - * type is locked then nothing happens. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Monday, December 8, 1997 - * - * Modifications: - * Robb Matzke, 1999-04-27 - * This function fails if the datatype state is IMMUTABLE. - * - * Robb Matzke, 1999-05-20 - * Closes opaque types also. - * - * Pedro Vicente, 22 Aug 2002 - * Added "ID to name" support - * - * Quincey Koziol, 2003-01-06 - * Moved "guts" of function to H5T_free() - * - *------------------------------------------------------------------------- - */ -herr_t -H5T_close(H5T_t *dt) -{ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5T_close, FAIL); - - assert(dt); - - if(H5T_free(dt)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free datatype"); - - /* Free the datatype struct */ - H5FL_FREE(H5T_t,dt); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_is_atomic - * - * Purpose: Determines if a data type is an atomic type. - * - * Return: Success: TRUE, FALSE - * - * Failure: Negative - * - * Programmer: Robb Matzke - * Wednesday, January 7, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -htri_t -H5T_is_atomic(const H5T_t *dt) -{ - htri_t ret_value; - - FUNC_ENTER_NOAPI(H5T_is_atomic, FAIL); - - assert(dt); - - if (H5T_COMPOUND!=dt->type && H5T_ENUM!=dt->type && H5T_VLEN!=dt->type && H5T_OPAQUE!=dt->type && H5T_ARRAY!=dt->type) - ret_value = TRUE; - else - ret_value = FALSE; - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_set_size - * - * Purpose: Sets the total size in bytes for a data type (this operation - * is not permitted on compound data types). If the size is - * decreased so that the significant bits of the data type - * extend beyond the edge of the new size, then the `offset' - * property is decreased toward zero. If the `offset' becomes - * zero and the significant bits of the data type still hang - * over the edge of the new size, then the number of significant - * bits is decreased. - * - * Adjusting the size of an H5T_STRING automatically sets the - * precision to 8*size. - * - * All data types have a positive size. - * - * Return: Success: non-negative - * - * Failure: nagative - * - * Programmer: Robb Matzke - * Tuesday, December 22, 1998 - * - * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works with derived data types. - * - *------------------------------------------------------------------------- - */ -herr_t -H5T_set_size(H5T_t *dt, size_t size) -{ - size_t prec, offset; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5T_set_size, FAIL); - - /* Check args */ - assert(dt); - assert(size!=0); - assert(H5T_ENUM!=dt->type || 0==dt->u.enumer.nmembs); - - if (dt->parent) { - if (H5T_set_size(dt->parent, size)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set size for parent data type"); - dt->size = dt->parent->size; - } else { - if (H5T_is_atomic(dt)) { - offset = dt->u.atomic.offset; - prec = dt->u.atomic.prec; - - /* Decrement the offset and precision if necessary */ - if (prec > 8*size) - offset = 0; - else - if (offset+prec > 8*size) - offset = 8 * size - prec; - if (prec > 8*size) - prec = 8 * size; - } else { - prec = offset = 0; - } - - switch (dt->type) { - case H5T_COMPOUND: - case H5T_ARRAY: - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set size of specified data type"); - - case H5T_INTEGER: - case H5T_TIME: - case H5T_BITFIELD: - case H5T_ENUM: - case H5T_OPAQUE: - /* nothing to check */ - break; - - case H5T_STRING: - /* Convert string to variable-length datatype */ - if(size==H5T_VARIABLE) { - H5T_t *base = NULL; /* base data type */ - H5T_cset_t tmp_cset; /* Temp. cset info */ - H5T_str_t tmp_strpad; /* Temp. strpad info */ - - /* Get a copy of unsigned char type as the base/parent type */ - if (NULL==(base=H5I_object(H5T_NATIVE_UCHAR))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid base datatype"); - dt->parent=H5T_copy(base,H5T_COPY_ALL); - - /* change this datatype into a VL string */ - dt->type = H5T_VLEN; - - /* - * Force conversions (i.e. memory to memory conversions - * should duplicate data, not point to the same VL strings) - */ - dt->force_conv = TRUE; - - /* Before we mess with the info in the union, extract the - * values we need */ - tmp_cset=dt->u.atomic.u.s.cset; - tmp_strpad=dt->u.atomic.u.s.pad; - - /* This is a string, not a sequence */ - dt->u.vlen.type = H5T_VLEN_STRING; - - /* Set character set and padding information */ - dt->u.vlen.cset = tmp_cset; - dt->u.vlen.pad = tmp_strpad; - - /* Set up VL information */ - if (H5T_vlen_mark(dt, NULL, H5T_VLEN_MEMORY)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid VL location"); - - } else { - prec = 8 * size; - offset = 0; - } /* end else */ - break; - - case H5T_FLOAT: - /* - * The sign, mantissa, and exponent fields should be adjusted - * first when decreasing the size of a floating point type. - */ - if (dt->u.atomic.u.f.sign >= prec || - dt->u.atomic.u.f.epos + dt->u.atomic.u.f.esize > prec || - dt->u.atomic.u.f.mpos + dt->u.atomic.u.f.msize > prec) { - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "adjust sign, mantissa, and exponent fields first"); - } - break; - - default: - assert("not implemented yet" && 0); - } - - /* Commit */ - if(dt->type!=H5T_VLEN) { - dt->size = size; - if (H5T_is_atomic(dt)) { - dt->u.atomic.offset = offset; - dt->u.atomic.prec = prec; - } - } - } - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_get_size - * - * Purpose: Determines the total size of a data type in bytes. - * - * Return: Success: Size of the data type in bytes. The size of - * the data type is the size of an instance of - * that data type. - * - * Failure: 0 (valid data types are never zero size) - * - * Programmer: Robb Matzke - * Tuesday, December 9, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -size_t -H5T_get_size(const H5T_t *dt) -{ - /* Use FUNC_ENTER_NOINIT here to avoid performance issues */ - FUNC_ENTER_NOINIT(H5T_get_size); - - /* check args */ - assert(dt); - - FUNC_LEAVE_NOAPI(dt->size); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_set_precision - * - * Purpose: Sets the precision of a data type. The precision is - * the number of significant bits which, unless padding is - * present, is 8 times larger than the value returned by - * H5Tget_size(). - * - * If the precision is increased then the offset is decreased - * and then the size is increased to insure that significant - * bits do not "hang over" the edge of the data type. - * - * The precision property of strings is read-only. - * - * When decreasing the precision of a floating point type, set - * the locations and sizes of the sign, mantissa, and exponent - * fields first. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Wednesday, January 7, 1998 - * - * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works for derived data types. - * - *------------------------------------------------------------------------- - */ -herr_t -H5T_set_precision(H5T_t *dt, size_t prec) -{ - size_t offset, size; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5T_set_precision, FAIL); - - /* Check args */ - assert(dt); - assert(prec>0); - assert(H5T_ENUM!=dt->type || 0==dt->u.enumer.nmembs); - - if (dt->parent) { - if (H5T_set_precision(dt->parent, prec)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set precision for base type"); - dt->size = dt->parent->size; - } else { - if (H5T_COMPOUND==dt->type || H5T_OPAQUE==dt->type || H5T_ARRAY==dt->type) { - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for specified data type"); - } else if (H5T_ENUM==dt->type) { - /*nothing*/ - } else if (H5T_is_atomic(dt)) { - /* Adjust the offset and size */ - offset = dt->u.atomic.offset; - size = dt->size; - if (prec > 8*size) - offset = 0; - else if (offset+prec > 8 * size) offset = 8 * size - prec; - if (prec > 8*size) - size = (prec+7) / 8; - - /* Check that things are still kosher */ - switch (dt->type) { - case H5T_INTEGER: - case H5T_TIME: - case H5T_BITFIELD: - /* nothing to check */ - break; - - case H5T_STRING: - HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "precision for this type is read-only"); - - case H5T_FLOAT: - /* - * The sign, mantissa, and exponent fields should be adjusted - * first when decreasing the precision of a floating point - * type. - */ - if (dt->u.atomic.u.f.sign >= prec || - dt->u.atomic.u.f.epos + dt->u.atomic.u.f.esize > prec || - dt->u.atomic.u.f.mpos + dt->u.atomic.u.f.msize > prec) { - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "adjust sign, mantissa, and exponent fields first"); - } - break; - - default: - assert("not implemented yet" && 0); - } - - /* Commit */ - dt->size = size; - if (H5T_is_atomic(dt)) { - dt->u.atomic.offset = offset; - dt->u.atomic.prec = prec; - } - } - } - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5T_set_offset - * - * Purpose: Sets the bit offset of the first significant bit. The - * signficant bits of an atomic datum can be offset from the - * beginning of the memory for that datum by an amount of - * padding. The `offset' property specifies the number of bits - * of padding that appear to the "right of" the value. That is, - * if we have a 32-bit datum with 16-bits of precision having - * the value 0x1122 then it will be layed out in memory as (from - * small byte address toward larger byte addresses): - * - * Big Big Little Little - * Endian Endian Endian Endian - * offset=0 offset=16 offset=0 offset=16 - * - * 0: [ pad] [0x11] [0x22] [ pad] - * 1: [ pad] [0x22] [0x11] [ pad] - * 2: [0x11] [ pad] [ pad] [0x22] - * 3: [0x22] [ pad] [ pad] [0x11] - * - * If the offset is incremented then the total size is - * incremented also if necessary to prevent significant bits of - * the value from hanging over the edge of the data type. - * - * The offset of an H5T_STRING cannot be set to anything but - * zero. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Wednesday, January 7, 1998 - * - * Modifications: - * Robb Matzke, 22 Dec 1998 - * Also works for derived data types. - * - *------------------------------------------------------------------------- - */ -herr_t -H5T_set_offset(H5T_t *dt, size_t offset) -{ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5T_set_offset, FAIL); - - /* Check args */ - assert(dt); - assert(H5T_STRING!=dt->type || 0==offset); - assert(H5T_ENUM!=dt->type || 0==dt->u.enumer.nmembs); - - if (dt->parent) { - if (H5T_set_offset(dt->parent, offset)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set offset for base type"); - dt->size = dt->parent->size; - } else { - if (H5T_COMPOUND==dt->type || H5T_OPAQUE==dt->type || H5T_ARRAY==dt->type) { - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for specified data type"); - } else if (H5T_ENUM==dt->type) { - /*nothing*/ - } else { - if (offset+dt->u.atomic.prec > 8*dt->size) { - dt->size = (offset + dt->u.atomic.prec + 7) / 8; - } - dt->u.atomic.offset = offset; - } - } + default: + break; + } /* end switch */ + + /* Deep copy of the symbol table entry */ + if (H5G_ent_copy(&(new_dt->ent), &(old_dt->ent),H5G_COPY_DEEP)<0) + HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to copy entry"); + + /* Set return value */ + ret_value=new_dt; done: + if(ret_value==NULL) { + if(new_dt!=NULL) + H5FL_FREE (H5T_t,new_dt); + } /* end if */ + FUNC_LEAVE_NOAPI(ret_value); } /*------------------------------------------------------------------------- - * Function: H5T_insert + * Function: H5T_lock + * + * Purpose: Lock a transient data type making it read-only. If IMMUTABLE + * is set then the type cannot be closed except when the library + * itself closes. * - * Purpose: Adds a new MEMBER to the compound data type PARENT. The new - * member will have a NAME that is unique within PARENT and an - * instance of PARENT will have the member begin at byte offset - * OFFSET from the beginning. + * This function is a no-op if the type is not transient or if + * the type is already read-only or immutable. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke - * Monday, December 8, 1997 + * Thursday, June 4, 1998 * * Modifications: - * Took out arrayness parameters - QAK, 10/6/00 * *------------------------------------------------------------------------- */ herr_t -H5T_insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member) +H5T_lock (H5T_t *dt, hbool_t immutable) { - int idx, i; - size_t total_size; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5T_insert, FAIL); - - /* check args */ - assert(parent && H5T_COMPOUND == parent->type); - assert(H5T_STATE_TRANSIENT==parent->state); - assert(member); - assert(name && *name); - - /* Does NAME already exist in PARENT? */ - for (i=0; iu.compnd.nmembs; i++) { - if (!HDstrcmp(parent->u.compnd.memb[i].name, name)) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member name is not unique"); - } - - /* Does the new member overlap any existing member ? */ - total_size=member->size; - for (i=0; iu.compnd.nmembs; i++) { - if ((offset <= 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].size > offset)) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member overlaps with another member"); - } - - /* Does the new member overlap the end of the compound type? */ - if(offset+total_size>parent->size) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member extends past end of compound type"); + herr_t ret_value=SUCCEED; /* Return value */ - /* Increase member array if necessary */ - if (parent->u.compnd.nmembs >= parent->u.compnd.nalloc) { - size_t na = parent->u.compnd.nalloc + H5T_COMPND_INC; - H5T_cmemb_t *x = H5MM_realloc (parent->u.compnd.memb, - na * sizeof(H5T_cmemb_t)); + FUNC_ENTER_NOAPI(H5T_lock, FAIL); + assert (dt); - if (!x) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - parent->u.compnd.nalloc = (int)na; - parent->u.compnd.memb = x; + switch (dt->state) { + case H5T_STATE_TRANSIENT: + dt->state = immutable ? H5T_STATE_IMMUTABLE : H5T_STATE_RDONLY; + break; + case H5T_STATE_RDONLY: + if (immutable) dt->state = H5T_STATE_IMMUTABLE; + break; + case H5T_STATE_IMMUTABLE: + case H5T_STATE_NAMED: + case H5T_STATE_OPEN: + /*void*/ + break; } - /* Add member to end of member array */ - 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].type = H5T_copy (member, H5T_COPY_ALL); - - parent->u.compnd.sorted = H5T_SORT_NONE; - parent->u.compnd.nmembs++; - - /* - * Set the "force conversion" flag if VL datatype fields exist in this type - * or any component types - */ - if(member->type==H5T_VLEN || member->force_conv==TRUE) - parent->force_conv=TRUE; - - /* Set the flag for this compound type, if the field is an array */ - if(member->type==H5T_ARRAY) - parent->u.compnd.has_array=TRUE; - done: FUNC_LEAVE_NOAPI(ret_value); } /*------------------------------------------------------------------------- - * Function: H5T_pack + * Function: H5T_free * - * Purpose: Recursively packs a compound data type by removing padding - * bytes. This is done in place (that is, destructively). + * Purpose: Frees all memory associated with a datatype, but does not + * free the H5T_t structure (which should be done in H5T_close). * * Return: Non-negative on success/Negative on failure * - * Programmer: Robb Matzke - * Wednesday, January 7, 1998 + * Programmer: Quincey Koziol + * Monday, January 6, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t -H5T_pack(H5T_t *dt) +H5T_free(H5T_t *dt) { - int i; - size_t offset; + int i; herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5T_pack, FAIL); + FUNC_ENTER_NOAPI(H5T_free, FAIL); assert(dt); - if (H5T_COMPOUND == dt->type) { - assert(H5T_STATE_TRANSIENT==dt->state); - - /* Recursively pack the members */ - for (i=0; iu.compnd.nmembs; i++) { - if (H5T_pack(dt->u.compnd.memb[i].type) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack part of a compound data type"); - } + /* + * If a named type is being closed then close the object header also. + */ + if (H5T_STATE_OPEN==dt->state) { + assert (H5F_addr_defined(dt->ent.header)); + if (H5O_close(&(dt->ent))<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close data type object header"); + dt->state = H5T_STATE_NAMED; + } - /* Remove padding between members */ - H5T_sort_value(dt, NULL); - for (i=0, offset=0; iu.compnd.nmembs; i++) { - dt->u.compnd.memb[i].offset = offset; - offset += dt->u.compnd.memb[i].size; - } + /* + * Don't free locked datatypes. + */ + if (H5T_STATE_IMMUTABLE==dt->state) + HGOTO_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to close immutable datatype"); + + /* Close the datatype */ + switch (dt->type) { + case H5T_COMPOUND: + for (i=0; iu.compnd.nmembs; i++) { + H5MM_xfree(dt->u.compnd.memb[i].name); + H5T_close(dt->u.compnd.memb[i].type); + } + H5MM_xfree(dt->u.compnd.memb); + break; + + case H5T_ENUM: + for (i=0; iu.enumer.nmembs; i++) + H5MM_xfree(dt->u.enumer.name[i]); + H5MM_xfree(dt->u.enumer.name); + H5MM_xfree(dt->u.enumer.value); + break; + + case H5T_OPAQUE: + H5MM_xfree(dt->u.opaque.tag); + break; - /* Change total size */ - dt->size = MAX(1, offset); + default: + break; } + + /* Free the ID to name info */ + H5G_free_ent_name(&(dt->ent)); + + /* Close the parent */ + if (dt->parent && H5T_close(dt->parent)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close parent data type"); done: FUNC_LEAVE_NOAPI(ret_value); -} +} /* end H5T_free() */ /*------------------------------------------------------------------------- - * Function: H5T_sort_value + * Function: H5T_close * - * Purpose: Sorts the members of a compound data type by their offsets; - * sorts the members of an enum type by their values. This even - * works for locked data types 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. + * Purpose: Frees a data type and all associated memory. If the data + * type is locked then nothing happens. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke - * Wednesday, January 7, 1998 + * Monday, December 8, 1997 * * Modifications: + * Robb Matzke, 1999-04-27 + * This function fails if the datatype state is IMMUTABLE. + * + * Robb Matzke, 1999-05-20 + * Closes opaque types also. + * + * Pedro Vicente, 22 Aug 2002 + * Added "ID to name" support + * + * Quincey Koziol, 2003-01-06 + * Moved "guts" of function to H5T_free() * *------------------------------------------------------------------------- */ herr_t -H5T_sort_value(H5T_t *dt, int *map) +H5T_close(H5T_t *dt) { - int i, j, nmembs; - size_t size; - hbool_t swapped; - uint8_t tbuf[32]; - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5T_sort_value, FAIL); + FUNC_ENTER_NOAPI(H5T_close, FAIL); - /* Check args */ assert(dt); - assert(H5T_COMPOUND==dt->type || H5T_ENUM==dt->type); - - /* Use a bubble sort because we can short circuit */ - if (H5T_COMPOUND==dt->type) { - if (H5T_SORT_VALUE!=dt->u.compnd.sorted) { - dt->u.compnd.sorted = H5T_SORT_VALUE; - nmembs = dt->u.compnd.nmembs; - for (i=nmembs-1, swapped=TRUE; i>0 && swapped; --i) { - for (j=0, swapped=FALSE; ju.compnd.memb[j].offset > - dt->u.compnd.memb[j+1].offset) { - H5T_cmemb_t tmp = dt->u.compnd.memb[j]; - dt->u.compnd.memb[j] = dt->u.compnd.memb[j+1]; - dt->u.compnd.memb[j+1] = tmp; - 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; iu.compnd.memb[i].offset < - dt->u.compnd.memb[i+1].offset); - } -#endif - } - } else if (H5T_ENUM==dt->type) { - if (H5T_SORT_VALUE!=dt->u.enumer.sorted) { - dt->u.enumer.sorted = H5T_SORT_VALUE; - nmembs = dt->u.enumer.nmembs; - size = dt->size; - assert(size<=sizeof(tbuf)); - for (i=nmembs-1, swapped=TRUE; i>0 && swapped; --i) { - for (j=0, swapped=FALSE; ju.enumer.value+j*size, - dt->u.enumer.value+(j+1)*size, - size)>0) { - /* Swap names */ - char *tmp = dt->u.enumer.name[j]; - dt->u.enumer.name[j] = dt->u.enumer.name[j+1]; - dt->u.enumer.name[j+1] = tmp; - - /* Swap values */ - HDmemcpy(tbuf, dt->u.enumer.value+j*size, size); - HDmemcpy(dt->u.enumer.value+j*size, - dt->u.enumer.value+(j+1)*size, size); - HDmemcpy(dt->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; iu.enumer.value+i*size, - dt->u.enumer.value+(i+1)*size, - size)<0); - } -#endif - } - } - + + if(H5T_free(dt)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free datatype"); + + /* Free the datatype struct */ + H5FL_FREE(H5T_t,dt); + done: FUNC_LEAVE_NOAPI(ret_value); } /*------------------------------------------------------------------------- - * Function: H5T_sort_name + * Function: H5T_is_atomic * - * Purpose: Sorts members of a compound or enumeration data type by their - * names. This even works for locked data types since it doesn't - * change the value of the types. + * Purpose: Determines if a data type is an atomic type. * - * Return: Success: Non-negative + * Return: Success: TRUE, FALSE * * Failure: Negative * * Programmer: Robb Matzke - * Monday, January 4, 1999 + * Wednesday, January 7, 1998 * * Modifications: * *------------------------------------------------------------------------- */ -herr_t -H5T_sort_name(H5T_t *dt, int *map) +htri_t +H5T_is_atomic(const H5T_t *dt) { - int i, j, nmembs; - size_t size; - hbool_t swapped; - uint8_t tbuf[32]; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5T_sort_name, FAIL); + htri_t ret_value; + + FUNC_ENTER_NOAPI(H5T_is_atomic, FAIL); - /* Check args */ assert(dt); - assert(H5T_COMPOUND==dt->type || H5T_ENUM==dt->type); - - /* Use a bubble sort because we can short circuit */ - if (H5T_COMPOUND==dt->type) { - if (H5T_SORT_NAME!=dt->u.compnd.sorted) { - dt->u.compnd.sorted = H5T_SORT_NAME; - nmembs = dt->u.compnd.nmembs; - for (i=nmembs-1, swapped=TRUE; i>0 && swapped; --i) { - for (j=0, swapped=FALSE; ju.compnd.memb[j].name, - dt->u.compnd.memb[j+1].name)>0) { - H5T_cmemb_t tmp = dt->u.compnd.memb[j]; - dt->u.compnd.memb[j] = dt->u.compnd.memb[j+1]; - dt->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; iu.compnd.memb[i].name, - dt->u.compnd.memb[i+1].name)<0); - } -#endif - } - } else if (H5T_ENUM==dt->type) { - if (H5T_SORT_NAME!=dt->u.enumer.sorted) { - dt->u.enumer.sorted = H5T_SORT_NAME; - nmembs = dt->u.enumer.nmembs; - size = dt->size; - assert(size<=sizeof(tbuf)); - for (i=nmembs-1, swapped=TRUE; i>0 && swapped; --i) { - for (j=0, swapped=FALSE; ju.enumer.name[j], - dt->u.enumer.name[j+1])>0) { - /* Swap names */ - char *tmp = dt->u.enumer.name[j]; - dt->u.enumer.name[j] = dt->u.enumer.name[j+1]; - dt->u.enumer.name[j+1] = tmp; - - /* Swap values */ - HDmemcpy(tbuf, dt->u.enumer.value+j*size, size); - HDmemcpy(dt->u.enumer.value+j*size, - dt->u.enumer.value+(j+1)*size, size); - HDmemcpy(dt->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; iu.enumer.name[i], dt->u.enumer.name[i+1])<0); -#endif - } - } - + + if (H5T_COMPOUND!=dt->type && H5T_ENUM!=dt->type && H5T_VLEN!=dt->type && + H5T_OPAQUE!=dt->type && H5T_ARRAY!=dt->type) + ret_value = TRUE; + else + ret_value = FALSE; + done: FUNC_LEAVE_NOAPI(ret_value); } /*------------------------------------------------------------------------- - * Function: H5T_enum_insert + * Function: H5T_set_size * - * Purpose: Insert a new member having a NAME and VALUE into an - * enumeration data TYPE. The NAME and VALUE must both be - * unique. The VALUE points to data of the data type defined for - * the enumeration base type. + * Purpose: Sets the total size in bytes for a data type (this operation + * is not permitted on compound data types). If the size is + * decreased so that the significant bits of the data type + * extend beyond the edge of the new size, then the `offset' + * property is decreased toward zero. If the `offset' becomes + * zero and the significant bits of the data type still hang + * over the edge of the new size, then the number of significant + * bits is decreased. + * + * Adjusting the size of an H5T_STRING automatically sets the + * precision to 8*size. + * + * All data types have a positive size. * * Return: Success: non-negative * - * Failure: negative + * Failure: nagative * * Programmer: Robb Matzke - * Wednesday, December 23, 1998 + * Tuesday, December 22, 1998 * * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works with derived data types. * *------------------------------------------------------------------------- */ herr_t -H5T_enum_insert(H5T_t *dt, const char *name, void *value) +H5T_set_size(H5T_t *dt, size_t size) { - int i; - char **names=NULL; - uint8_t *values=NULL; + size_t prec, offset; herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5T_enum_insert, FAIL); - assert(dt); - assert(name && *name); - assert(value); - - /* The name and value had better not already exist */ - for (i=0; iu.enumer.nmembs; i++) { - if (!HDstrcmp(dt->u.enumer.name[i], name)) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "name redefinition"); - if (!HDmemcmp(dt->u.enumer.value+i*dt->size, value, dt->size)) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "value redefinition"); - } + FUNC_ENTER_NOAPI(H5T_set_size, FAIL); + + /* Check args */ + assert(dt); + assert(size!=0); + assert(H5T_ENUM!=dt->type || 0==dt->u.enumer.nmembs); + + if (dt->parent) { + if (H5T_set_size(dt->parent, size)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set size for parent data type"); + dt->size = dt->parent->size; + } else { + if (H5T_is_atomic(dt)) { + offset = dt->u.atomic.offset; + prec = dt->u.atomic.prec; + + /* Decrement the offset and precision if necessary */ + if (prec > 8*size) + offset = 0; + else + if (offset+prec > 8*size) + offset = 8 * size - prec; + if (prec > 8*size) + prec = 8 * size; + } else { + prec = offset = 0; + } + + switch (dt->type) { + case H5T_COMPOUND: + case H5T_ARRAY: + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set size of specified data type"); + + case H5T_INTEGER: + case H5T_TIME: + case H5T_BITFIELD: + case H5T_ENUM: + case H5T_OPAQUE: + /* nothing to check */ + break; + + case H5T_STRING: + /* Convert string to variable-length datatype */ + if(size==H5T_VARIABLE) { + H5T_t *base = NULL; /* base data type */ + H5T_cset_t tmp_cset; /* Temp. cset info */ + H5T_str_t tmp_strpad; /* Temp. strpad info */ - /* Increase table sizes */ - if (dt->u.enumer.nmembs >= dt->u.enumer.nalloc) { - int n = MAX(32, 2*dt->u.enumer.nalloc); - if (NULL==(names=H5MM_realloc(dt->u.enumer.name, n*sizeof(char*)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - dt->u.enumer.name = names; - - if (NULL==(values=H5MM_realloc(dt->u.enumer.value, n*dt->size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - dt->u.enumer.value = values; - dt->u.enumer.nalloc = n; - } + /* Get a copy of unsigned char type as the base/parent type */ + if (NULL==(base=H5I_object(H5T_NATIVE_UCHAR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid base datatype"); + dt->parent=H5T_copy(base,H5T_COPY_ALL); - /* Insert new member at end of member arrays */ - dt->u.enumer.sorted = H5T_SORT_NONE; - i = dt->u.enumer.nmembs++; - dt->u.enumer.name[i] = H5MM_xstrdup(name); - HDmemcpy(dt->u.enumer.value+i*dt->size, value, dt->size); + /* change this datatype into a VL string */ + dt->type = H5T_VLEN; -done: - FUNC_LEAVE_NOAPI(ret_value); -} + /* + * Force conversions (i.e. memory to memory conversions + * should duplicate data, not point to the same VL strings) + */ + dt->force_conv = TRUE; - -/*------------------------------------------------------------------------- - * Function: H5T_enum_nameof - * - * Purpose: Finds the symbol name that corresponds the the specified - * VALUE of an enumeration data type DT. At most SIZE characters - * of the symbol name are copied into the NAME buffer. If the - * entire symbol name and null terminator do not fit in the NAME - * buffer then as many characters as possible are copied and the - * function returns failure. - * - * If NAME is the null pointer and SIZE is zero then enough - * space is allocated to hold the result and a pointer to that - * memory is returned. - * - * Return: Success: Pointer to NAME - * - * Failure: NULL, name[0] is set to null. - * - * Programmer: Robb Matzke - * Monday, January 4, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -char * -H5T_enum_nameof(H5T_t *dt, void *value, char *name/*out*/, size_t size) -{ - int lt, md, rt; /*indices for binary search */ - int cmp=(-1); /*comparison result */ - char *ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(H5T_enum_nameof, NULL); + /* Before we mess with the info in the union, extract the + * values we need */ + tmp_cset=dt->u.atomic.u.s.cset; + tmp_strpad=dt->u.atomic.u.s.pad; - /* Check args */ - assert(dt && H5T_ENUM==dt->type); - assert(value); - assert(name || 0==size); - if (name && size>0) *name = '\0'; - - /* Sanity check */ - if (dt->u.enumer.nmembs == 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "datatype has no members"); - - /* Do a binary search over the values to find the correct one */ - H5T_sort_value(dt, NULL); - lt = 0; - rt = dt->u.enumer.nmembs; - md = -1; - - while (ltu.enumer.value+md*dt->size, dt->size); - if (cmp<0) { - rt = md; - } else if (cmp>0) { - lt = md+1; - } else { - break; - } - } - /* Value was not yet defined. This fixes bug # 774, 2002/06/05 EIP */ - if (cmp!=0) - HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "value is currently not defined"); + /* This is a string, not a sequence */ + dt->u.vlen.type = H5T_VLEN_STRING; - /* Save result name */ - if (!name && NULL==(name=H5MM_malloc(HDstrlen(dt->u.enumer.name[md])+1))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - HDstrncpy(name, dt->u.enumer.name[md], size); - if (HDstrlen(dt->u.enumer.name[md])>=size) - HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, NULL, "name has been truncated"); + /* Set character set and padding information */ + dt->u.vlen.cset = tmp_cset; + dt->u.vlen.pad = tmp_strpad; - /* Set return value */ - ret_value=name; + /* Set up VL information */ + if (H5T_vlen_mark(dt, NULL, H5T_VLEN_MEMORY)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid VL location"); + + } else { + prec = 8 * size; + offset = 0; + } /* end else */ + break; + + case H5T_FLOAT: + /* + * The sign, mantissa, and exponent fields should be adjusted + * first when decreasing the size of a floating point type. + */ + if (dt->u.atomic.u.f.sign >= prec || + dt->u.atomic.u.f.epos + dt->u.atomic.u.f.esize > prec || + dt->u.atomic.u.f.mpos + dt->u.atomic.u.f.msize > prec) { + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "adjust sign, mantissa, and exponent fields first"); + } + break; + + default: + assert("not implemented yet" && 0); + } + /* Commit */ + if(dt->type!=H5T_VLEN) { + dt->size = size; + if (H5T_is_atomic(dt)) { + dt->u.atomic.offset = offset; + dt->u.atomic.prec = prec; + } + } + } + done: FUNC_LEAVE_NOAPI(ret_value); } /*------------------------------------------------------------------------- - * Function: H5T_enum_valueof + * Function: H5T_get_size * - * Purpose: Finds the value that corresponds the the specified symbol - * NAME of an enumeration data type DT and copy it to the VALUE - * result buffer. The VALUE should be allocated by the caller to - * be large enough for the result. + * Purpose: Determines the total size of a data type in bytes. * - * Return: Success: Non-negative, value stored in VALUE. + * Return: Success: Size of the data type in bytes. The size of + * the data type is the size of an instance of + * that data type. * - * Failure: Negative, VALUE is undefined. + * Failure: 0 (valid data types are never zero size) * * Programmer: Robb Matzke - * Monday, January 4, 1999 + * Tuesday, December 9, 1997 * * Modifications: * *------------------------------------------------------------------------- */ -herr_t -H5T_enum_valueof(H5T_t *dt, const char *name, void *value/*out*/) +size_t +H5T_get_size(const H5T_t *dt) { - int lt, md, rt; /*indices for binary search */ - int cmp=(-1); /*comparison result */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5T_enum_valueof, FAIL); - - /* Check args */ - assert(dt && H5T_ENUM==dt->type); - assert(name && *name); - assert(value); - - /* Sanity check */ - if (dt->u.enumer.nmembs == 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, FAIL, "datatype has no members"); - - /* Do a binary search over the names to find the correct one */ - H5T_sort_name(dt, NULL); - lt = 0; - rt = dt->u.enumer.nmembs; - md = -1; - - while (ltu.enumer.name[md]); - if (cmp<0) { - rt = md; - } else if (cmp>0) { - lt = md+1; - } else { - break; - } - } - /* Value was not yet defined. This fixes bug # 774, 2002/06/05 EIP */ - if (cmp!=0) - HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, FAIL, "string doesn't exist in the enumeration type"); + /* Use FUNC_ENTER_NOINIT here to avoid performance issues */ + FUNC_ENTER_NOINIT(H5T_get_size); - HDmemcpy(value, dt->u.enumer.value+md*dt->size, dt->size); + /* check args */ + assert(dt); -done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(dt->size); } @@ -8737,291 +4974,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5Tarray_create - * - * Purpose: Create a new array data type based on the specified BASE_TYPE. - * The type is an array with NDIMS dimensionality and the size of the - * array is DIMS. The total member size should be relatively small. - * PERM is currently unimplemented and unused, but is designed to contain - * the dimension permutation from C order. - * Array datatypes are currently limited to H5S_MAX_RANK number of - * dimensions and must have the number of dimensions set greater than - * 0. (i.e. 0 > ndims <= H5S_MAX_RANK) All dimensions sizes must be greater - * than 0 also. - * - * Return: Success: ID of new array data type - * - * Failure: Negative - * - * Programmer: Quincey Koziol - * Thursday, Oct 26, 2000 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -hid_t -H5Tarray_create(hid_t base_id, int ndims, const hsize_t dim[/* ndims */], - const int perm[/* ndims */]) -{ - H5T_t *base = NULL; /* base data type */ - H5T_t *dt = NULL; /* new array data type */ - int i; /* local index variable */ - hid_t ret_value; /* return value */ - - FUNC_ENTER_API(H5Tarray_create, FAIL); - H5TRACE4("i","iIs*h*Is",base_id,ndims,dim,perm); - - /* Check args */ - if (ndims<1 || ndims>H5S_MAX_RANK) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid dimensionality"); - if (ndims>0 && !dim) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no dimensions specified"); - for(i=0; i0)) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "zero-sized dimension specified"); - if (NULL==(base=H5I_object_verify(base_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype"); - - /* Create the actual array datatype */ - if ((dt=H5T_array_create(base,ndims,dim,perm))==NULL) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to create datatype"); - - /* Atomize the type */ - if ((ret_value=H5I_register(H5I_DATATYPE, dt))<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype"); - -done: - FUNC_LEAVE_API(ret_value); -} /* end H5Tarray_create */ - - -/*------------------------------------------------------------------------- - * Function: H5T_array_create - * - * Purpose: Internal routine to create a new array data type based on the - * specified BASE_TYPE. The type is an array with NDIMS dimensionality - * and the size of the array is DIMS. PERM is currently unimplemented - * and unused, but is designed to contain the dimension permutation from - * C order. Array datatypes are currently limited to H5S_MAX_RANK number - * of * dimensions. - * - * Return: Success: ID of new array data type - * - * Failure: Negative - * - * Programmer: Quincey Koziol - * Thursday, Oct 26, 2000 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5T_t * -H5T_array_create(H5T_t *base, int ndims, const hsize_t dim[/* ndims */], - const int perm[/* ndims */]) -{ - H5T_t *ret_value = NULL; /*new array data type */ - int i; /* local index variable */ - - FUNC_ENTER_NOAPI(H5T_array_create, NULL); - - assert(base); - assert(ndims>0 && ndims<=H5S_MAX_RANK); - assert(dim); - - /* Build new type */ - if (NULL==(ret_value = H5FL_CALLOC(H5T_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); - - ret_value->ent.header = HADDR_UNDEF; - ret_value->type = H5T_ARRAY; - - /* Copy the base type of the array */ - ret_value->parent = H5T_copy(base, H5T_COPY_ALL); - - /* Set the array parameters */ - ret_value->u.array.ndims = ndims; - - /* Copy the array dimensions & compute the # of elements in the array */ - for(i=0, ret_value->u.array.nelem=1; iu.array.dim[i],dim[i],hsize_t,size_t); - ret_value->u.array.nelem *= (size_t)dim[i]; - } /* end for */ - - /* Copy the dimension permutations */ - for(i=0; iu.array.perm[i] = perm ? perm[i] : i; - - /* Set the array's size (number of elements * element datatype's size) */ - ret_value->size = ret_value->parent->size * ret_value->u.array.nelem; - - /* - * Set the "force conversion" flag if a VL base datatype is used or - * or if any components of the base datatype are VL types. - */ - if(base->type==H5T_VLEN || base->force_conv==TRUE) - ret_value->force_conv=TRUE; - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5T_array_create */ - - -/*------------------------------------------------------------------------- - * Function: H5Tget_array_ndims - * - * Purpose: Query the number of dimensions for an array datatype. - * - * Return: Success: Number of dimensions of the array datatype - * Failure: Negative - * - * Programmer: Quincey Koziol - * Monday, November 6, 2000 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -int -H5Tget_array_ndims(hid_t type_id) -{ - H5T_t *dt = NULL; /* pointer to array data type */ - int ret_value; /* return value */ - - FUNC_ENTER_API(H5Tget_array_ndims, FAIL); - H5TRACE1("Is","i",type_id); - - /* Check args */ - if (NULL==(dt=H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); - if(dt->type!=H5T_ARRAY) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an array datatype"); - - /* Retrieve the number of dimensions */ - ret_value = H5T_get_array_ndims(dt); - -done: - FUNC_LEAVE_API(ret_value); -} /* end H5Tget_array_ndims */ - - -/*------------------------------------------------------------------------- - * Function: H5T_get_array_ndims - * - * Purpose: Private function for H5T_get_array_ndims. Query the number - * of dimensions for an array datatype. - * - * Return: Success: Number of dimensions of the array datatype - * Failure: Negative - * - * Programmer: Raymond Lu - * October 10, 2002 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -int -H5T_get_array_ndims(H5T_t *dt) -{ - int ret_value; /* return value */ - - FUNC_ENTER_NOAPI(H5T_get_array_ndims, FAIL); - - assert(dt); - assert(dt->type==H5T_ARRAY); - - /* Retrieve the number of dimensions */ - ret_value=dt->u.array.ndims; - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5T_get_array_ndims */ - - -/*------------------------------------------------------------------------- - * Function: H5Tget_array_dims - * - * Purpose: Query the sizes of dimensions for an array datatype. - * - * Return: Success: Non-negative - * Failure: Negative - * - * Programmer: Quincey Koziol - * Monday, November 6, 2000 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tget_array_dims(hid_t type_id, hsize_t dims[], int perm[]) -{ - H5T_t *dt = NULL; /* pointer to array data type */ - herr_t ret_value = SUCCEED; /* return value */ - - FUNC_ENTER_API(H5Tget_array_dims, FAIL); - H5TRACE3("e","i*h*Is",type_id,dims,perm); - - /* Check args */ - if (NULL==(dt=H5I_object_verify(type_id,H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); - if(dt->type!=H5T_ARRAY) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an array datatype"); - - /* Retrieve the sizes of the dimensions */ - if(H5T_get_array_dims(dt, dims, perm)<0) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unable to get dimension sizes"); -done: - FUNC_LEAVE_API(ret_value); -} /* end H5Tget_array_dims */ - - -/*------------------------------------------------------------------------- - * Function: H5T_get_array_dims - * - * Purpose: Private function for H5T_get_array_dims. Query the sizes - * of dimensions for an array datatype. - * - * Return: Success: Non-negative - * Failure: Negative - * - * Programmer: Raymond Lu - * October 10, 2002 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5T_get_array_dims(H5T_t *dt, hsize_t dims[], int perm[]) -{ - herr_t ret_value = SUCCEED; /* return value */ - int i; /* Local index variable */ - - FUNC_ENTER_NOAPI(H5T_get_array_dims, FAIL); - - assert(dt); - assert(dt->type==H5T_ARRAY); - - /* Retrieve the sizes of the dimensions */ - if(dims) - for(i=0; iu.array.ndims; i++) - dims[i]=dt->u.array.dim[i]; - - /* Retrieve the dimension permutations */ - if(perm) - for(i=0; iu.array.ndims; i++) - perm[i]=dt->u.array.perm[i]; - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5T_get_array_dims */ - - - -/*------------------------------------------------------------------------- * Function: H5T_is_sensible * * Purpose: Determines if a data type is sensible to store on disk diff --git a/src/H5Tarray.c b/src/H5Tarray.c new file mode 100644 index 0000000..a9b2d10 --- /dev/null +++ b/src/H5Tarray.c @@ -0,0 +1,343 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains the functionality for array datatypes in + * the H5T interface. + */ + +#define H5T_PACKAGE /*suppress error about including H5Tpkg */ + +#include "H5private.h" /*generic functions */ +#include "H5Eprivate.h" /*error handling */ +#include "H5FLprivate.h" /*Free Lists */ +#include "H5Iprivate.h" /*ID functions */ +#include "H5Tpkg.h" /*data-type functions */ + +#define PABLO_MASK H5Tarray_mask + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT H5T_init_array_interface +static herr_t H5T_init_array_interface(void); + +/* Declare extern the free list for H5T_t's */ +H5FL_EXTERN(H5T_t); + + +/*-------------------------------------------------------------------------- +NAME + H5T_init_array_interface -- Initialize interface-specific information +USAGE + herr_t H5T_init_array_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5T_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5T_init_array_interface(void) +{ + FUNC_ENTER_NOINIT(H5T_init_array_interface); + + FUNC_LEAVE_NOAPI(H5T_init_interface()); +} /* H5T_init_array_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tarray_create + * + * Purpose: Create a new array data type based on the specified BASE_TYPE. + * The type is an array with NDIMS dimensionality and the size of the + * array is DIMS. The total member size should be relatively small. + * PERM is currently unimplemented and unused, but is designed to contain + * the dimension permutation from C order. + * Array datatypes are currently limited to H5S_MAX_RANK number of + * dimensions and must have the number of dimensions set greater than + * 0. (i.e. 0 > ndims <= H5S_MAX_RANK) All dimensions sizes must be greater + * than 0 also. + * + * Return: Success: ID of new array data type + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, Oct 26, 2000 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t +H5Tarray_create(hid_t base_id, int ndims, const hsize_t dim[/* ndims */], + const int perm[/* ndims */]) +{ + H5T_t *base = NULL; /* base data type */ + H5T_t *dt = NULL; /* new array data type */ + int i; /* local index variable */ + hid_t ret_value; /* return value */ + + FUNC_ENTER_API(H5Tarray_create, FAIL); + H5TRACE4("i","iIs*h*Is",base_id,ndims,dim,perm); + + /* Check args */ + if (ndims<1 || ndims>H5S_MAX_RANK) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid dimensionality"); + if (ndims>0 && !dim) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no dimensions specified"); + for(i=0; i0)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "zero-sized dimension specified"); + if (NULL==(base=H5I_object_verify(base_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype"); + + /* Create the actual array datatype */ + if ((dt=H5T_array_create(base,ndims,dim,perm))==NULL) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to create datatype"); + + /* Atomize the type */ + if ((ret_value=H5I_register(H5I_DATATYPE, dt))<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype"); + +done: + FUNC_LEAVE_API(ret_value); +} /* end H5Tarray_create */ + + +/*------------------------------------------------------------------------- + * Function: H5T_array_create + * + * Purpose: Internal routine to create a new array data type based on the + * specified BASE_TYPE. The type is an array with NDIMS dimensionality + * and the size of the array is DIMS. PERM is currently unimplemented + * and unused, but is designed to contain the dimension permutation from + * C order. Array datatypes are currently limited to H5S_MAX_RANK number + * of * dimensions. + * + * Return: Success: ID of new array data type + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, Oct 26, 2000 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5T_t * +H5T_array_create(H5T_t *base, int ndims, const hsize_t dim[/* ndims */], + const int perm[/* ndims */]) +{ + H5T_t *ret_value = NULL; /*new array data type */ + int i; /* local index variable */ + + FUNC_ENTER_NOAPI(H5T_array_create, NULL); + + assert(base); + assert(ndims>0 && ndims<=H5S_MAX_RANK); + assert(dim); + + /* Build new type */ + if (NULL==(ret_value = H5FL_CALLOC(H5T_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + + ret_value->ent.header = HADDR_UNDEF; + ret_value->type = H5T_ARRAY; + + /* Copy the base type of the array */ + ret_value->parent = H5T_copy(base, H5T_COPY_ALL); + + /* Set the array parameters */ + ret_value->u.array.ndims = ndims; + + /* Copy the array dimensions & compute the # of elements in the array */ + for(i=0, ret_value->u.array.nelem=1; iu.array.dim[i],dim[i],hsize_t,size_t); + ret_value->u.array.nelem *= (size_t)dim[i]; + } /* end for */ + + /* Copy the dimension permutations */ + for(i=0; iu.array.perm[i] = perm ? perm[i] : i; + + /* Set the array's size (number of elements * element datatype's size) */ + ret_value->size = ret_value->parent->size * ret_value->u.array.nelem; + + /* + * Set the "force conversion" flag if a VL base datatype is used or + * or if any components of the base datatype are VL types. + */ + if(base->type==H5T_VLEN || base->force_conv==TRUE) + ret_value->force_conv=TRUE; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5T_array_create */ + + +/*------------------------------------------------------------------------- + * Function: H5Tget_array_ndims + * + * Purpose: Query the number of dimensions for an array datatype. + * + * Return: Success: Number of dimensions of the array datatype + * Failure: Negative + * + * Programmer: Quincey Koziol + * Monday, November 6, 2000 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +H5Tget_array_ndims(hid_t type_id) +{ + H5T_t *dt = NULL; /* pointer to array data type */ + int ret_value; /* return value */ + + FUNC_ENTER_API(H5Tget_array_ndims, FAIL); + H5TRACE1("Is","i",type_id); + + /* Check args */ + if (NULL==(dt=H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); + if(dt->type!=H5T_ARRAY) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an array datatype"); + + /* Retrieve the number of dimensions */ + ret_value = H5T_get_array_ndims(dt); + +done: + FUNC_LEAVE_API(ret_value); +} /* end H5Tget_array_ndims */ + + +/*------------------------------------------------------------------------- + * Function: H5T_get_array_ndims + * + * Purpose: Private function for H5T_get_array_ndims. Query the number + * of dimensions for an array datatype. + * + * Return: Success: Number of dimensions of the array datatype + * Failure: Negative + * + * Programmer: Raymond Lu + * October 10, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +H5T_get_array_ndims(H5T_t *dt) +{ + int ret_value; /* return value */ + + FUNC_ENTER_NOAPI(H5T_get_array_ndims, FAIL); + + assert(dt); + assert(dt->type==H5T_ARRAY); + + /* Retrieve the number of dimensions */ + ret_value=dt->u.array.ndims; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5T_get_array_ndims */ + + +/*------------------------------------------------------------------------- + * Function: H5Tget_array_dims + * + * Purpose: Query the sizes of dimensions for an array datatype. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Quincey Koziol + * Monday, November 6, 2000 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tget_array_dims(hid_t type_id, hsize_t dims[], int perm[]) +{ + H5T_t *dt = NULL; /* pointer to array data type */ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_API(H5Tget_array_dims, FAIL); + H5TRACE3("e","i*h*Is",type_id,dims,perm); + + /* Check args */ + if (NULL==(dt=H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); + if(dt->type!=H5T_ARRAY) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an array datatype"); + + /* Retrieve the sizes of the dimensions */ + if(H5T_get_array_dims(dt, dims, perm)<0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unable to get dimension sizes"); +done: + FUNC_LEAVE_API(ret_value); +} /* end H5Tget_array_dims */ + + +/*------------------------------------------------------------------------- + * Function: H5T_get_array_dims + * + * Purpose: Private function for H5T_get_array_dims. Query the sizes + * of dimensions for an array datatype. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Raymond Lu + * October 10, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5T_get_array_dims(H5T_t *dt, hsize_t dims[], int perm[]) +{ + herr_t ret_value = SUCCEED; /* return value */ + int i; /* Local index variable */ + + FUNC_ENTER_NOAPI(H5T_get_array_dims, FAIL); + + assert(dt); + assert(dt->type==H5T_ARRAY); + + /* Retrieve the sizes of the dimensions */ + if(dims) + for(i=0; iu.array.ndims; i++) + dims[i]=dt->u.array.dim[i]; + + /* Retrieve the dimension permutations */ + if(perm) + for(i=0; iu.array.ndims; i++) + perm[i]=dt->u.array.perm[i]; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5T_get_array_dims */ + diff --git a/src/H5Tbit.c b/src/H5Tbit.c index ad716d3..ece0d51 100644 --- a/src/H5Tbit.c +++ b/src/H5Tbit.c @@ -1,23 +1,33 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + /* - * Copyright (C) 1998-2001 NCSA - * All rights reserved. - * - * Programmer: Robb Matzke - * Wednesday, June 10, 1998 - * - * Purpose: Operations on bit vectors. A bit vector is an array of bytes + * Module Info: Operations on bit vectors. A bit vector is an array of bytes * with the least-significant bits in the first byte. That is, * the bytes are in little-endian order. */ + #define H5T_PACKAGE /*suppress error about including H5Tpkg */ -#include "H5private.h" -#include "H5Eprivate.h" -#include "H5Iprivate.h" -#include "H5Tpkg.h" +#include "H5private.h" /*generic functions */ +#include "H5Eprivate.h" /*error handling */ +#include "H5Iprivate.h" /*ID functions */ +#include "H5Tpkg.h" /*data-type functions */ -/* Interface initialization */ #define PABLO_MASK H5Tbit_mask + +/* Interface initialization */ static int interface_initialize_g = 0; #define INTERFACE_INIT NULL diff --git a/src/H5Tcommit.c b/src/H5Tcommit.c new file mode 100644 index 0000000..6619392 --- /dev/null +++ b/src/H5Tcommit.c @@ -0,0 +1,206 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains the functionality for committing datatypes + * to a file for the H5T interface. + */ + +#define H5T_PACKAGE /*suppress error about including H5Tpkg */ + +#include "H5private.h" /*generic functions */ +#include "H5Eprivate.h" /*error handling */ +#include "H5Iprivate.h" /*ID functions */ +#include "H5Tpkg.h" /*data-type functions */ + +#define PABLO_MASK H5Tcommit_mask + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT H5T_init_commit_interface +static herr_t H5T_init_commit_interface(void); + + +/* Static local functions */ +static herr_t H5T_commit(H5G_entry_t *loc, const char *name, H5T_t *type, hid_t dxpl_id); + + +/*-------------------------------------------------------------------------- +NAME + H5T_init_commit_interface -- Initialize interface-specific information +USAGE + herr_t H5T_init_commit_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5T_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5T_init_commit_interface(void) +{ + FUNC_ENTER_NOINIT(H5T_init_commit_interface); + + FUNC_LEAVE_NOAPI(H5T_init_interface()); +} /* H5T_init_commit_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tcommit + * + * Purpose: Save a transient data type to a file and turn the type handle + * into a named, immutable type. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Monday, June 1, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tcommit(hid_t loc_id, const char *name, hid_t type_id) +{ + H5G_entry_t *loc = NULL; + H5T_t *type = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tcommit, FAIL); + H5TRACE3("e","isi",loc_id,name,type_id); + + /* Check arguments */ + if (NULL==(loc=H5G_loc (loc_id))) + HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); + if (!name || !*name) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "no name"); + if (NULL==(type=H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + + /* Commit the type */ + if (H5T_commit (loc, name, type, H5AC_dxpl_id)<0) + HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to commit data type"); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_commit + * + * Purpose: Commit a type, giving it a name and causing it to become + * immutable. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Monday, June 1, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T_commit (H5G_entry_t *loc, const char *name, H5T_t *type, hid_t dxpl_id) +{ + H5F_t *file = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5T_commit, FAIL); + + assert (loc); + assert (name && *name); + assert (type); + + /* + * Check arguments. We cannot commit an immutable type because H5Tclose() + * normally fails on such types (try H5Tclose(H5T_NATIVE_INT)) but closing + * a named type should always succeed. + */ + if (H5T_STATE_NAMED==type->state || H5T_STATE_OPEN==type->state) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "data type is already committed"); + if (H5T_STATE_IMMUTABLE==type->state) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "data type is immutable"); + + /* Check for a "sensible" datatype to store on disk */ + if(H5T_is_sensible(type)!=TRUE) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "datatype is not sensible"); + + /* Find the insertion file */ + if (NULL==(file=H5G_insertion_file(loc, name, dxpl_id))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to find insertion point"); + + /* + * Create the object header and open it for write access. Insert the data + * type message and then give the object header a name. + */ + if (H5O_create (file, dxpl_id, 64, &(type->ent))<0) + HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create data type object header"); + if (H5O_modify (&(type->ent), H5O_DTYPE, 0, H5O_FLAG_CONSTANT, 1, type, dxpl_id)<0) + HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to update type header message"); + if (H5G_insert (loc, name, &(type->ent), dxpl_id)<0) + HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to name data type"); + type->state = H5T_STATE_OPEN; + +done: + if (ret_value<0) { + if ((type->state==H5T_STATE_TRANSIENT || type->state==H5T_STATE_RDONLY) && H5F_addr_defined(type->ent.header)) { + H5O_close(&(type->ent)); + type->ent.header = HADDR_UNDEF; + } + } + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tcommitted + * + * Purpose: Determines if a data type is committed or not. + * + * Return: Success: TRUE if committed, FALSE otherwise. + * + * Failure: Negative + * + * Programmer: Robb Matzke + * Thursday, June 4, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +htri_t +H5Tcommitted(hid_t type_id) +{ + H5T_t *type = NULL; + htri_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5Tcommitted, FAIL); + H5TRACE1("b","i",type_id); + + /* Check arguments */ + if (NULL==(type=H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + + /* Set return value */ + ret_value= (H5T_STATE_OPEN==type->state || H5T_STATE_NAMED==type->state); + +done: + FUNC_LEAVE_API(ret_value); +} + diff --git a/src/H5Tcompound.c b/src/H5Tcompound.c new file mode 100644 index 0000000..8326ffe --- /dev/null +++ b/src/H5Tcompound.c @@ -0,0 +1,512 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains the functionality for compound datatypes + * in the H5T interface. + */ + +#define H5T_PACKAGE /*suppress error about including H5Tpkg */ + +#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 */ + +#define PABLO_MASK H5Tcompound_mask + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT H5T_init_compound_interface +static herr_t H5T_init_compound_interface(void); + +/* Local macros */ +#define H5T_COMPND_INC 64 /*typical max numb of members per struct */ + +/* Static local functions */ +static size_t H5T_get_member_offset(H5T_t *dt, int membno); +static herr_t H5T_pack(H5T_t *dt); + + +/*-------------------------------------------------------------------------- +NAME + H5T_init_compound_interface -- Initialize interface-specific information +USAGE + herr_t H5T_init_compound_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5T_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5T_init_compound_interface(void) +{ + FUNC_ENTER_NOINIT(H5T_init_compound_interface); + + FUNC_LEAVE_NOAPI(H5T_init_interface()); +} /* H5T_init_compound_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tget_member_offset + * + * Purpose: Returns the byte offset of the beginning of a member with + * respect to the beginning of the compound data type datum. + * + * Return: Success: Byte offset. + * + * Failure: Zero. Zero is a valid offset, but this + * function will fail only if a call to + * H5Tget_member_dims() fails with the same + * arguments. + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +size_t +H5Tget_member_offset(hid_t type_id, int membno) +{ + H5T_t *dt = NULL; + size_t ret_value; + + FUNC_ENTER_API(H5Tget_member_offset, 0); + H5TRACE2("z","iIs",type_id,membno); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)) || H5T_COMPOUND != dt->type) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a compound data type"); + if (membno < 0 || membno >= dt->u.compnd.nmembs) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid member number"); + + /* Value */ + ret_value = H5T_get_member_offset(dt, membno); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_get_member_offset + * + * Purpose: Private function for H5Tget_member_offset. Returns the byte + * offset of the beginning of a member with respect to the i + * beginning of the compound data type datum. + * + * Return: Success: Byte offset. + * + * Failure: Zero. Zero is a valid offset, but this + * function will fail only if a call to + * H5Tget_member_dims() fails with the same + * arguments. + * + * Programmer: Raymond Lu + * October 8, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5T_get_member_offset(H5T_t *dt, int membno) +{ + size_t ret_value; + + FUNC_ENTER_NOAPI(H5T_get_member_offset, 0); + + assert(dt); + assert(membno >= 0 && membno < dt->u.compnd.nmembs); + + /* Value */ + ret_value = dt->u.compnd.memb[membno].offset; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tget_member_class + * + * Purpose: Returns the datatype class of a member of a compound datatype. + * + * Return: Success: Non-negative + * + * Failure: H5T_NO_CLASS + * + * Programmer: Quincey Koziol + * Thursday, November 9, 2000 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5T_class_t +H5Tget_member_class(hid_t type_id, int membno) +{ + H5T_t *dt = NULL; + H5T_class_t ret_value; + + FUNC_ENTER_API(H5Tget_member_class, H5T_NO_CLASS); + H5TRACE2("Tt","iIs",type_id,membno); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)) || H5T_COMPOUND != dt->type) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a compound data type"); + if (membno < 0 || membno >= dt->u.compnd.nmembs) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5T_NO_CLASS, "invalid member number"); + + /* Value */ + ret_value = dt->u.compnd.memb[membno].type->type; + +done: + FUNC_LEAVE_API(ret_value); +} /* end H5Tget_member_class() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tget_member_type + * + * Purpose: Returns the data type of the specified member. The caller + * should invoke H5Tclose() to release resources associated with + * the type. + * + * Return: Success: An OID of a copy of the member data type; + * modifying the returned data type does not + * modify the member type. + * + * Failure: Negative + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * + * Robb Matzke, 4 Jun 1998 + * If the member type is a named type then this function returns a + * handle to the re-opened named type. + * + *------------------------------------------------------------------------- + */ +hid_t +H5Tget_member_type(hid_t type_id, int membno) +{ + H5T_t *dt = NULL, *memb_dt = NULL; + hid_t ret_value; + + FUNC_ENTER_API(H5Tget_member_type, FAIL); + H5TRACE2("i","iIs",type_id,membno); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)) || H5T_COMPOUND != dt->type) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound data type"); + if (membno < 0 || membno >= dt->u.compnd.nmembs) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid member number"); + if ((memb_dt=H5T_get_member_type(dt, membno))==NULL) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to retrieve member type"); + if ((ret_value = H5I_register(H5I_DATATYPE, memb_dt)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable register data type atom"); + +done: + if(ret_value<0) { + if(memb_dt!=NULL) + H5T_close(memb_dt); + } /* end if */ + + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_get_member_type + * + * Purpose: Private function for H5Tget_member_type. Returns the data + * type of the specified member. + * + * Return: Success: A copy of the member data type; + * modifying the returned data type does not + * modify the member type. + * + * Failure: NULL + * + * Programmer: Raymond Lu + * October 8, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5T_t * +H5T_get_member_type(H5T_t *dt, int membno) +{ + H5T_t *ret_value = NULL; + + FUNC_ENTER_NOAPI(H5T_get_member_type, NULL); + + assert(dt); + assert(membno >=0 && membno < dt->u.compnd.nmembs); + + /* Copy data type into an atom */ + if (NULL == (ret_value = H5T_copy(dt->u.compnd.memb[membno].type, H5T_COPY_REOPEN))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy member data type"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tinsert + * + * 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. + * + * Return: Success: Non-negative, the PARENT_ID compound data + * type is modified to include a copy of the + * member type MEMBER_ID. + * + * Failure: Negative + * + * Errors: + * + * Programmer: Robb Matzke + * Monday, December 8, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tinsert(hid_t parent_id, const char *name, size_t offset, hid_t member_id) +{ + H5T_t *parent = NULL; /*the compound parent data type */ + H5T_t *member = NULL; /*the atomic member type */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tinsert, FAIL); + H5TRACE4("e","iszi",parent_id,name,offset,member_id); + + /* Check args */ + if (parent_id==member_id) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "can't insert compound datatype within itself"); + if (NULL == (parent = H5I_object_verify(parent_id,H5I_DATATYPE)) || H5T_COMPOUND != parent->type) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound data type"); + if (H5T_STATE_TRANSIENT!=parent->state) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent type read-only"); + if (!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no member name"); + if (NULL == (member = H5I_object_verify(member_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + + /* Insert */ + if (H5T_insert(parent, name, offset, member) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "unable to insert member"); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tpack + * + * Purpose: Recursively removes padding from within a compound data type + * to make it more efficient (space-wise) to store that data. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tpack(hid_t type_id) +{ + H5T_t *dt = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tpack, FAIL); + H5TRACE1("e","i",type_id); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)) || H5T_COMPOUND != dt->type) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound data type"); + if (H5T_STATE_TRANSIENT!=dt->state) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "data type is read-only"); + + /* Pack */ + if (H5T_pack(dt) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack compound data type"); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_insert + * + * Purpose: Adds a new MEMBER to the compound data type PARENT. The new + * member will have a NAME that is unique within PARENT and an + * instance of PARENT will have the member begin at byte offset + * OFFSET from the beginning. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Monday, December 8, 1997 + * + * Modifications: + * Took out arrayness parameters - QAK, 10/6/00 + * + *------------------------------------------------------------------------- + */ +herr_t +H5T_insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member) +{ + int idx, i; + size_t total_size; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5T_insert, FAIL); + + /* check args */ + assert(parent && H5T_COMPOUND == parent->type); + assert(H5T_STATE_TRANSIENT==parent->state); + assert(member); + assert(name && *name); + + /* Does NAME already exist in PARENT? */ + for (i=0; iu.compnd.nmembs; i++) { + if (!HDstrcmp(parent->u.compnd.memb[i].name, name)) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member name is not unique"); + } + + /* Does the new member overlap any existing member ? */ + total_size=member->size; + for (i=0; iu.compnd.nmembs; i++) { + if ((offset <= 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].size > offset)) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member overlaps with another member"); + } + + /* Does the new member overlap the end of the compound type? */ + if(offset+total_size>parent->size) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member extends past end of compound type"); + + /* Increase member array if necessary */ + if (parent->u.compnd.nmembs >= parent->u.compnd.nalloc) { + size_t na = parent->u.compnd.nalloc + H5T_COMPND_INC; + H5T_cmemb_t *x = H5MM_realloc (parent->u.compnd.memb, + na * sizeof(H5T_cmemb_t)); + + if (!x) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + parent->u.compnd.nalloc = (int)na; + parent->u.compnd.memb = x; + } + + /* Add member to end of member array */ + 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].type = H5T_copy (member, H5T_COPY_ALL); + + parent->u.compnd.sorted = H5T_SORT_NONE; + parent->u.compnd.nmembs++; + + /* + * Set the "force conversion" flag if VL datatype fields exist in this type + * or any component types + */ + if(member->type==H5T_VLEN || member->force_conv==TRUE) + parent->force_conv=TRUE; + + /* Set the flag for this compound type, if the field is an array */ + if(member->type==H5T_ARRAY) + parent->u.compnd.has_array=TRUE; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_pack + * + * Purpose: Recursively packs a compound data type by removing padding + * bytes. This is done in place (that is, destructively). + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T_pack(H5T_t *dt) +{ + int i; + size_t offset; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5T_pack, FAIL); + + assert(dt); + + if (H5T_COMPOUND == dt->type) { + assert(H5T_STATE_TRANSIENT==dt->state); + + /* Recursively pack the members */ + for (i=0; iu.compnd.nmembs; i++) { + if (H5T_pack(dt->u.compnd.memb[i].type) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack part of a compound data type"); + } + + /* Remove padding between members */ + H5T_sort_value(dt, NULL); + for (i=0, offset=0; iu.compnd.nmembs; i++) { + dt->u.compnd.memb[i].offset = offset; + offset += dt->u.compnd.memb[i].size; + } + + /* Change total size */ + dt->size = MAX(1, offset); + } + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + diff --git a/src/H5Tconv.c b/src/H5Tconv.c index c2a9691..5f195d1 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -1,21 +1,32 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + /* - * Copyright (C) 1998-2001 Spizella Software - * All rights reserved. - * - * Programmer: Robb Matzke - * Tuesday, January 13, 1998 - * - * Purpose: Data type conversions. + * Module Info: Data type conversions for the H5T interface. */ + #define H5T_PACKAGE /*suppress error about including H5Tpkg */ -#define PABLO_MASK H5Tconv_mask -#include "H5Iprivate.h" -#include "H5Eprivate.h" +#include "H5private.h" /*generic functions */ +#include "H5Eprivate.h" /*error handling */ #include "H5FLprivate.h" /*Free Lists */ -#include "H5MMprivate.h" -#include "H5Pprivate.h" -#include "H5Tpkg.h" +#include "H5Iprivate.h" /*ID functions */ +#include "H5MMprivate.h" /*memory management */ +#include "H5Pprivate.h" /* Property Lists */ +#include "H5Tpkg.h" /*data-type functions */ + +#define PABLO_MASK H5Tconv_mask /* Conversion data for H5T_conv_struct() */ typedef struct H5T_conv_struct_t { diff --git a/src/H5Tcset.c b/src/H5Tcset.c new file mode 100644 index 0000000..0ddfe23 --- /dev/null +++ b/src/H5Tcset.c @@ -0,0 +1,159 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains the functionality for setting & querying + * the character set (cset) for the H5T interface. + */ + +#define H5T_PACKAGE /*suppress error about including H5Tpkg */ + +#include "H5private.h" /*generic functions */ +#include "H5Eprivate.h" /*error handling */ +#include "H5Iprivate.h" /*ID functions */ +#include "H5Tpkg.h" /*data-type functions */ + +#define PABLO_MASK H5Tcset_mask + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT H5T_init_cset_interface +static herr_t H5T_init_cset_interface(void); + + +/*-------------------------------------------------------------------------- +NAME + H5T_init_cset_interface -- Initialize interface-specific information +USAGE + herr_t H5T_init_cset_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5T_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5T_init_cset_interface(void) +{ + FUNC_ENTER_NOINIT(H5T_init_cset_interface); + + FUNC_LEAVE_NOAPI(H5T_init_interface()); +} /* H5T_init_cset_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tget_cset + * + * Purpose: HDF5 is able to distinguish between character sets of + * different nationalities and to convert between them to the + * extent possible. + * + * Return: Success: The character set of an H5T_STRING type. + * + * Failure: H5T_CSET_ERROR (Negative) + * + * Programmer: Robb Matzke + * Friday, January 9, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works for derived data types. + * + *------------------------------------------------------------------------- + */ +H5T_cset_t +H5Tget_cset(hid_t type_id) +{ + H5T_t *dt = NULL; + H5T_cset_t ret_value; + + FUNC_ENTER_API(H5Tget_cset, H5T_CSET_ERROR); + H5TRACE1("Tc","i",type_id); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_CSET_ERROR, "not a data type"); + /* Don't see any reason for this. Causes problem for variable-length + * string. -SLU (& QAK) */ + /*if (dt->parent) dt = dt->parent;*/ /*defer to parent*/ + if (!(H5T_STRING == dt->type || (H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5T_CSET_ERROR, "operation not defined for data type class"); + + /* result */ + if(H5T_STRING == dt->type) + ret_value = dt->u.atomic.u.s.cset; + else if(H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type) + ret_value = dt->u.vlen.cset; + else + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, H5T_CSET_ERROR, "can't get cset info"); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tset_cset + * + * Purpose: HDF5 is able to distinguish between character sets of + * different nationalities and to convert between them to the + * extent possible. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Friday, January 9, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works with derived data types. + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tset_cset(hid_t type_id, H5T_cset_t cset) +{ + H5T_t *dt = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tset_cset, FAIL); + H5TRACE2("e","iTc",type_id,cset); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (H5T_STATE_TRANSIENT!=dt->state) + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); + if (cset < 0 || cset >= H5T_NCSET) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "illegal character set type"); + /* Don't see any reason for this. Causes problem for variable-length + * string. -SLU (& QAK) */ + /*if (dt->parent) dt = dt->parent;*/ /*defer to parent*/ + if (!(H5T_STRING == dt->type || (H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); + + /* Commit */ + if(H5T_STRING == dt->type) + dt->u.atomic.u.s.cset = cset; + else if(H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type) + dt->u.vlen.cset = cset; + else + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "can't set cset info"); + +done: + FUNC_LEAVE_API(ret_value); +} + diff --git a/src/H5Tenum.c b/src/H5Tenum.c new file mode 100644 index 0000000..dcd7ff7 --- /dev/null +++ b/src/H5Tenum.c @@ -0,0 +1,582 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains the functionality for enumerated datatypes + * in the H5T interface. + */ + +#define H5T_PACKAGE /*suppress error about including H5Tpkg */ + +#include "H5private.h" /*generic functions */ +#include "H5Eprivate.h" /*error handling */ +#include "H5FLprivate.h" /*Free Lists */ +#include "H5Iprivate.h" /*ID functions */ +#include "H5MMprivate.h" /*memory management */ +#include "H5Tpkg.h" /*data-type functions */ + +#define PABLO_MASK H5Tenum_mask + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT H5T_init_enum_interface +static herr_t H5T_init_enum_interface(void); + +/* Declare extern the free list for H5T_t's */ +H5FL_EXTERN(H5T_t); + +/* Static local functions */ +static char *H5T_enum_nameof(H5T_t *dt, void *value, char *name/*out*/, + size_t size); +static herr_t H5T_enum_valueof(H5T_t *dt, const char *name, + void *value/*out*/); + + +/*-------------------------------------------------------------------------- +NAME + H5T_init_enum_interface -- Initialize interface-specific information +USAGE + herr_t H5T_init_enum_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5T_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5T_init_enum_interface(void) +{ + FUNC_ENTER_NOINIT(H5T_init_enum_interface); + + FUNC_LEAVE_NOAPI(H5T_init_interface()); +} /* H5T_init_enum_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tenum_create + * + * Purpose: Create a new enumeration data type based on the specified + * TYPE, which must be an integer type. + * + * Return: Success: ID of new enumeration data type + * + * Failure: Negative + * + * Programmer: Robb Matzke + * Tuesday, December 22, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t +H5Tenum_create(hid_t parent_id) +{ + H5T_t *parent = NULL; /*base integer data type */ + H5T_t *dt = NULL; /*new enumeration data type */ + hid_t ret_value; /*return value */ + + FUNC_ENTER_API(H5Tenum_create, FAIL); + H5TRACE1("i","i",parent_id); + + /* Check args */ + if (NULL==(parent=H5I_object_verify(parent_id,H5I_DATATYPE)) || H5T_INTEGER!=parent->type) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an integer data type"); + + /* Build new type */ + if((dt=H5T_enum_create(parent))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "cannot create enum type"); + /* Atomize the type */ + if ((ret_value=H5I_register(H5I_DATATYPE, dt))<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data type atom"); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_enum_create + * + * Purpose: Private function for H5Tenum_create. Create a new + * enumeration data type based on the specified + * TYPE, which must be an integer type. + * + * Return: Success: new enumeration data type + * + * Failure: NULL + * + * Programmer: Raymond Lu + * October 9, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5T_t * +H5T_enum_create(H5T_t *parent) +{ + H5T_t *ret_value; /*new enumeration data type */ + + FUNC_ENTER_NOAPI(H5T_enum_create, NULL); + + assert(parent); + + /* Build new type */ + if (NULL==(ret_value = H5FL_CALLOC(H5T_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + ret_value->type = H5T_ENUM; + ret_value->parent = H5T_copy(parent, H5T_COPY_ALL); + assert(ret_value->parent); + ret_value->size = ret_value->parent->size; + ret_value->ent.header = HADDR_UNDEF; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tenum_insert + * + * Purpose: Insert a new enumeration data type member into an enumeration + * type. TYPE is the enumeration type, NAME is the name of the + * new member, and VALUE points to the value of the new member. + * The NAME and VALUE must both be unique within the TYPE. VALUE + * points to data which is of the data type defined when the + * enumeration type was created. + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Robb Matzke + * Wednesday, December 23, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tenum_insert(hid_t type, const char *name, void *value) +{ + H5T_t *dt=NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tenum_insert, FAIL); + H5TRACE3("e","isx",type,name,value); + + /* Check args */ + if (NULL==(dt=H5I_object_verify(type,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (H5T_ENUM!=dt->type) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an enumeration data type"); + if (!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified"); + if (!value) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no value specified"); + + /* Do work */ + if (H5T_enum_insert(dt, name, value)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to insert new enumeration member"); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_enum_insert + * + * Purpose: Insert a new member having a NAME and VALUE into an + * enumeration data TYPE. The NAME and VALUE must both be + * unique. The VALUE points to data of the data type defined for + * the enumeration base type. + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Robb Matzke + * Wednesday, December 23, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5T_enum_insert(H5T_t *dt, const char *name, void *value) +{ + int i; + char **names=NULL; + uint8_t *values=NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5T_enum_insert, FAIL); + + assert(dt); + assert(name && *name); + assert(value); + + /* The name and value had better not already exist */ + for (i=0; iu.enumer.nmembs; i++) { + if (!HDstrcmp(dt->u.enumer.name[i], name)) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "name redefinition"); + if (!HDmemcmp(dt->u.enumer.value+i*dt->size, value, dt->size)) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "value redefinition"); + } + + /* Increase table sizes */ + if (dt->u.enumer.nmembs >= dt->u.enumer.nalloc) { + int n = MAX(32, 2*dt->u.enumer.nalloc); + if (NULL==(names=H5MM_realloc(dt->u.enumer.name, n*sizeof(char*)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + dt->u.enumer.name = names; + + if (NULL==(values=H5MM_realloc(dt->u.enumer.value, n*dt->size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + dt->u.enumer.value = values; + dt->u.enumer.nalloc = n; + } + + /* Insert new member at end of member arrays */ + dt->u.enumer.sorted = H5T_SORT_NONE; + i = dt->u.enumer.nmembs++; + dt->u.enumer.name[i] = H5MM_xstrdup(name); + HDmemcpy(dt->u.enumer.value+i*dt->size, value, dt->size); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tget_member_value + * + * Purpose: Return the value for an enumeration data type member. + * + * Return: Success: non-negative with the member value copied + * into the memory pointed to by VALUE. + * + * Failure: negative, VALUE memory is undefined. + * + * Programmer: Robb Matzke + * Wednesday, December 23, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tget_member_value(hid_t type, int membno, void *value/*out*/) +{ + H5T_t *dt=NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tget_member_value, FAIL); + H5TRACE3("e","iIsx",type,membno,value); + + if (NULL==(dt=H5I_object_verify(type,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (H5T_ENUM!=dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); + if (membno<0 || membno>=dt->u.enumer.nmembs) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid member number"); + if (!value) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null value buffer"); + + if (H5T_get_member_value(dt, membno, value)<0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get member value"); +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_get_member_value + * + * Purpose: Private function for H5T_get_member_value. Return the + * value for an enumeration data type member. + * + * Return: Success: non-negative with the member value copied + * into the memory pointed to by VALUE. + * + * Failure: negative, VALUE memory is undefined. + * + * Programmer: Raymond Lu + * October 9, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5T_get_member_value(H5T_t *dt, int membno, void *value/*out*/) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5T_get_member_value, FAIL); + + assert(dt); + assert(value); + + HDmemcpy(value, dt->u.enumer.value + membno*dt->size, dt->size); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + + +/*------------------------------------------------------------------------- + * Function: H5Tenum_nameof + * + * Purpose: Finds the symbol name that corresponds to the specified VALUE + * of an enumeration data type TYPE. At most SIZE characters of + * the symbol name are copied into the NAME buffer. If the + * entire symbol anem and null terminator do not fit in the NAME + * buffer then as many characters as possible are copied (not + * null terminated) and the function fails. + * + * Return: Success: Non-negative. + * + * Failure: Negative, first character of NAME is set to + * null if SIZE allows it. + * + * Programmer: Robb Matzke + * Monday, January 4, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tenum_nameof(hid_t type, void *value, char *name/*out*/, size_t size) +{ + H5T_t *dt = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tenum_nameof, FAIL); + H5TRACE4("e","ixxz",type,value,name,size); + + /* Check args */ + if (NULL==(dt=H5I_object_verify(type,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (H5T_ENUM!=dt->type) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an enumeration data type"); + if (!value) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no value supplied"); + if (!name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name buffer supplied"); + + if (NULL==H5T_enum_nameof(dt, value, name, size)) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "nameof query failed"); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_enum_nameof + * + * Purpose: Finds the symbol name that corresponds the the specified + * VALUE of an enumeration data type DT. At most SIZE characters + * of the symbol name are copied into the NAME buffer. If the + * entire symbol name and null terminator do not fit in the NAME + * buffer then as many characters as possible are copied and the + * function returns failure. + * + * If NAME is the null pointer and SIZE is zero then enough + * space is allocated to hold the result and a pointer to that + * memory is returned. + * + * Return: Success: Pointer to NAME + * + * Failure: NULL, name[0] is set to null. + * + * Programmer: Robb Matzke + * Monday, January 4, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static char * +H5T_enum_nameof(H5T_t *dt, void *value, char *name/*out*/, size_t size) +{ + int lt, md, rt; /*indices for binary search */ + int cmp=(-1); /*comparison result */ + char *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5T_enum_nameof, NULL); + + /* Check args */ + assert(dt && H5T_ENUM==dt->type); + assert(value); + assert(name || 0==size); + if (name && size>0) *name = '\0'; + + /* Sanity check */ + if (dt->u.enumer.nmembs == 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "datatype has no members"); + + /* Do a binary search over the values to find the correct one */ + H5T_sort_value(dt, NULL); + lt = 0; + rt = dt->u.enumer.nmembs; + md = -1; + + while (ltu.enumer.value+md*dt->size, dt->size); + if (cmp<0) { + rt = md; + } else if (cmp>0) { + lt = md+1; + } else { + break; + } + } + /* Value was not yet defined. This fixes bug # 774, 2002/06/05 EIP */ + if (cmp!=0) + HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "value is currently not defined"); + + /* Save result name */ + if (!name && NULL==(name=H5MM_malloc(HDstrlen(dt->u.enumer.name[md])+1))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + HDstrncpy(name, dt->u.enumer.name[md], size); + if (HDstrlen(dt->u.enumer.name[md])>=size) + HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, NULL, "name has been truncated"); + + /* Set return value */ + ret_value=name; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tenum_valueof + * + * Purpose: Finds the value that corresponds to the specified NAME f an + * enumeration TYPE. The VALUE argument should be at least as + * large as the value of H5Tget_size(type) in order to hold the + * result. + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Robb Matzke + * Monday, January 4, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tenum_valueof(hid_t type, const char *name, void *value/*out*/) +{ + H5T_t *dt = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tenum_valueof, FAIL); + H5TRACE3("e","isx",type,name,value); + + /* Check args */ + if (NULL==(dt=H5I_object_verify(type,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (H5T_ENUM!=dt->type) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an enumeration data type"); + if (!name || !*name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name"); + if (!value) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no value buffer"); + + if (H5T_enum_valueof(dt, name, value)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "valueof query failed"); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_enum_valueof + * + * Purpose: Finds the value that corresponds the the specified symbol + * NAME of an enumeration data type DT and copy it to the VALUE + * result buffer. The VALUE should be allocated by the caller to + * be large enough for the result. + * + * Return: Success: Non-negative, value stored in VALUE. + * + * Failure: Negative, VALUE is undefined. + * + * Programmer: Robb Matzke + * Monday, January 4, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T_enum_valueof(H5T_t *dt, const char *name, void *value/*out*/) +{ + int lt, md, rt; /*indices for binary search */ + int cmp=(-1); /*comparison result */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5T_enum_valueof, FAIL); + + /* Check args */ + assert(dt && H5T_ENUM==dt->type); + assert(name && *name); + assert(value); + + /* Sanity check */ + if (dt->u.enumer.nmembs == 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, FAIL, "datatype has no members"); + + /* Do a binary search over the names to find the correct one */ + H5T_sort_name(dt, NULL); + lt = 0; + rt = dt->u.enumer.nmembs; + md = -1; + + while (ltu.enumer.name[md]); + if (cmp<0) { + rt = md; + } else if (cmp>0) { + lt = md+1; + } else { + break; + } + } + /* Value was not yet defined. This fixes bug # 774, 2002/06/05 EIP */ + if (cmp!=0) + HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, FAIL, "string doesn't exist in the enumeration type"); + + HDmemcpy(value, dt->u.enumer.value+md*dt->size, dt->size); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + diff --git a/src/H5Tfields.c b/src/H5Tfields.c new file mode 100644 index 0000000..b14d6d3 --- /dev/null +++ b/src/H5Tfields.c @@ -0,0 +1,505 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains commond functionality for fields in + * enumerated & compound datatypes in the H5T interface. + */ + +#define H5T_PACKAGE /*suppress error about including H5Tpkg */ + +#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 */ + +#define PABLO_MASK H5Tfields_mask + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT H5T_init_fields_interface +static herr_t H5T_init_fields_interface(void); + + +/*-------------------------------------------------------------------------- +NAME + H5T_init_fields_interface -- Initialize interface-specific information +USAGE + herr_t H5T_init_fields_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5T_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5T_init_fields_interface(void) +{ + FUNC_ENTER_NOINIT(H5T_init_fields_interface); + + FUNC_LEAVE_NOAPI(H5T_init_interface()); +} /* H5T_init_fields_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tget_nmembers + * + * Purpose: Determines how many members TYPE_ID has. The type must be + * either a compound data type or an enumeration data type. + * + * Return: Success: Number of members defined in the data type. + * + * Failure: Negative + * + * Errors: + * + * Programmer: Robb Matzke + * Monday, December 8, 1997 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works with enumeration data types. + *------------------------------------------------------------------------- + */ +int +H5Tget_nmembers(hid_t type_id) +{ + H5T_t *dt = NULL; + int ret_value; + + FUNC_ENTER_API(H5Tget_num_members, FAIL); + H5TRACE1("Is","i",type_id); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + + 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); +} + + +/*------------------------------------------------------------------------- + * 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 data type. + * + * Return: Success: Number of members defined in the data type. + * + * Failure: Negative + * + * Errors: + * + * Programmer: Raymond Lu + * October 8, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +H5T_get_nmembers(const H5T_t *dt) +{ + int ret_value; + + FUNC_ENTER_NOAPI(H5T_get_nmembers, FAIL); + + assert(dt); + + if (H5T_COMPOUND==dt->type) + ret_value = dt->u.compnd.nmembs; + else if (H5T_ENUM==dt->type) + ret_value = dt->u.enumer.nmembs; + else + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "operation not supported for type class"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tget_member_name + * + * Purpose: Returns the name of a member of a compound or enumeration + * data type. 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 data types. + *------------------------------------------------------------------------- + */ +char * +H5Tget_member_name(hid_t type_id, int membno) +{ + H5T_t *dt = NULL; + char *ret_value; + + FUNC_ENTER_API(H5Tget_member_name, NULL); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); + + if((ret_value = H5T_get_member_name(dt, membno))==NULL) + 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 data type. 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 *dt, int membno) +{ + char *ret_value; + + FUNC_ENTER_NOAPI(H5T_get_member_name, NULL); + + assert(dt); + + switch (dt->type) { + case H5T_COMPOUND: + if (membno<0 || membno>=dt->u.compnd.nmembs) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid member number"); + ret_value = H5MM_xstrdup(dt->u.compnd.memb[membno].name); + break; + + case H5T_ENUM: + if (membno<0 || membno>=dt->u.enumer.nmembs) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid member number"); + ret_value = H5MM_xstrdup(dt->u.enumer.name[membno]); + break; + + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "operation not supported for type class"); + } + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tget_member_index + * + * Purpose: Returns the index of a member in a compound or enumeration + * data type 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; + int nmembs, i; + + FUNC_ENTER_API(H5Tget_member_index, FAIL); + H5TRACE2("Is","is",type_id,name); + + /* Check arguments */ + assert(name); + if(NULL==(dt=H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + + /* Locate member by name */ + switch (dt->type) { + case H5T_COMPOUND: + nmembs = dt->u.compnd.nmembs; + for(i=0; iu.compnd.memb[i].name, name)) + HGOTO_DONE(i); + } + break; + case H5T_ENUM: + nmembs = dt->u.enumer.nmembs; + for(i=0; iu.enumer.name[i], name)) + HGOTO_DONE(i); + } + break; + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "operation not supported for this type"); + } + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_sort_value + * + * Purpose: Sorts the members of a compound data type by their offsets; + * sorts the members of an enum type by their values. This even + * works for locked data types 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 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5T_sort_value(H5T_t *dt, int *map) +{ + int i, j, nmembs; + size_t size; + hbool_t swapped; + uint8_t tbuf[32]; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5T_sort_value, FAIL); + + /* Check args */ + assert(dt); + assert(H5T_COMPOUND==dt->type || H5T_ENUM==dt->type); + + /* Use a bubble sort because we can short circuit */ + if (H5T_COMPOUND==dt->type) { + if (H5T_SORT_VALUE!=dt->u.compnd.sorted) { + dt->u.compnd.sorted = H5T_SORT_VALUE; + nmembs = dt->u.compnd.nmembs; + for (i=nmembs-1, swapped=TRUE; i>0 && swapped; --i) { + for (j=0, swapped=FALSE; ju.compnd.memb[j].offset > + dt->u.compnd.memb[j+1].offset) { + H5T_cmemb_t tmp = dt->u.compnd.memb[j]; + dt->u.compnd.memb[j] = dt->u.compnd.memb[j+1]; + dt->u.compnd.memb[j+1] = tmp; + 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; iu.compnd.memb[i].offset < + dt->u.compnd.memb[i+1].offset); + } +#endif + } + } else if (H5T_ENUM==dt->type) { + if (H5T_SORT_VALUE!=dt->u.enumer.sorted) { + dt->u.enumer.sorted = H5T_SORT_VALUE; + nmembs = dt->u.enumer.nmembs; + size = dt->size; + assert(size<=sizeof(tbuf)); + for (i=nmembs-1, swapped=TRUE; i>0 && swapped; --i) { + for (j=0, swapped=FALSE; ju.enumer.value+j*size, + dt->u.enumer.value+(j+1)*size, + size)>0) { + /* Swap names */ + char *tmp = dt->u.enumer.name[j]; + dt->u.enumer.name[j] = dt->u.enumer.name[j+1]; + dt->u.enumer.name[j+1] = tmp; + + /* Swap values */ + HDmemcpy(tbuf, dt->u.enumer.value+j*size, size); + HDmemcpy(dt->u.enumer.value+j*size, + dt->u.enumer.value+(j+1)*size, size); + HDmemcpy(dt->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; iu.enumer.value+i*size, + dt->u.enumer.value+(i+1)*size, + size)<0); + } +#endif + } + } + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_sort_name + * + * Purpose: Sorts members of a compound or enumeration data type by their + * names. This even works for locked data types 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(H5T_t *dt, int *map) +{ + int i, j, nmembs; + size_t size; + hbool_t swapped; + uint8_t tbuf[32]; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5T_sort_name, FAIL); + + /* Check args */ + assert(dt); + assert(H5T_COMPOUND==dt->type || H5T_ENUM==dt->type); + + /* Use a bubble sort because we can short circuit */ + if (H5T_COMPOUND==dt->type) { + if (H5T_SORT_NAME!=dt->u.compnd.sorted) { + dt->u.compnd.sorted = H5T_SORT_NAME; + nmembs = dt->u.compnd.nmembs; + for (i=nmembs-1, swapped=TRUE; i>0 && swapped; --i) { + for (j=0, swapped=FALSE; ju.compnd.memb[j].name, + dt->u.compnd.memb[j+1].name)>0) { + H5T_cmemb_t tmp = dt->u.compnd.memb[j]; + dt->u.compnd.memb[j] = dt->u.compnd.memb[j+1]; + dt->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; iu.compnd.memb[i].name, + dt->u.compnd.memb[i+1].name)<0); + } +#endif + } + } else if (H5T_ENUM==dt->type) { + if (H5T_SORT_NAME!=dt->u.enumer.sorted) { + dt->u.enumer.sorted = H5T_SORT_NAME; + nmembs = dt->u.enumer.nmembs; + size = dt->size; + assert(size<=sizeof(tbuf)); + for (i=nmembs-1, swapped=TRUE; i>0 && swapped; --i) { + for (j=0, swapped=FALSE; ju.enumer.name[j], + dt->u.enumer.name[j+1])>0) { + /* Swap names */ + char *tmp = dt->u.enumer.name[j]; + dt->u.enumer.name[j] = dt->u.enumer.name[j+1]; + dt->u.enumer.name[j+1] = tmp; + + /* Swap values */ + HDmemcpy(tbuf, dt->u.enumer.value+j*size, size); + HDmemcpy(dt->u.enumer.value+j*size, + dt->u.enumer.value+(j+1)*size, size); + HDmemcpy(dt->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; iu.enumer.name[i], dt->u.enumer.name[i+1])<0); +#endif + } + } + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + diff --git a/src/H5Tfixed.c b/src/H5Tfixed.c new file mode 100644 index 0000000..fbcc1b0 --- /dev/null +++ b/src/H5Tfixed.c @@ -0,0 +1,182 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains the functionality for fixed-point (i.e. + * integer) datatypes in the H5T interface. + */ + +#define H5T_PACKAGE /*suppress error about including H5Tpkg */ + +#include "H5private.h" /*generic functions */ +#include "H5Eprivate.h" /*error handling */ +#include "H5Iprivate.h" /*ID functions */ +#include "H5Tpkg.h" /*data-type functions */ + +#define PABLO_MASK H5Tfixed_mask + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT H5T_init_fixed_interface +static herr_t H5T_init_fixed_interface(void); + + +/*-------------------------------------------------------------------------- +NAME + H5T_init_fixed_interface -- Initialize interface-specific information +USAGE + herr_t H5T_init_fixed_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5T_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5T_init_fixed_interface(void) +{ + FUNC_ENTER_NOINIT(H5T_init_fixed_interface); + + FUNC_LEAVE_NOAPI(H5T_init_interface()); +} /* H5T_init_fixed_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tget_sign + * + * Purpose: Retrieves the sign type for an integer type. + * + * Return: Success: The sign type. + * + * Failure: H5T_SGN_ERROR (Negative) + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works with derived data types. + *------------------------------------------------------------------------- + */ +H5T_sign_t +H5Tget_sign(hid_t type_id) +{ + H5T_t *dt = NULL; + H5T_sign_t ret_value; + + FUNC_ENTER_API(H5Tget_sign, H5T_SGN_ERROR); + H5TRACE1("Ts","i",type_id); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_SGN_ERROR, "not an integer data type"); + + ret_value = H5T_get_sign(dt); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_get_sign + * + * Purpose: Private function for H5Tget_sign. Retrieves the sign type + * for an integer type. + * + * Return: Success: The sign type. + * + * Failure: H5T_SGN_ERROR (Negative) + * + * Programmer: Raymond Lu + * October 8, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5T_sign_t +H5T_get_sign(H5T_t *dt) +{ + H5T_sign_t ret_value; + + FUNC_ENTER_NOAPI(H5T_get_sign, H5T_SGN_ERROR); + + assert(dt); + + /* Defer to parent */ + while(dt->parent) + dt = dt->parent; + + /* Check args */ + if (H5T_INTEGER!=dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5T_SGN_ERROR, "operation not defined for data type class"); + + /* Sign */ + ret_value = dt->u.atomic.u.i.sign; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + + +/*------------------------------------------------------------------------- + * Function: H5Tset_sign + * + * Purpose: Sets the sign property for an integer. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works with derived data types. + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tset_sign(hid_t type_id, H5T_sign_t sign) +{ + H5T_t *dt = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tset_sign, FAIL); + H5TRACE2("e","iTs",type_id,sign); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an integer data type"); + if (H5T_STATE_TRANSIENT!=dt->state) + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); + if (sign < 0 || sign >= H5T_NSGN) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "illegal sign type"); + if (H5T_ENUM==dt->type && dt->u.enumer.nmembs>0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined"); + if (dt->parent) + dt = dt->parent; /*defer to parent*/ + if (H5T_INTEGER!=dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); + + /* Commit */ + dt->u.atomic.u.i.sign = sign; + +done: + FUNC_LEAVE_API(ret_value); +} + diff --git a/src/H5Tfloat.c b/src/H5Tfloat.c new file mode 100644 index 0000000..a0ecac1 --- /dev/null +++ b/src/H5Tfloat.c @@ -0,0 +1,447 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains the functionality for floating-point + * datatypes in the H5T interface. + */ + +#define H5T_PACKAGE /*suppress error about including H5Tpkg */ + +#include "H5private.h" /*generic functions */ +#include "H5Eprivate.h" /*error handling */ +#include "H5Iprivate.h" /*ID functions */ +#include "H5Tpkg.h" /*data-type functions */ + +#define PABLO_MASK H5Tfloat_mask + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT H5T_init_float_interface +static herr_t H5T_init_float_interface(void); + + +/*-------------------------------------------------------------------------- +NAME + H5T_init_float_interface -- Initialize interface-specific information +USAGE + herr_t H5T_init_float_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5T_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5T_init_float_interface(void) +{ + FUNC_ENTER_NOINIT(H5T_init_float_interface); + + FUNC_LEAVE_NOAPI(H5T_init_interface()); +} /* H5T_init_float_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tget_fields + * + * Purpose: Returns information about the locations of the various bit + * fields of a floating point data type. The field positions + * are bit positions in the significant region of the data type. + * Bits are numbered with the least significant bit number zero. + * + * Any (or even all) of the arguments can be null pointers. + * + * Return: Success: Non-negative, field locations and sizes are + * returned through the arguments. + * + * Failure: Negative + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works with derived data types. + *------------------------------------------------------------------------- + */ +herr_t +H5Tget_fields(hid_t type_id, size_t *spos/*out*/, + size_t *epos/*out*/, size_t *esize/*out*/, + size_t *mpos/*out*/, size_t *msize/*out*/) +{ + H5T_t *dt = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tget_fields, FAIL); + H5TRACE6("e","ixxxxx",type_id,spos,epos,esize,mpos,msize); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (dt->parent) + dt = dt->parent; /*defer to parent*/ + if (H5T_FLOAT != dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); + + /* Get values */ + if (spos) *spos = dt->u.atomic.u.f.sign; + if (epos) *epos = dt->u.atomic.u.f.epos; + if (esize) *esize = dt->u.atomic.u.f.esize; + if (mpos) *mpos = dt->u.atomic.u.f.mpos; + if (msize) *msize = dt->u.atomic.u.f.msize; + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tset_fields + * + * Purpose: Sets the locations and sizes of the various floating point + * bit fields. The field positions are bit positions in the + * significant region of the data type. Bits are numbered with + * the least significant bit number zero. + * + * Fields are not allowed to extend beyond the number of bits of + * precision, nor are they allowed to overlap with one another. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works for derived data types. + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tset_fields(hid_t type_id, size_t spos, size_t epos, size_t esize, + size_t mpos, size_t msize) +{ + H5T_t *dt = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tset_fields, FAIL); + H5TRACE6("e","izzzzz",type_id,spos,epos,esize,mpos,msize); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (H5T_STATE_TRANSIENT!=dt->state) + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); + if (dt->parent) + dt = dt->parent; /*defer to parent*/ + if (H5T_FLOAT != dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); + if (epos + esize > dt->u.atomic.prec) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "exponent bit field size/location is invalid"); + if (mpos + msize > dt->u.atomic.prec) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mantissa bit field size/location is invalid"); + if (spos >= dt->u.atomic.prec) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sign location is not valid"); + + /* Check for overlap */ + if (spos >= epos && spos < epos + esize) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sign bit appears within exponent field"); + if (spos >= mpos && spos < mpos + msize) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "sign bit appears within mantissa field"); + if ((mpos < epos && mpos + msize > epos) || + (epos < mpos && epos + esize > mpos)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "exponent and mantissa fields overlap"); + + /* Commit */ + dt->u.atomic.u.f.sign = spos; + dt->u.atomic.u.f.epos = epos; + dt->u.atomic.u.f.mpos = mpos; + dt->u.atomic.u.f.esize = esize; + dt->u.atomic.u.f.msize = msize; + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tget_ebias + * + * Purpose: Retrieves the exponent bias of a floating-point type. + * + * Return: Success: The bias + * + * Failure: 0 + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works with derived data types. + *------------------------------------------------------------------------- + */ +size_t +H5Tget_ebias(hid_t type_id) +{ + H5T_t *dt = NULL; + size_t ret_value; + + FUNC_ENTER_API(H5Tget_ebias, 0); + H5TRACE1("z","i",type_id); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a data type"); + if (dt->parent) + dt = dt->parent; /*defer to parent*/ + if (H5T_FLOAT != dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, 0, "operation not defined for data type class"); + + /* bias */ + H5_ASSIGN_OVERFLOW(ret_value,dt->u.atomic.u.f.ebias,uint64_t,size_t); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tset_ebias + * + * Purpose: Sets the exponent bias of a floating-point type. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works with derived data types. + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tset_ebias(hid_t type_id, size_t ebias) +{ + H5T_t *dt = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tset_ebias, FAIL); + H5TRACE2("e","iz",type_id,ebias); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (H5T_STATE_TRANSIENT!=dt->state) + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); + if (dt->parent) + dt = dt->parent; /*defer to parent*/ + if (H5T_FLOAT != dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); + + /* Commit */ + dt->u.atomic.u.f.ebias = ebias; + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tget_norm + * + * Purpose: Returns the mantisssa normalization of a floating-point data + * type. + * + * Return: Success: Normalization ID + * + * Failure: H5T_NORM_ERROR (Negative) + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works with derived data types. + * + *------------------------------------------------------------------------- + */ +H5T_norm_t +H5Tget_norm(hid_t type_id) +{ + H5T_t *dt = NULL; + H5T_norm_t ret_value; + + FUNC_ENTER_API(H5Tget_norm, H5T_NORM_ERROR); + H5TRACE1("Tn","i",type_id); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NORM_ERROR, "not a data type"); + if (dt->parent) + dt = dt->parent; /*defer to parent*/ + if (H5T_FLOAT != dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5T_NORM_ERROR, "operation not defined for data type class"); + + /* norm */ + ret_value = dt->u.atomic.u.f.norm; + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tset_norm + * + * Purpose: Sets the mantissa normalization method for a floating point + * data type. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works for derived data types. + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tset_norm(hid_t type_id, H5T_norm_t norm) +{ + H5T_t *dt = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tset_norm, FAIL); + H5TRACE2("e","iTn",type_id,norm); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (H5T_STATE_TRANSIENT!=dt->state) + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); + if (norm < 0 || norm > H5T_NORM_NONE) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "illegal normalization"); + if (dt->parent) + dt = dt->parent; /*defer to parent*/ + if (H5T_FLOAT != dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); + + /* Commit */ + dt->u.atomic.u.f.norm = norm; + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tget_inpad + * + * Purpose: If any internal bits of a floating point type are unused + * (that is, those significant bits which are not part of the + * sign, exponent, or mantissa) then they will be filled + * according to the value of this property. + * + * Return: Success: The internal padding type. + * + * Failure: H5T_PAD_ERROR (Negative) + * + * Programmer: Robb Matzke + * Friday, January 9, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works for derived data types. + * + *------------------------------------------------------------------------- + */ +H5T_pad_t +H5Tget_inpad(hid_t type_id) +{ + H5T_t *dt = NULL; + H5T_pad_t ret_value; + + FUNC_ENTER_API(H5Tget_inpad, H5T_PAD_ERROR); + H5TRACE1("Tp","i",type_id); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_PAD_ERROR, "not a data type"); + if (dt->parent) + dt = dt->parent; /*defer to parent*/ + if (H5T_FLOAT != dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5T_PAD_ERROR, "operation not defined for data type class"); + + /* pad */ + ret_value = dt->u.atomic.u.f.pad; + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tset_inpad + * + * Purpose: If any internal bits of a floating point type are unused + * (that is, those significant bits which are not part of the + * sign, exponent, or mantissa) then they will be filled + * according to the value of this property. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Friday, January 9, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works for derived data types. + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tset_inpad(hid_t type_id, H5T_pad_t pad) +{ + H5T_t *dt = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tset_inpad, FAIL); + H5TRACE2("e","iTp",type_id,pad); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (H5T_STATE_TRANSIENT!=dt->state) + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); + if (pad < 0 || pad >= H5T_NPAD) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "illegal internal pad type"); + if (dt->parent) + dt = dt->parent; /*defer to parent*/ + if (H5T_FLOAT != dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); + + /* Commit */ + dt->u.atomic.u.f.pad = pad; + +done: + FUNC_LEAVE_API(ret_value); +} + diff --git a/src/H5Tnative.c b/src/H5Tnative.c new file mode 100644 index 0000000..fab2014 --- /dev/null +++ b/src/H5Tnative.c @@ -0,0 +1,761 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains the functionality for querying + * a "native" datatype for the H5T interface. + */ + +#define H5T_PACKAGE /*suppress error about including H5Tpkg */ + +#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 */ + +#define PABLO_MASK H5Tnative_mask + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT H5T_init_native_interface +static herr_t H5T_init_native_interface(void); + +/* Static local functions */ +static H5T_t *H5T_get_native_type(H5T_t *dt, H5T_direction_t direction, + size_t *struct_align, size_t *offset, size_t *comp_size); +static H5T_t *H5T_get_native_integer(size_t size, H5T_sign_t sign, H5T_direction_t direction, + size_t *struct_align, size_t *offset, size_t *comp_size); +static H5T_t *H5T_get_native_float(size_t size, H5T_direction_t direction, + size_t *struct_align, size_t *offset, size_t *comp_size); +static herr_t H5T_cmp_offset(size_t *comp_size, size_t *offset, size_t elem_size, + size_t nelems, size_t align, size_t *struct_align); + + +/*-------------------------------------------------------------------------- +NAME + H5T_init_native_interface -- Initialize interface-specific information +USAGE + herr_t H5T_init_native_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5T_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5T_init_native_interface(void) +{ + FUNC_ENTER_NOINIT(H5T_init_native_interface); + + FUNC_LEAVE_NOAPI(H5T_init_interface()); +} /* H5T_init_native_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tget_native_type + * + * Purpose: High-level API to return the native type of a datatype. + * The native type is chosen by matching the size and class of + * querried datatype from the following native premitive + * datatypes: + * H5T_NATIVE_CHAR H5T_NATIVE_UCHAR + * H5T_NATIVE_SHORT H5T_NATIVE_USHORT + * H5T_NATIVE_INT H5T_NATIVE_UINT + * H5T_NATIVE_LONG H5T_NATIVE_ULONG + * H5T_NATIVE_LLONG H5T_NATIVE_ULLONG + * + * H5T_NATIVE_FLOAT + * H5T_NATIVE_DOUBLE + * H5T_NATIVE_LDOUBLE + * + * Compound, array, enum, and VL types all choose among these + * types for theire members. Time, Bifield, Opaque, Reference + * types are only copy out. + * + * Return: Success: Returns the native data type if successful. + * + * Failure: negative + * + * Programmer: Raymond Lu + * Oct 3, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t +H5Tget_native_type(hid_t type_id, H5T_direction_t direction) +{ + H5T_t *dt; /* Datatype to create native datatype from */ + H5T_t *new_dt=NULL; /* Datatype for native datatype created */ + size_t comp_size=0; /* Compound datatype's size */ + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5Tget_native_type, FAIL); + H5TRACE1("z","i",type_id); + + /* check argument */ + if(NULL==(dt=H5I_object_verify(type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + + if(direction!=H5T_DIR_DEFAULT && direction!=H5T_DIR_ASCEND + && direction!=H5T_DIR_DESCEND) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not valid direction value"); + + if((new_dt = H5T_get_native_type(dt, direction, NULL, NULL, &comp_size))==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "cannot retrieve native type"); + + if((ret_value=H5I_register(H5I_DATATYPE, new_dt)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data type"); + +done: + /* Error cleanup */ + if(ret_value<0) { + if(new_dt) + H5T_close(new_dt); + } /* end if */ + + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_get_native_type + * + * Purpose: Returns the native type of a datatype. + * + * Return: Success: Returns the native data type if successful. + * + * Failure: negative + * + * Programmer: Raymond Lu + * Oct 3, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5T_t* +H5T_get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_align, size_t *offset, size_t *comp_size) +{ + H5T_t *dt; /* Datatype to make native */ + H5T_class_t h5_class; /* Class of datatype to make native */ + size_t size; /* Size of datatype to make native */ + int nmemb; /* Number of members in compound & enum types */ + H5T_t *super_type; /* Super type of VL, array and enum datatypes */ + H5T_t *nat_super_type; /* Native form of VL, array & enum super datatype */ + H5T_t *new_type=NULL; /* New native datatype */ + int i; /* Local index variable */ + H5T_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5T_get_native_type, NULL); + + assert(dtype); + + if((h5_class = H5T_get_class(dtype))<0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a valid class"); + + if((size = H5T_get_size(dtype))==0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a valid size"); + + switch(h5_class) { + case H5T_INTEGER: + { + H5T_sign_t sign; /* Signedness of integer type */ + + if((sign = H5T_get_sign(dtype))==H5T_SGN_ERROR) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a valid signess"); + + if((ret_value = H5T_get_native_integer(size, sign, direction, struct_align, offset, comp_size))==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve integer type"); + } + break; + + case H5T_FLOAT: + if((ret_value = H5T_get_native_float(size, direction, struct_align, offset, comp_size))==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); + + break; + + case H5T_STRING: + { + size_t align; + size_t pointer_size; + + if(H5T_is_variable_str(dtype)) { + if(NULL==(dt=H5I_object(H5T_C_S1))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); + if((ret_value=H5T_copy(dt, H5T_COPY_TRANSIENT))==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); + if(H5T_set_size(ret_value, H5T_VARIABLE)<0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot set size"); + + /* Update size, offset and compound alignment for parent. */ + align = H5T_POINTER_COMP_ALIGN_g; + pointer_size = sizeof(char*); + + if(H5T_cmp_offset(comp_size, offset, pointer_size, 1, align, struct_align)<0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset"); + + } else { + /*size_t char_size;*/ + + if(NULL==(dt=H5I_object(H5T_NATIVE_UCHAR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); + if((ret_value=H5T_copy(dt, H5T_COPY_TRANSIENT))==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); + if(H5T_set_size(ret_value, size)<0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot set size"); + + /* Update size, offset and compound alignment for parent. */ + align = H5T_NATIVE_SCHAR_COMP_ALIGN_g; + + if(H5T_cmp_offset(comp_size, offset, sizeof(char), size, align, struct_align)<0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset"); + + } + } + break; + + /* These three types don't need to compute compound field information since they + * can't be used as field. */ + case H5T_TIME: + case H5T_BITFIELD: + case H5T_OPAQUE: + if((ret_value=H5T_copy(dtype, H5T_COPY_TRANSIENT))==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); + + break; + case H5T_REFERENCE: + { + size_t align; + size_t ref_size; + int not_equal; + + if((ret_value=H5T_copy(dtype, H5T_COPY_TRANSIENT))==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); + + /* Decide if the data type is object or dataset region reference. */ + if(NULL==(dt=H5I_object(H5T_STD_REF_OBJ_g))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); + not_equal = H5T_cmp(ret_value, dt); + + /* Update size, offset and compound alignment for parent. */ + if(!not_equal) { + align = H5T_HOBJREF_COMP_ALIGN_g; + ref_size = sizeof(hobj_ref_t); + } else { + align = H5T_HDSETREGREF_COMP_ALIGN_g; + ref_size = sizeof(hdset_reg_ref_t); + } + + if(H5T_cmp_offset(comp_size, offset, ref_size, 1, align, struct_align)<0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset"); + } + break; + + case H5T_COMPOUND: + { + H5T_t *memb_type; /* Datatype of member */ + H5T_t **memb_list; /* List of compound member IDs */ + size_t *memb_offset; /* List of member offsets in compound type, including member size and alignment */ + size_t children_size=0;/* Total size of compound members */ + size_t children_st_align=0; /* The max alignment among compound members. This'll be the compound alignment */ + char **comp_mname; /* List of member names in compound type */ + + if((nmemb = H5T_get_nmembers(dtype))<=0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "compound data type doesn't have any member"); + + if((memb_list = (H5T_t**)H5MM_malloc(nmemb*sizeof(H5T_t*)))==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot allocate memory"); + if((memb_offset = (size_t*)H5MM_calloc(nmemb*sizeof(size_t)))==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot allocate memory"); + if((comp_mname = (char**)H5MM_malloc(nmemb*sizeof(char*)))==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot allocate memory"); + + /* Construct child compound type and retrieve a list of their IDs, offsets, total size, and alignment for compound type. */ + for(i=0; i0); + + if(direction == H5T_DIR_DEFAULT || direction == H5T_DIR_ASCEND) { + if(size==sizeof(char)) + match=H5T_NATIVE_INT_MATCH_CHAR; + else if(size==sizeof(short)) + match=H5T_NATIVE_INT_MATCH_SHORT; + else if(size==sizeof(int)) + match=H5T_NATIVE_INT_MATCH_INT; + else if(size==sizeof(long)) + match=H5T_NATIVE_INT_MATCH_LONG; + else if(size==sizeof(long_long)) + match=H5T_NATIVE_INT_MATCH_LLONG; + else /* If no native type matches the querried datatype, simply choose the type of biggest size. */ + match=H5T_NATIVE_INT_MATCH_LLONG; + } else if(direction == H5T_DIR_DESCEND) { + if(size==sizeof(long_long)) + match=H5T_NATIVE_INT_MATCH_LLONG; + else if(size==sizeof(long)) + match=H5T_NATIVE_INT_MATCH_LONG; + else if(size==sizeof(int)) + match=H5T_NATIVE_INT_MATCH_INT; + else if(size==sizeof(short)) + match=H5T_NATIVE_INT_MATCH_SHORT; + else if(size==sizeof(char)) + match=H5T_NATIVE_INT_MATCH_CHAR; + else /* If no native type matches the querried datatype, simple choose the type of smallest size. */ + match=H5T_NATIVE_INT_MATCH_CHAR; + } + + /* Set the appropriate native datatype information */ + switch(match) { + case H5T_NATIVE_INT_MATCH_CHAR: + if(sign==H5T_SGN_2) + tid = H5T_NATIVE_SCHAR; + else + tid = H5T_NATIVE_UCHAR; + + align = H5T_NATIVE_SCHAR_COMP_ALIGN_g; + break; + + case H5T_NATIVE_INT_MATCH_SHORT: + if(sign==H5T_SGN_2) + tid = H5T_NATIVE_SHORT; + else + tid = H5T_NATIVE_USHORT; + + align = H5T_NATIVE_SHORT_COMP_ALIGN_g; + break; + + case H5T_NATIVE_INT_MATCH_INT: + if(sign==H5T_SGN_2) + tid = H5T_NATIVE_INT; + else + tid = H5T_NATIVE_UINT; + + align = H5T_NATIVE_INT_COMP_ALIGN_g; + break; + + case H5T_NATIVE_INT_MATCH_LONG: + if(sign==H5T_SGN_2) + tid = H5T_NATIVE_LONG; + else + tid = H5T_NATIVE_ULONG; + + align = H5T_NATIVE_LONG_COMP_ALIGN_g; + break; + + case H5T_NATIVE_INT_MATCH_LLONG: + if(sign==H5T_SGN_2) + tid = H5T_NATIVE_LLONG; + else + tid = H5T_NATIVE_ULLONG; + + align = H5T_NATIVE_LLONG_COMP_ALIGN_g; + break; + + default: + assert(0 && "Unknown native integer match!"); + break; + } /* end switch */ + + /* Create new native type */ + assert(tid>=0); + if(NULL==(dt=H5I_object(tid))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); + if((ret_value=H5T_copy(dt, H5T_COPY_TRANSIENT))==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); + + /* compute size and offset of compound type member. */ + if(H5T_cmp_offset(comp_size, offset, size, 1, align, struct_align)<0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_get_native_float + * + * Purpose: Returns the native floatt type of a datatype. + * + * Return: Success: Returns the native data type if successful. + * + * Failure: negative + * + * Programmer: Raymond Lu + * Oct 3, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5T_t* +H5T_get_native_float(size_t size, H5T_direction_t direction, size_t *struct_align, size_t *offset, size_t *comp_size) +{ + H5T_t *dt=NULL; /* Appropriate native datatype to copy */ + hid_t tid=(-1); /* Datatype ID of appropriate native datatype */ + size_t align=0; /* Alignment necessary for native datatype */ + enum match_type { /* The different kinds of floating point types we can match */ + H5T_NATIVE_FLOAT_MATCH_FLOAT, + H5T_NATIVE_FLOAT_MATCH_DOUBLE, + H5T_NATIVE_FLOAT_MATCH_LDOUBLE, + H5T_NATIVE_FLOAT_MATCH_UNKNOWN + } match=H5T_NATIVE_FLOAT_MATCH_UNKNOWN; + H5T_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5T_get_native_integer, NULL); + + assert(size>0); + + if(direction == H5T_DIR_DEFAULT || direction == H5T_DIR_ASCEND) { + if(size==sizeof(float)) + match=H5T_NATIVE_FLOAT_MATCH_FLOAT; + else if(size==sizeof(double)) + match=H5T_NATIVE_FLOAT_MATCH_DOUBLE; + else if(size==sizeof(long double)) + match=H5T_NATIVE_FLOAT_MATCH_LDOUBLE; + else /* If not match, return the biggest datatype */ + match=H5T_NATIVE_FLOAT_MATCH_LDOUBLE; + } else { + if(size==sizeof(long double)) + match=H5T_NATIVE_FLOAT_MATCH_LDOUBLE; + else if(size==sizeof(double)) + match=H5T_NATIVE_FLOAT_MATCH_DOUBLE; + else if(size==sizeof(float)) + match=H5T_NATIVE_FLOAT_MATCH_FLOAT; + else + match=H5T_NATIVE_FLOAT_MATCH_FLOAT; + } + + /* Set the appropriate native floating point information */ + switch(match) { + case H5T_NATIVE_FLOAT_MATCH_FLOAT: + tid = H5T_NATIVE_FLOAT; + align = H5T_NATIVE_FLOAT_COMP_ALIGN_g; + break; + + case H5T_NATIVE_FLOAT_MATCH_DOUBLE: + tid = H5T_NATIVE_DOUBLE; + align = H5T_NATIVE_DOUBLE_COMP_ALIGN_g; + break; + + case H5T_NATIVE_FLOAT_MATCH_LDOUBLE: + tid = H5T_NATIVE_LDOUBLE; + align = H5T_NATIVE_LDOUBLE_COMP_ALIGN_g; + break; + + default: + assert(0 && "Unknown native floating-point match!"); + break; + } /* end switch */ + + /* Create new native type */ + assert(tid>=0); + if(NULL==(dt=H5I_object(tid))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); + if((ret_value=H5T_copy(dt, H5T_COPY_TRANSIENT))==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type"); + + /* compute offset of compound type member. */ + if(H5T_cmp_offset(comp_size, offset, size, 1, align, struct_align)<0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_cmp_offset + * + * Purpose: This function is only for convenience. It computes the + * compound type size, offset of the member being considered + * and the alignment for the whole compound type. + * + * Return: Success: Non-negative value. + * + * Failure: Negative value. + * + * Programmer: Raymond Lu + * December 10, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T_cmp_offset(size_t *comp_size, size_t *offset, size_t elem_size, + size_t nelems, size_t align, size_t *struct_align) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5T_cmp_offset, FAIL); + + if(offset && comp_size) { + if(align>1 && *comp_size%align) { + /* Add alignment value */ + *offset = *comp_size + (align - *comp_size%align); + *comp_size += (align - *comp_size%align); + } else + *offset = *comp_size; + + /* compute size of compound type member. */ + *comp_size += nelems*elem_size; + } + + if(struct_align && *struct_align < align) + *struct_align = align; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + diff --git a/src/H5Toffset.c b/src/H5Toffset.c new file mode 100644 index 0000000..63cffea --- /dev/null +++ b/src/H5Toffset.c @@ -0,0 +1,258 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains the functionality for setting & querying + * the datatype offset for the H5T interface. + */ + +#define H5T_PACKAGE /*suppress error about including H5Tpkg */ + +#include "H5private.h" /*generic functions */ +#include "H5Eprivate.h" /*error handling */ +#include "H5Iprivate.h" /*ID functions */ +#include "H5Tpkg.h" /*data-type functions */ + +#define PABLO_MASK H5Toffset_mask + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT H5T_init_offset_interface +static herr_t H5T_init_offset_interface(void); + +/* Static local functions */ +static herr_t H5T_set_offset(H5T_t *dt, size_t offset); + + +/*-------------------------------------------------------------------------- +NAME + H5T_init_offset_interface -- Initialize interface-specific information +USAGE + herr_t H5T_init_offset_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5T_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5T_init_offset_interface(void) +{ + FUNC_ENTER_NOINIT(H5T_init_offset_interface); + + FUNC_LEAVE_NOAPI(H5T_init_interface()); +} /* H5T_init_offset_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tget_offset + * + * Purpose: Retrieves the bit offset of the first significant bit. The + * signficant bits of an atomic datum can be offset from the + * beginning of the memory for that datum by an amount of + * padding. The `offset' property specifies the number of bits + * of padding that appear to the "right of" the value. That is, + * if we have a 32-bit datum with 16-bits of precision having + * the value 0x1122 then it will be layed out in memory as (from + * small byte address toward larger byte addresses): + * + * Big Big Little Little + * Endian Endian Endian Endian + * offset=0 offset=16 offset=0 offset=16 + * + * 0: [ pad] [0x11] [0x22] [ pad] + * 1: [ pad] [0x22] [0x11] [ pad] + * 2: [0x11] [ pad] [ pad] [0x22] + * 3: [0x22] [ pad] [ pad] [0x11] + * + * Return: Success: The offset (non-negative) + * + * Failure: Negative + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works for derived data types. + * + *------------------------------------------------------------------------- + */ +int +H5Tget_offset(hid_t type_id) +{ + H5T_t *dt = NULL; + int ret_value; + + FUNC_ENTER_API(H5Tget_offset, -1); + H5TRACE1("Is","i",type_id); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an atomic data type"); + if (dt->parent) + dt = dt->parent; /*defer to parent*/ + if (H5T_COMPOUND==dt->type || H5T_OPAQUE==dt->type || H5T_ARRAY==dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for specified data type"); + + /* Offset */ + assert(H5T_is_atomic(dt)); + ret_value = (int)dt->u.atomic.offset; + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tset_offset + * + * Purpose: Sets the bit offset of the first significant bit. The + * signficant bits of an atomic datum can be offset from the + * beginning of the memory for that datum by an amount of + * padding. The `offset' property specifies the number of bits + * of padding that appear to the "right of" the value. That is, + * if we have a 32-bit datum with 16-bits of precision having + * the value 0x1122 then it will be layed out in memory as (from + * small byte address toward larger byte addresses): + * + * Big Big Little Little + * Endian Endian Endian Endian + * offset=0 offset=16 offset=0 offset=16 + * + * 0: [ pad] [0x11] [0x22] [ pad] + * 1: [ pad] [0x22] [0x11] [ pad] + * 2: [0x11] [ pad] [ pad] [0x22] + * 3: [0x22] [ pad] [ pad] [0x11] + * + * If the offset is incremented then the total size is + * incremented also if necessary to prevent significant bits of + * the value from hanging over the edge of the data type. + * + * The offset of an H5T_STRING cannot be set to anything but + * zero. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Moved real work to a private function. + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tset_offset(hid_t type_id, size_t offset) +{ + H5T_t *dt = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tset_offset, FAIL); + H5TRACE2("e","iz",type_id,offset); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an atomic data type"); + if (H5T_STATE_TRANSIENT!=dt->state) + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); + if (H5T_STRING == dt->type && offset != 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "offset must be zero for this type"); + if (H5T_ENUM==dt->type && dt->u.enumer.nmembs>0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined"); + + /* Do the real work */ + if (H5T_set_offset(dt, offset)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set offset"); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_set_offset + * + * Purpose: Sets the bit offset of the first significant bit. The + * signficant bits of an atomic datum can be offset from the + * beginning of the memory for that datum by an amount of + * padding. The `offset' property specifies the number of bits + * of padding that appear to the "right of" the value. That is, + * if we have a 32-bit datum with 16-bits of precision having + * the value 0x1122 then it will be layed out in memory as (from + * small byte address toward larger byte addresses): + * + * Big Big Little Little + * Endian Endian Endian Endian + * offset=0 offset=16 offset=0 offset=16 + * + * 0: [ pad] [0x11] [0x22] [ pad] + * 1: [ pad] [0x22] [0x11] [ pad] + * 2: [0x11] [ pad] [ pad] [0x22] + * 3: [0x22] [ pad] [ pad] [0x11] + * + * If the offset is incremented then the total size is + * incremented also if necessary to prevent significant bits of + * the value from hanging over the edge of the data type. + * + * The offset of an H5T_STRING cannot be set to anything but + * zero. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works for derived data types. + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T_set_offset(H5T_t *dt, size_t offset) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5T_set_offset, FAIL); + + /* Check args */ + assert(dt); + assert(H5T_STRING!=dt->type || 0==offset); + assert(H5T_ENUM!=dt->type || 0==dt->u.enumer.nmembs); + + if (dt->parent) { + if (H5T_set_offset(dt->parent, offset)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set offset for base type"); + dt->size = dt->parent->size; + } else { + if (H5T_COMPOUND==dt->type || H5T_OPAQUE==dt->type || H5T_ARRAY==dt->type) { + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for specified data type"); + } else if (H5T_ENUM==dt->type) { + /*nothing*/ + } else { + if (offset+dt->u.atomic.prec > 8*dt->size) { + dt->size = (offset + dt->u.atomic.prec + 7) / 8; + } + dt->u.atomic.offset = offset; + } + } + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + diff --git a/src/H5Topaque.c b/src/H5Topaque.c new file mode 100644 index 0000000..1d1fec2 --- /dev/null +++ b/src/H5Topaque.c @@ -0,0 +1,139 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains the functionality for opaque + * datatypes in the H5T interface. + */ + +#define H5T_PACKAGE /*suppress error about including H5Tpkg */ + +#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 */ + +#define PABLO_MASK H5Topaque_mask + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT H5T_init_opaque_interface +static herr_t H5T_init_opaque_interface(void); + + +/*-------------------------------------------------------------------------- +NAME + H5T_init_opaque_interface -- Initialize interface-specific information +USAGE + herr_t H5T_init_opaque_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5T_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5T_init_opaque_interface(void) +{ + FUNC_ENTER_NOINIT(H5T_init_opaque_interface); + + FUNC_LEAVE_NOAPI(H5T_init_interface()); +} /* H5T_init_opaque_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tset_tag + * + * Purpose: Tag an opaque datatype with a unique ASCII identifier. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Thursday, May 20, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tset_tag(hid_t type_id, const char *tag) +{ + H5T_t *dt=NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tset_tag, FAIL); + H5TRACE2("e","is",type_id,tag); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (H5T_STATE_TRANSIENT!=dt->state) + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); + if (H5T_OPAQUE!=dt->type) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an opaque data type"); + if (!tag) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no tag"); + + /* Commit */ + H5MM_xfree(dt->u.opaque.tag); + dt->u.opaque.tag = H5MM_strdup(tag); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tget_tag + * + * Purpose: Get tha tag associated with an opaque datatype. + * + * Return: A pointer to an allocated string. The caller should free + * the string. NULL is returned for errors. + * + * Programmer: Robb Matzke + * Thursday, May 20, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +char * +H5Tget_tag(hid_t type_id) +{ + H5T_t *dt=NULL; + char *ret_value; + + FUNC_ENTER_API(H5Tget_tag, NULL); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type"); + + if (dt->parent) + dt = dt->parent; /*defer to parent*/ + if (H5T_OPAQUE != dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "operation not defined for data type class"); + + /* result */ + if (NULL==(ret_value=H5MM_strdup(dt->u.opaque.tag))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + +done: + FUNC_LEAVE_API(ret_value); +} + diff --git a/src/H5Torder.c b/src/H5Torder.c new file mode 100644 index 0000000..4e2f167 --- /dev/null +++ b/src/H5Torder.c @@ -0,0 +1,148 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains the functionality for setting & querying + * the datatype byte order for the H5T interface. + */ + +#define H5T_PACKAGE /*suppress error about including H5Tpkg */ + +#include "H5private.h" /*generic functions */ +#include "H5Eprivate.h" /*error handling */ +#include "H5Iprivate.h" /*ID functions */ +#include "H5Tpkg.h" /*data-type functions */ + +#define PABLO_MASK H5Torder_mask + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT H5T_init_order_interface +static herr_t H5T_init_order_interface(void); + + +/*-------------------------------------------------------------------------- +NAME + H5T_init_order_interface -- Initialize interface-specific information +USAGE + herr_t H5T_init_order_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5T_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5T_init_order_interface(void) +{ + FUNC_ENTER_NOINIT(H5T_init_order_interface); + + FUNC_LEAVE_NOAPI(H5T_init_interface()); +} /* H5T_init_order_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tget_order + * + * Purpose: Returns the byte order of a data type. + * + * Return: Success: A byte order constant + * + * Failure: H5T_ORDER_ERROR (Negative) + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works for derived data types. + * + *------------------------------------------------------------------------- + */ +H5T_order_t +H5Tget_order(hid_t type_id) +{ + H5T_t *dt = NULL; + H5T_order_t ret_value; + + FUNC_ENTER_API(H5Tget_order, H5T_ORDER_ERROR); + H5TRACE1("To","i",type_id); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_ORDER_ERROR, "not a data type"); + + if (dt->parent) + dt = dt->parent; /*defer to parent*/ + if (H5T_COMPOUND==dt->type || H5T_OPAQUE==dt->type || H5T_ARRAY ==dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5T_ORDER_ERROR, "operation not defined for specified data type"); + + /* Order */ + assert(H5T_is_atomic(dt)); + ret_value = dt->u.atomic.order; + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tset_order + * + * Purpose: Sets the byte order for a data type. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works for derived data types. + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tset_order(hid_t type_id, H5T_order_t order) +{ + H5T_t *dt = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tset_order, FAIL); + H5TRACE2("e","iTo",type_id,order); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (H5T_STATE_TRANSIENT!=dt->state) + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); + if (order < 0 || order > H5T_ORDER_NONE) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "illegal byte order"); + if (H5T_ENUM==dt->type && dt->u.enumer.nmembs>0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined"); + if (dt->parent) + dt = dt->parent; /*defer to parent*/ + if (H5T_COMPOUND==dt->type || H5T_OPAQUE==dt->type || H5T_ARRAY==dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5T_ORDER_ERROR, "operation not defined for specified data type"); + + /* Commit */ + assert(H5T_is_atomic(dt)); + dt->u.atomic.order = order; + +done: + FUNC_LEAVE_API(ret_value); +} + diff --git a/src/H5Tpad.c b/src/H5Tpad.c new file mode 100644 index 0000000..4f69d9e --- /dev/null +++ b/src/H5Tpad.c @@ -0,0 +1,151 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains the functionality for setting & querying + * the datatype padding for the H5T interface. + */ + +#define H5T_PACKAGE /*suppress error about including H5Tpkg */ + +#include "H5private.h" /*generic functions */ +#include "H5Eprivate.h" /*error handling */ +#include "H5Iprivate.h" /*ID functions */ +#include "H5Tpkg.h" /*data-type functions */ + +#define PABLO_MASK H5Tpad_mask + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT H5T_init_pad_interface +static herr_t H5T_init_pad_interface(void); + + +/*-------------------------------------------------------------------------- +NAME + H5T_init_pad_interface -- Initialize interface-specific information +USAGE + herr_t H5T_init_pad_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5T_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5T_init_pad_interface(void) +{ + FUNC_ENTER_NOINIT(H5T_init_pad_interface); + + FUNC_LEAVE_NOAPI(H5T_init_interface()); +} /* H5T_init_pad_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tget_pad + * + * Purpose: Gets the least significant pad type and the most significant + * pad type and returns their values through the LSB and MSB + * arguments, either of which may be the null pointer. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Friday, January 9, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works with derived data types. + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tget_pad(hid_t type_id, H5T_pad_t *lsb/*out*/, H5T_pad_t *msb/*out*/) +{ + H5T_t *dt = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tget_pad, FAIL); + H5TRACE3("e","ixx",type_id,lsb,msb); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (dt->parent) + dt = dt->parent; /*defer to parent*/ + if (H5T_COMPOUND==dt->type || H5T_OPAQUE==dt->type || H5T_ARRAY==dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for specified data type"); + + /* Get values */ + assert(H5T_is_atomic(dt)); + if (lsb) + *lsb = dt->u.atomic.lsb_pad; + if (msb) + *msb = dt->u.atomic.msb_pad; + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tset_pad + * + * Purpose: Sets the LSB and MSB pad types. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Friday, January 9, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works with derived data types. + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tset_pad(hid_t type_id, H5T_pad_t lsb, H5T_pad_t msb) +{ + H5T_t *dt = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tset_pad, FAIL); + H5TRACE3("e","iTpTp",type_id,lsb,msb); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (H5T_STATE_TRANSIENT!=dt->state) + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); + if (lsb < 0 || lsb >= H5T_NPAD || msb < 0 || msb >= H5T_NPAD) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pad type"); + if (H5T_ENUM==dt->type && dt->u.enumer.nmembs>0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined"); + if (dt->parent) + dt = dt->parent; /*defer to parent*/ + if (H5T_COMPOUND==dt->type || H5T_OPAQUE==dt->type || H5T_ARRAY==dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for specified data type"); + + /* Commit */ + assert(H5T_is_atomic(dt)); + dt->u.atomic.lsb_pad = lsb; + dt->u.atomic.msb_pad = msb; + +done: + FUNC_LEAVE_API(ret_value); +} + diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index 5b4cf09..87a96cc 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -241,6 +241,28 @@ H5_DLLVAR size_t H5T_NATIVE_UINT_LEAST64_ALIGN_g; H5_DLLVAR size_t H5T_NATIVE_INT_FAST64_ALIGN_g; H5_DLLVAR size_t H5T_NATIVE_UINT_FAST64_ALIGN_g; +/* Common functions */ +H5_DLL herr_t H5T_init_interface(void); +H5_DLL H5T_t *H5T_create(H5T_class_t type, size_t size); +H5_DLL herr_t H5T_free(H5T_t *dt); +H5_DLL H5T_sign_t H5T_get_sign(H5T_t *dt); +H5_DLL H5T_t *H5T_get_super(H5T_t *dt); +H5_DLL char *H5T_get_member_name(H5T_t *dt, int membno); +H5_DLL herr_t H5T_get_member_value(H5T_t *dt, int membno, void *value); +H5_DLL H5T_t *H5T_get_member_type(H5T_t *dt, int membno); +H5_DLL int H5T_get_nmembers(const H5T_t *dt); +H5_DLL htri_t H5T_is_variable_str(H5T_t *dt); +H5_DLL htri_t H5T_is_atomic(const H5T_t *dt); +H5_DLL herr_t H5T_insert(H5T_t *parent, const char *name, size_t offset, + const H5T_t *member); +H5_DLL H5T_t *H5T_enum_create(H5T_t *parent); +H5_DLL herr_t H5T_enum_insert(H5T_t *dt, const char *name, void *value); +H5_DLL int H5T_get_array_ndims(H5T_t *dt); +H5_DLL herr_t H5T_get_array_dims(H5T_t *dt, hsize_t dims[], int perm[]); +H5_DLL herr_t H5T_sort_value(H5T_t *dt, int *map); +H5_DLL herr_t H5T_sort_name(H5T_t *dt, int *map); +H5_DLL herr_t H5T_set_size(H5T_t *dt, size_t size); + /* Conversion functions */ H5_DLL herr_t H5T_conv_noop(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, size_t buf_stride, @@ -778,6 +800,7 @@ H5_DLL ssize_t H5T_bit_find(uint8_t *buf, size_t offset, size_t size, H5_DLL htri_t H5T_bit_inc(uint8_t *buf, size_t start, size_t size); /* VL functions */ +H5_DLL H5T_t * H5T_vlen_create(H5T_t *base); H5_DLL hssize_t H5T_vlen_seq_mem_getlen(H5F_t *f, void *vl_addr); H5_DLL herr_t H5T_vlen_seq_mem_read(H5F_t *f, hid_t dxpl_id, void *vl_addr, void *_buf, size_t len); H5_DLL herr_t H5T_vlen_seq_mem_write(H5F_t *f, hid_t dxpl_id, void *vl_addr, void *_buf, void *bg_addr, hsize_t seq_len, hsize_t base_size); diff --git a/src/H5Tprecis.c b/src/H5Tprecis.c new file mode 100644 index 0000000..60a82aa --- /dev/null +++ b/src/H5Tprecis.c @@ -0,0 +1,266 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains the functionality for setting & querying + * the datatype precision for the H5T interface. + */ + +#define H5T_PACKAGE /*suppress error about including H5Tpkg */ + +#include "H5private.h" /*generic functions */ +#include "H5Eprivate.h" /*error handling */ +#include "H5Iprivate.h" /*ID functions */ +#include "H5Tpkg.h" /*data-type functions */ + +#define PABLO_MASK H5Tprecis_mask + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT H5T_init_precis_interface +static herr_t H5T_init_precis_interface(void); + +/* Static local functions */ +static herr_t H5T_set_precision(H5T_t *dt, size_t prec); + + +/*-------------------------------------------------------------------------- +NAME + H5T_init_precis_interface -- Initialize interface-specific information +USAGE + herr_t H5T_init_precis_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5T_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5T_init_precis_interface(void) +{ + FUNC_ENTER_NOINIT(H5T_init_precis_interface); + + FUNC_LEAVE_NOAPI(H5T_init_interface()); +} /* H5T_init_precis_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tget_precision + * + * Purpose: Gets the precision of a data type. The precision is + * the number of significant bits which, unless padding is + * present, is 8 times larger than the value returned by + * H5Tget_size(). + * + * Return: Success: Number of significant bits + * + * Failure: 0 (all atomic types have at least one + * significant bit) + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works for derived data types. + * + *------------------------------------------------------------------------- + */ +size_t +H5Tget_precision(hid_t type_id) +{ + H5T_t *dt = NULL; + size_t ret_value; + + FUNC_ENTER_API(H5Tget_precision, 0); + H5TRACE1("z","i",type_id); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a data type"); + if (dt->parent) + dt = dt->parent; /*defer to parent*/ + if (H5T_COMPOUND==dt->type || H5T_OPAQUE==dt->type || H5T_ARRAY==dt->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, 0, "operation not defined for specified data type"); + + /* Precision */ + assert(H5T_is_atomic(dt)); + ret_value = dt->u.atomic.prec; + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tset_precision + * + * Purpose: Sets the precision of a data type. The precision is + * the number of significant bits which, unless padding is + * present, is 8 times larger than the value returned by + * H5Tget_size(). + * + * If the precision is increased then the offset is decreased + * and then the size is increased to insure that significant + * bits do not "hang over" the edge of the data type. + * + * The precision property of strings is read-only. + * + * When decreasing the precision of a floating point type, set + * the locations and sizes of the sign, mantissa, and exponent + * fields first. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Moved real work to a private function. + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tset_precision(hid_t type_id, size_t prec) +{ + H5T_t *dt = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tset_precision, FAIL); + H5TRACE2("e","iz",type_id,prec); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (H5T_STATE_TRANSIENT!=dt->state) + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); + if (prec <= 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "precision must be positive"); + if (H5T_ENUM==dt->type && dt->u.enumer.nmembs>0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined"); + + /* Do the work */ + if (H5T_set_precision(dt, prec)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set precision"); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_set_precision + * + * Purpose: Sets the precision of a data type. The precision is + * the number of significant bits which, unless padding is + * present, is 8 times larger than the value returned by + * H5Tget_size(). + * + * If the precision is increased then the offset is decreased + * and then the size is increased to insure that significant + * bits do not "hang over" the edge of the data type. + * + * The precision property of strings is read-only. + * + * When decreasing the precision of a floating point type, set + * the locations and sizes of the sign, mantissa, and exponent + * fields first. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Wednesday, January 7, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works for derived data types. + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T_set_precision(H5T_t *dt, size_t prec) +{ + size_t offset, size; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5T_set_precision, FAIL); + + /* Check args */ + assert(dt); + assert(prec>0); + assert(H5T_ENUM!=dt->type || 0==dt->u.enumer.nmembs); + + if (dt->parent) { + if (H5T_set_precision(dt->parent, prec)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set precision for base type"); + dt->size = dt->parent->size; + } else { + if (H5T_COMPOUND==dt->type || H5T_OPAQUE==dt->type || H5T_ARRAY==dt->type) { + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for specified data type"); + } else if (H5T_ENUM==dt->type) { + /*nothing*/ + } else if (H5T_is_atomic(dt)) { + /* Adjust the offset and size */ + offset = dt->u.atomic.offset; + size = dt->size; + if (prec > 8*size) + offset = 0; + else if (offset+prec > 8 * size) offset = 8 * size - prec; + if (prec > 8*size) + size = (prec+7) / 8; + + /* Check that things are still kosher */ + switch (dt->type) { + case H5T_INTEGER: + case H5T_TIME: + case H5T_BITFIELD: + /* nothing to check */ + break; + + case H5T_STRING: + HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "precision for this type is read-only"); + + case H5T_FLOAT: + /* + * The sign, mantissa, and exponent fields should be adjusted + * first when decreasing the precision of a floating point + * type. + */ + if (dt->u.atomic.u.f.sign >= prec || + dt->u.atomic.u.f.epos + dt->u.atomic.u.f.esize > prec || + dt->u.atomic.u.f.mpos + dt->u.atomic.u.f.msize > prec) { + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "adjust sign, mantissa, and exponent fields first"); + } + break; + + default: + assert("not implemented yet" && 0); + } + + /* Commit */ + dt->size = size; + if (H5T_is_atomic(dt)) { + dt->u.atomic.offset = offset; + dt->u.atomic.prec = prec; + } + } + } + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index fd35f28..82bf370 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -95,63 +95,23 @@ typedef struct { H5_DLL herr_t H5TN_init_interface(void); H5_DLL herr_t H5T_init(void); H5_DLL htri_t H5T_isa(H5G_entry_t *ent, hid_t dxpl_id); -H5_DLL H5T_t *H5T_open(H5G_entry_t *loc, const char *name, hid_t dxpl_id); H5_DLL H5T_t *H5T_open_oid(H5G_entry_t *ent, hid_t dxpl_id); -H5_DLL H5T_t *H5T_create(H5T_class_t type, size_t size); H5_DLL H5T_t *H5T_copy(const H5T_t *old_dt, H5T_copy_t method); -H5_DLL herr_t H5T_commit(H5G_entry_t *loc, const char *name, H5T_t *type, hid_t dxpl_id); H5_DLL herr_t H5T_lock(H5T_t *dt, hbool_t immutable); -H5_DLL herr_t H5T_free(H5T_t *dt); H5_DLL herr_t H5T_close(H5T_t *dt); -H5_DLL herr_t H5T_unregister(H5T_pers_t pers, const char *name, H5T_t *src, - H5T_t *dst, H5T_conv_t func, hid_t dxpl_id); -H5_DLL herr_t H5T_path_force_reinit(H5T_t *dt); H5_DLL H5T_class_t H5T_get_class(const H5T_t *dt); H5_DLL htri_t H5T_detect_class (const H5T_t *dt, H5T_class_t cls); H5_DLL size_t H5T_get_size(const H5T_t *dt); -H5_DLL H5T_sign_t H5T_get_sign(H5T_t *dt); -H5_DLL H5T_t *H5T_get_super(H5T_t *dt); -H5_DLL char *H5T_get_member_name(H5T_t *dt, int membno); -H5_DLL herr_t H5T_get_member_value(H5T_t *dt, int membno, void *value); -H5_DLL H5T_t *H5T_get_member_type(H5T_t *dt, int membno); -H5_DLL size_t H5T_get_member_offset(H5T_t *dt, int membno); -H5_DLL int H5T_get_nmembers(const H5T_t *dt); -H5_DLL htri_t H5T_is_variable_str(H5T_t *dt); -H5_DLL H5T_t *H5T_get_native_type(H5T_t *dt, H5T_direction_t direction, - size_t *struct_align, size_t *offset, size_t *comp_size); -H5_DLL H5T_t *H5T_get_native_integer(size_t size, H5T_sign_t sign, H5T_direction_t direction, - size_t *struct_align, size_t *offset, size_t *comp_size); -H5_DLL H5T_t *H5T_get_native_float(size_t size, H5T_direction_t direction, - size_t *struct_align, size_t *offset, size_t *comp_size); -H5_DLL herr_t H5T_cmp_offset(size_t *comp_size, size_t *offset, size_t elem_size, - size_t nelems, size_t align, size_t *struct_align); H5_DLL int H5T_cmp(const H5T_t *dt1, const H5T_t *dt2); -H5_DLL htri_t H5T_is_atomic(const H5T_t *dt); -H5_DLL herr_t H5T_insert(H5T_t *parent, const char *name, size_t offset, - const H5T_t *member); -H5_DLL H5T_t *H5T_enum_create(H5T_t *parent); -H5_DLL herr_t H5T_enum_insert(H5T_t *dt, const char *name, void *value); -H5_DLL int H5T_get_array_ndims(H5T_t *dt); -H5_DLL herr_t H5T_get_array_dims(H5T_t *dt, hsize_t dims[], int perm[]); -H5_DLL herr_t H5T_pack(H5T_t *dt); H5_DLL herr_t H5T_debug(const H5T_t *dt, FILE * stream); H5_DLL H5G_entry_t *H5T_entof(H5T_t *dt); H5_DLL htri_t H5T_is_immutable(H5T_t *dt); H5_DLL htri_t H5T_is_named(H5T_t *dt); H5_DLL H5T_path_t *H5T_path_find(const H5T_t *src, const H5T_t *dst, const char *name, H5T_conv_t func, hid_t dxpl_id); -H5_DLL herr_t H5T_sort_value(H5T_t *dt, int *map); -H5_DLL herr_t H5T_sort_name(H5T_t *dt, int *map); H5_DLL herr_t H5T_convert(H5T_path_t *tpath, hid_t src_id, hid_t dst_id, hsize_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg, hid_t dset_xfer_plist); -H5_DLL herr_t H5T_set_size(H5T_t *dt, size_t size); -H5_DLL herr_t H5T_set_precision(H5T_t *dt, size_t prec); -H5_DLL herr_t H5T_set_offset(H5T_t *dt, size_t offset); -H5_DLL char *H5T_enum_nameof(H5T_t *dt, void *value, char *name/*out*/, - size_t size); -H5_DLL herr_t H5T_enum_valueof(H5T_t *dt, const char *name, - void *value/*out*/); H5_DLL herr_t H5T_vlen_reclaim(void *elem, hid_t type_id, hsize_t ndim, hssize_t *point, void *_op_data); H5_DLL htri_t H5T_vlen_mark(H5T_t *dt, H5F_t *f, H5T_vlen_loc_t loc); H5_DLL htri_t H5T_is_sensible(const H5T_t *dt); diff --git a/src/H5Tstrpad.c b/src/H5Tstrpad.c new file mode 100644 index 0000000..ae8167c --- /dev/null +++ b/src/H5Tstrpad.c @@ -0,0 +1,171 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains the functionality for setting & querying + * the datatype string padding for the H5T interface. + */ + +#define H5T_PACKAGE /*suppress error about including H5Tpkg */ + +#include "H5private.h" /*generic functions */ +#include "H5Eprivate.h" /*error handling */ +#include "H5Iprivate.h" /*ID functions */ +#include "H5Tpkg.h" /*data-type functions */ + +#define PABLO_MASK H5Tstrpad_mask + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT H5T_init_strpad_interface +static herr_t H5T_init_strpad_interface(void); + + +/*-------------------------------------------------------------------------- +NAME + H5T_init_strpad_interface -- Initialize interface-specific information +USAGE + herr_t H5T_init_strpad_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5T_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5T_init_strpad_interface(void) +{ + FUNC_ENTER_NOINIT(H5T_init_strpad_interface); + + FUNC_LEAVE_NOAPI(H5T_init_interface()); +} /* H5T_init_strpad_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tget_strpad + * + * Purpose: The method used to store character strings differs with the + * programming language: C usually null terminates strings while + * Fortran left-justifies and space-pads strings. This property + * defines the storage mechanism for the string. + * + * Return: Success: The character set of an H5T_STRING type. + * + * Failure: H5T_STR_ERROR (Negative) + * + * Programmer: Robb Matzke + * Friday, January 9, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works for derived data types. + * + *------------------------------------------------------------------------- + */ +H5T_str_t +H5Tget_strpad(hid_t type_id) +{ + H5T_t *dt = NULL; + H5T_str_t ret_value; + + FUNC_ENTER_API(H5Tget_strpad, H5T_STR_ERROR); + H5TRACE1("Tz","i",type_id); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_STR_ERROR, "not a data type"); + /* Don't see any reason for this. Causes problem for variable-length + * string. -SLU (& QAK) */ + /* if (dt->parent) dt = dt->parent;*/ /*defer to parent*/ + if (!(H5T_STRING == dt->type || (H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5T_STR_ERROR, "operation not defined for data type class"); + + /* result */ + if(H5T_STRING == dt->type) + ret_value = dt->u.atomic.u.s.pad; + else if(H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type) + ret_value = dt->u.vlen.pad; + else + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, H5T_STR_ERROR, "can't get strpad info"); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Tset_strpad + * + * Purpose: The method used to store character strings differs with the + * programming language: C usually null terminates strings while + * Fortran left-justifies and space-pads strings. This property + * defines the storage mechanism for the string. + * + * When converting from a long string to a short string if the + * short string is H5T_STR_NULLPAD or H5T_STR_SPACEPAD then the + * string is simply truncated; otherwise if the short string is + * H5T_STR_NULLTERM it will be truncated and a null terminator + * is appended. + * + * When converting from a short string to a long string, the + * long string is padded on the end by appending nulls or + * spaces. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Friday, January 9, 1998 + * + * Modifications: + * Robb Matzke, 22 Dec 1998 + * Also works for derived data types. + * + *------------------------------------------------------------------------- + */ +herr_t +H5Tset_strpad(hid_t type_id, H5T_str_t strpad) +{ + H5T_t *dt = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Tset_strpad, FAIL); + H5TRACE2("e","iTz",type_id,strpad); + + /* Check args */ + if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (H5T_STATE_TRANSIENT!=dt->state) + HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); + if (strpad < 0 || strpad >= H5T_NSTR) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "illegal string pad type"); + /* Don't see any reason for this. Causes problem for variable-length + * string. -SLU (& QAK) */ + /* if (dt->parent) dt = dt->parent;*/ /*defer to parent*/ + if (!(H5T_STRING == dt->type || (H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); + + /* Commit */ + if(H5T_STRING == dt->type) + dt->u.atomic.u.s.pad = strpad; + else if(H5T_VLEN == dt->type && H5T_VLEN_STRING == dt->u.vlen.type) + dt->u.vlen.pad = strpad; + else + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, H5T_STR_ERROR, "can't set strpad info"); + +done: + FUNC_LEAVE_API(ret_value); +} + diff --git a/src/H5Tvlen.c b/src/H5Tvlen.c index c1f9926..fbb0d0a 100644 --- a/src/H5Tvlen.c +++ b/src/H5Tvlen.c @@ -10,29 +10,159 @@ * * ****************************************************************************/ -/* $Id$ */ +/* + * Module Info: This module contains the functionality for variable-length + * datatypes in the H5T interface. + */ #define H5T_PACKAGE /*suppress error about including H5Tpkg */ #include "H5private.h" /* Generic Functions */ -#include "H5Eprivate.h" /* Errors */ -#include "H5HGprivate.h" /* Global Heaps */ -#include "H5Iprivate.h" /* IDs */ -#include "H5Pprivate.h" /* Property Lists */ -#include "H5MMprivate.h" /* Memory Allocation */ -#include "H5Tpkg.h" /* Datatypes */ +#include "H5Eprivate.h" /* Errors */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5HGprivate.h" /* Global Heaps */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory Allocation */ +#include "H5Pprivate.h" /* Property Lists */ +#include "H5Tpkg.h" /* Datatypes */ #define PABLO_MASK H5Tvlen_mask /* Interface initialization */ static int interface_initialize_g = 0; -#define INTERFACE_INIT NULL +#define INTERFACE_INIT H5T_init_vlen_interface +static herr_t H5T_init_vlen_interface(void); + +/* Declare extern the free list for H5T_t's */ +H5FL_EXTERN(H5T_t); /* Local functions */ static htri_t H5T_vlen_set_loc(H5T_t *dt, H5F_t *f, H5T_vlen_loc_t loc); static herr_t H5T_vlen_reclaim_recurse(void *elem, H5T_t *dt, H5MM_free_t free_func, void *free_info); +/*-------------------------------------------------------------------------- +NAME + H5T_init_vlen_interface -- Initialize interface-specific information +USAGE + herr_t H5T_init_vlen_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5T_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5T_init_vlen_interface(void) +{ + FUNC_ENTER_NOINIT(H5T_init_vlen_interface); + + FUNC_LEAVE_NOAPI(H5T_init_interface()); +} /* H5T_init_vlen_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5Tvlen_create + * + * Purpose: Create a new variable-length data type based on the specified + * BASE_TYPE. + * + * Return: Success: ID of new VL data type + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * Thursday, May 20, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t +H5Tvlen_create(hid_t base_id) +{ + H5T_t *base = NULL; /*base data type */ + H5T_t *dt = NULL; /*new data type */ + hid_t ret_value; /*return value */ + + FUNC_ENTER_API(H5Tvlen_create, FAIL); + H5TRACE1("i","i",base_id); + + /* Check args */ + if (NULL==(base=H5I_object_verify(base_id,H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype"); + + /* Create up VL datatype */ + if ((dt=H5T_vlen_create(base))==NULL) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid VL location"); + + /* Atomize the type */ + if ((ret_value=H5I_register(H5I_DATATYPE, dt))<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype"); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_vlen_create + * + * Purpose: Create a new variable-length data type based on the specified + * BASE_TYPE. + * + * Return: Success: new VL data type + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * Tuesday, November 20, 2001 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5T_t * +H5T_vlen_create(H5T_t *base) +{ + H5T_t *dt = NULL; /*new VL data type */ + H5T_t *ret_value; /*return value */ + + FUNC_ENTER_NOINIT(H5T_vlen_create); + + /* Check args */ + assert(base); + + /* Build new type */ + if (NULL==(dt = H5FL_CALLOC(H5T_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); + dt->ent.header = HADDR_UNDEF; + dt->type = H5T_VLEN; + + /* + * Force conversions (i.e. memory to memory conversions should duplicate + * data, not point to the same VL sequences) + */ + dt->force_conv = TRUE; + dt->parent = H5T_copy(base, H5T_COPY_ALL); + + /* This is a sequence, not a string */ + dt->u.vlen.type = H5T_VLEN_SEQUENCE; + + /* Set up VL information */ + if (H5T_vlen_mark(dt, NULL, H5T_VLEN_MEMORY)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid VL location"); + + /* Set return value */ + ret_value=dt; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + /*------------------------------------------------------------------------- * Function: H5T_vlen_set_loc * diff --git a/src/Makefile.in b/src/Makefile.in index b0e622a..e8aab01 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -38,8 +38,11 @@ LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5D.c H5E.c H5F.c H5Farray.c H5Fcontig.c \ H5Omtime.c H5Oname.c H5Onull.c H5Opline.c H5Oplist.c H5Osdspace.c \ H5Oshared.c H5Ostab.c H5P.c H5Pdcpl.c H5Pdxpl.c H5Pfapl.c H5Pfcpl.c \ H5R.c H5RS.c H5S.c H5Sall.c H5Shyper.c H5Smpio.c H5Snone.c H5Spoint.c \ - H5Sselect.c H5ST.c H5T.c H5Tbit.c H5Tconv.c H5Tinit.c H5Tvlen.c \ - H5TB.c H5TS.c H5V.c H5Z.c H5Zdeflate.c H5Zshuffle.c H5Zadler32.c + H5Sselect.c H5ST.c H5T.c H5Tarray.c H5Tbit.c H5Tcommit.c \ + H5Tcompound.c H5Tconv.c H5Tcset.c H5Tenum.c H5Tfields.c H5Tfixed.c \ + H5Tfloat.c H5Tinit.c H5Tnative.c H5Toffset.c H5Topaque.c H5Torder.c \ + H5Tpad.c H5Tprecis.c H5Tstrpad.c H5Tvlen.c H5TB.c H5TS.c H5V.c H5Z.c \ + H5Zdeflate.c H5Zshuffle.c H5Zadler32.c LIB_OBJ=$(LIB_SRC:.c=.lo) -- cgit v0.12