/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
* access to either file, you may request a copy from help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* 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 */
/* Interface initialization */
#define H5_INTERFACE_INIT_FUNC H5T_init_interface
#include "H5private.h" /*generic functions */
#include "H5Dprivate.h" /*datasets (for H5Tcopy) */
#include "H5Eprivate.h" /*error handling */
#include "H5FLprivate.h" /* Free Lists */
#include "H5FOprivate.h" /* File objects */
#include "H5Gprivate.h" /*groups */
#include "H5Iprivate.h" /*ID functions */
#include "H5MMprivate.h" /*memory management */
#include "H5Pprivate.h" /* Property Lists */
#include "H5Tpkg.h" /*data-type functions */
/* Check for header needed for SGI floating-point code */
#ifdef H5_HAVE_SYS_FPU_H
#include <sys/fpu.h>
#endif /* H5_HAVE_SYS_FPU_H */
/*
* Predefined data types. These are initialized at runtime in H5Tinit.c and
* by H5T_init_interface() in this source file.
*
* If more of these are added, the new ones must be added to the list of
* types to reset in H5T_term_interface().
*/
hid_t H5T_IEEE_F32BE_g = FAIL;
hid_t H5T_IEEE_F32LE_g = FAIL;
hid_t H5T_IEEE_F64BE_g = FAIL;
hid_t H5T_IEEE_F64LE_g = FAIL;
hid_t H5T_STD_I8BE_g = FAIL;
hid_t H5T_STD_I8LE_g = FAIL;
hid_t H5T_STD_I16BE_g = FAIL;
hid_t H5T_STD_I16LE_g = FAIL;
hid_t H5T_STD_I32BE_g = FAIL;
hid_t H5T_STD_I32LE_g = FAIL;
hid_t H5T_STD_I64BE_g = FAIL;
hid_t H5T_STD_I64LE_g = FAIL;
hid_t H5T_STD_U8BE_g = FAIL;
hid_t H5T_STD_U8LE_g = FAIL;
hid_t H5T_STD_U16BE_g = FAIL;
hid_t H5T_STD_U16LE_g = FAIL;
hid_t H5T_STD_U32BE_g = FAIL;
hid_t H5T_STD_U32LE_g = FAIL;
hid_t H5T_STD_U64BE_g = FAIL;
hid_t H5T_STD_U64LE_g = FAIL;
hid_t H5T_STD_B8BE_g = FAIL;
hid_t H5T_STD_B8LE_g = FAIL;
hid_t H5T_STD_B16BE_g = FAIL;
hid_t H5T_STD_B16LE_g = FAIL;
hid_t H5T_STD_B32BE_g = FAIL;
hid_t H5T_STD_B32LE_g = FAIL;
hid_t H5T_STD_B64BE_g = FAIL;
hid_t H5T_STD_B64LE_g = FAIL;
hid_t H5T_STD_REF_OBJ_g = FAIL;
hid_t H5T_STD_REF_DSETREG_g = FAIL;
hid_t H5T_UNIX_D32BE_g = FAIL;
hid_t H5T_UNIX_D32LE_g = FAIL;
hid_t H5T_UNIX_D64BE_g = FAIL;
hid_t H5T_UNIX_D64LE_g = FAIL;
hid_t H5T_C_S1_g = FAIL;
hid_t H5T_FORTRAN_S1_g = FAIL;
hid_t H5T_NATIVE_SCHAR_g = FAIL;
hid_t H5T_NATIVE_UCHAR_g = FAIL;
hid_t H5T_NATIVE_SHORT_g = FAIL;
hid_t H5T_NATIVE_USHORT_g = FAIL;
hid_t H5T_NATIVE_INT_g = FAIL;
hid_t H5T_NATIVE_UINT_g = FAIL;
hid_t H5T_NATIVE_LONG_g = FAIL;
hid_t H5T_NATIVE_ULONG_g = FAIL;
hid_t H5T_NATIVE_LLONG_g = FAIL;
hid_t H5T_NATIVE_ULLONG_g = FAIL;
hid_t H5T_NATIVE_FLOAT_g = FAIL;
hid_t H5T_NATIVE_DOUBLE_g = FAIL;
hid_t H5T_NATIVE_LDOUBLE_g = FAIL;
hid_t H5T_NATIVE_B8_g = FAIL;
hid_t H5T_NATIVE_B16_g = FAIL;
hid_t H5T_NATIVE_B32_g = FAIL;
hid_t H5T_NATIVE_B64_g = FAIL;
hid_t H5T_NATIVE_OPAQUE_g = FAIL;
hid_t H5T_NATIVE_HADDR_g = FAIL;
hid_t H5T_NATIVE_HSIZE_g = FAIL;
hid_t H5T_NATIVE_HSSIZE_g = FAIL;
hid_t H5T_NATIVE_HERR_g = FAIL;
hid_t H5T_NATIVE_HBOOL_g = FAIL;
hid_t H5T_NATIVE_INT8_g = FAIL;
hid_t H5T_NATIVE_UINT8_g = FAIL;
hid_t H5T_NATIVE_INT_LEAST8_g = FAIL;
hid_t H5T_NATIVE_UINT_LEAST8_g = FAIL;
hid_t H5T_NATIVE_INT_FAST8_g = FAIL;
hid_t H5T_NATIVE_UINT_FAST8_g = FAIL;
hid_t H5T_NATIVE_INT16_g = FAIL;
hid_t H5T_NATIVE_UINT16_g = FAIL;
hid_t H5T_NATIVE_INT_LEAST16_g = FAIL;
hid_t H5T_NATIVE_UINT_LEAST16_g = FAIL;
hid_t H5T_NATIVE_INT_FAST16_g = FAIL;
hid_t H5T_NATIVE_UINT_FAST16_g = FAIL;
hid_t H5T_NATIVE_INT32_g = FAIL;
hid_t H5T_NATIVE_UINT32_g = FAIL;
hid_t H5T_NATIVE_INT_LEAST32_g = FAIL;
hid_t H5T_NATIVE_UINT_LEAST32_g = FAIL;
hid_t H5T_NATIVE_INT_FAST32_g = FAIL;
hid_t H5T_NATIVE_UINT_FAST32_g = FAIL;
hid_t H5T_NATIVE_INT64_g = FAIL;
hid_t H5T_NATIVE_UINT64_g = FAIL;
hid_t H5T_NATIVE_INT_LEAST64_g = FAIL;
hid_t H5T_NATIVE_UINT_LEAST64_g = FAIL;
hid_t H5T_NATIVE_INT_FAST64_g = FAIL;
hid_t H5T_NATIVE_UINT_FAST64_g = FAIL;
/*
* Alignment constraints for native types. These are initialized at run time
* in H5Tinit.c. These alignments are mainly for offsets in HDF5 compound
* datatype or C structures, which are different from the alignments for memory
* address below this group of variables.
*/
size_t H5T_NATIVE_SCHAR_COMP_ALIGN_g = 0;
size_t H5T_NATIVE_UCHAR_COMP_ALIGN_g = 0;
size_t H5T_NATIVE_SHORT_COMP_ALIGN_g = 0;
size_t H5T_NATIVE_USHORT_COMP_ALIGN_g = 0;
size_t H5T_NATIVE_INT_COMP_ALIGN_g = 0;
size_t H5T_NATIVE_UINT_COMP_ALIGN_g = 0;
size_t H5T_NATIVE_LONG_COMP_ALIGN_g = 0;
size_t H5T_NATIVE_ULONG_COMP_ALIGN_g = 0;
size_t H5T_NATIVE_LLONG_COMP_ALIGN_g = 0;
size_t H5T_NATIVE_ULLONG_COMP_ALIGN_g = 0;
size_t H5T_NATIVE_FLOAT_COMP_ALIGN_g = 0;
size_t H5T_NATIVE_DOUBLE_COMP_ALIGN_g = 0;
size_t H5T_NATIVE_LDOUBLE_COMP_ALIGN_g = 0;
size_t H5T_POINTER_COMP_ALIGN_g = 0;
size_t H5T_HVL_COMP_ALIGN_g = 0;
size_t H5T_HOBJREF_COMP_ALIGN_g = 0;
size_t H5T_HDSETREGREF_COMP_ALIGN_g = 0;
/*
* Alignment constraints for native types. These are initialized at run time
* in H5Tinit.c
*/
size_t H5T_NATIVE_SCHAR_ALIGN_g = 0;
size_t H5T_NATIVE_UCHAR_ALIGN_g = 0;
size_t H5T_NATIVE_SHORT_ALIGN_g = 0;
size_t H5T_NATIVE_USHORT_ALIGN_g = 0;
size_t H5T_NATIVE_INT_ALIGN_g = 0;
size_t H5T_NATIVE_UINT_ALIGN_g = 0;
size_t H5T_NATIVE_LONG_ALIGN_g = 0;
size_t H5T_NATIVE_ULONG_ALIGN_g = 0;
size_t H5T_NATIVE_LLONG_ALIGN_g = 0;
size_t H5T_NATIVE_ULLONG_ALIGN_g = 0;
size_t H5T_NATIVE_FLOAT_ALIGN_g = 0;
size_t H5T_NATIVE_DOUBLE_ALIGN_g = 0;
size_t H5T_NATIVE_LDOUBLE_ALIGN_g = 0;
/*
* Alignment constraints for C9x types. These are initialized at run time in
* H5Tinit.c if the types are provided by the system. Otherwise we set their
* values to 0 here (no alignment calculated).
*/
size_t H5T_NATIVE_INT8_ALIGN_g = 0;
size_t H5T_NATIVE_UINT8_ALIGN_g = 0;
size_t H5T_NATIVE_INT_LEAST8_ALIGN_g = 0;
size_t H5T_NATIVE_UINT_LEAST8_ALIGN_g = 0;
size_t H5T_NATIVE_INT_FAST8_ALIGN_g = 0;
size_t H5T_NATIVE_UINT_FAST8_ALIGN_g = 0;
size_t H5T_NATIVE_INT16_ALIGN_g = 0;
size_t H5T_NATIVE_UINT16_ALIGN_g = 0;
size_t H5T_NATIVE_INT_LEAST16_ALIGN_g = 0;
size_t H5T_NATIVE_UINT_LEAST16_ALIGN_g = 0;
size_t H5T_NATIVE_INT_FAST16_ALIGN_g = 0;
size_t H5T_NATIVE_UINT_FAST16_ALIGN_g = 0;
size_t H5T_NATIVE_INT32_ALIGN_g = 0;
size_t H5T_NATIVE_UINT32_ALIGN_g = 0;
size_t H5T_NATIVE_INT_LEAST32_ALIGN_g = 0;
size_t H5T_NATIVE_UINT_LEAST32_ALIGN_g = 0;
size_t H5T_NATIVE_INT_FAST32_ALIGN_g = 0;
size_t H5T_NATIVE_UINT_FAST32_ALIGN_g = 0;
size_t H5T_NATIVE_INT64_ALIGN_g = 0;
size_t H5T_NATIVE_UINT64_ALIGN_g = 0;
size_t H5T_NATIVE_INT_LEAST64_ALIGN_g = 0;
size_t H5T_NATIVE_UINT_LEAST64_ALIGN_g = 0;
size_t H5T_NATIVE_INT_FAST64_ALIGN_g = 0;
size_t H5T_NATIVE_UINT_FAST64_ALIGN_g = 0;
/* Useful floating-point values for conversion routines */
/* (+/- Inf for all floating-point types) */
float H5T_NATIVE_FLOAT_POS_INF_g = 0.0;
float H5T_NATIVE_FLOAT_NEG_INF_g = 0.0;
double H5T_NATIVE_DOUBLE_POS_INF_g = 0.0;
double H5T_NATIVE_DOUBLE_NEG_INF_g = 0.0;
/*
* The path database. Each path has a source and destination data type pair
* which is used as the key by which the `entries' array is sorted.
*/
static struct {
int npaths; /*number of paths defined */
int apaths; /*number of paths allocated */
H5T_path_t **path; /*sorted array of path pointers */
int nsoft; /*number of soft conversions defined */
int asoft; /*number of soft conversions allocated */
H5T_soft_t *soft; /*unsorted array of soft conversions */
} H5T_g;
/* The overflow handler */
H5T_overflow_t H5T_overflow_g = NULL;
/* The native endianess of the platform */
H5T_order_t H5T_native_order_g = H5T_ORDER_ERROR;
/* Declare the free list for H5T_t's and H5T_shared_t's */
H5FL_DEFINE(H5T_t);
H5FL_DEFINE(H5T_shared_t);
/* Declare the free list for H5T_path_t's */
H5FL_DEFINE(H5T_path_t);
/* Static local functions */
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);
/*
* Type initialization macros
*
* These use the "template macro" technique to reduce the amount of gratuitous
* duplicated code when initializing the datatypes for the library. The main
* template macro is the H5T_INIT_TYPE() macro below.
*
*/
/* Define the code template for types which need no extra initialization for the "GUTS" in the H5T_INIT_TYPE macro */
#define H5T_INIT_TYPE_NONE_CORE { \
}
/* Define the code template for bitfields for the "GUTS" in the H5T_INIT_TYPE macro */
#define H5T_INIT_TYPE_BITFIELD_CORE { \
dt->shared->type = H5T_BITFIELD; \
}
/* Define the code template for times for the "GUTS" in the H5T_INIT_TYPE macro */
#define H5T_INIT_TYPE_TIME_CORE { \
dt->shared->type = H5T_TIME; \
}
/* Define the code template for types which reset the offset for the "GUTS" in the H5T_INIT_TYPE macro */
#define H5T_INIT_TYPE_OFFSET_CORE { \
dt->shared->u.atomic.offset = 0; \
}
/* Define common code for all numeric types (floating-point & int, signed & unsigned) */
#define H5T_INIT_TYPE_NUM_COMMON(ENDIANNESS) { \
dt->shared->u.atomic.order = ENDIANNESS; \
dt->shared->u.atomic.offset = 0; \
dt->shared->u.atomic.lsb_pad = H5T_PAD_ZERO; \
dt->shared->u.atomic.msb_pad = H5T_PAD_ZERO; \
}
/* Define the code templates for standard floats for the "GUTS" in the H5T_INIT_TYPE macro */
#define H5T_INIT_TYPE_FLOAT_COMMON(ENDIANNESS) { \
H5T_INIT_TYPE_NUM_COMMON(ENDIANNESS) \
dt->shared->u.atomic.u.f.sign = 31; \
dt->shared->u.atomic.u.f.epos = 23; \
dt->shared->u.atomic.u.f.esize = 8; \
dt->shared->u.atomic.u.f.ebias = 0x7f; \
dt->shared->u.atomic.u.f.mpos = 0; \
dt->shared->u.atomic.u.f.msize = 23; \
dt->shared->u.atomic.u.f.norm = H5T_NORM_IMPLIED; \
dt->shared->u.atomic.u.f.pad = H5T_PAD_ZERO; \
}
#define H5T_INIT_TYPE_FLOATLE_CORE { \
H5T_INIT_TYPE_FLOAT_COMMON(H5T_ORDER_LE) \
}
#define H5T_INIT_TYPE_FLOATBE_CORE { \
H5T_INIT_TYPE_FLOAT_COMMON(H5T_ORDER_BE) \
}
/* Define the code templates for standard doubles for the "GUTS" in the H5T_INIT_TYPE macro */
#define H5T_INIT_TYPE_DOUBLE_COMMON(ENDIANNESS) { \
H5T_INIT_TYPE_NUM_COMMON(ENDIANNESS) \
dt->shared->u.atomic.u.f.sign = 63; \
dt->shared->u.atomic.u.f.epos = 52; \
dt->shared->u.atomic.u.f.esize = 11; \
dt->shared->u.atomic.u.f.ebias = 0x03ff; \
dt->shared->u.atomic.u.f.mpos = 0; \
dt->shared->u.atomic.u.f.msize = 52; \
dt->shared->u.atomic.u.f.norm = H5T_NORM_IMPLIED; \
dt->shared->u.atomic.u.f.pad = H5T_PAD_ZERO; \
}
#define H5T_INIT_TYPE_DOUBLELE_CORE { \
H5T_INIT_TYPE_DOUBLE_COMMON(H5T_ORDER_LE) \
}
#define H5T_INIT_TYPE_DOUBLEBE_CORE { \
H5T_INIT_TYPE_DOUBLE_COMMON(H5T_ORDER_BE) \
}
/* Define the code templates for standard signed integers for the "GUTS" in the H5T_INIT_TYPE macro */
#define H5T_INIT_TYPE_SINT_COMMON(ENDIANNESS) { \
H5T_INIT_TYPE_NUM_COMMON(ENDIANNESS) \
dt->shared->u.atomic.u.i.sign = H5T_SGN_2; \
}
#define H5T_INIT_TYPE_SINTLE_CORE { \
H5T_INIT_TYPE_SINT_COMMON(H5T_ORDER_LE) \
}
#define H5T_INIT_TYPE_SINTBE_CORE { \
H5T_INIT_TYPE_SINT_COMMON(H5T_ORDER_BE) \
}
/* Define the code templates for standard unsigned integers for the "GUTS" in the H5T_INIT_TYPE macro */
#define H5T_INIT_TYPE_UINT_COMMON(ENDIANNESS) { \
H5T_INIT_TYPE_NUM_COMMON(ENDIANNESS) \
dt->shared->u.atomic.u.i.sign = H5T_SGN_NONE; \
}
#define H5T_INIT_TYPE_UINTLE_CORE { \
H5T_INIT_TYPE_UINT_COMMON(H5T_ORDER_LE) \
}
#define H5T_INIT_TYPE_UINTBE_CORE { \
H5T_INIT_TYPE_UINT_COMMON(H5T_ORDER_BE) \
}
/* Define a macro for common code for all newly allocate datatypes */
#define H5T_INIT_TYPE_ALLOC_COMMON(TYPE) { \
dt->ent.header = HADDR_UNDEF; \
dt->shared->type = TYPE; \
}
/* Define the code templates for opaque for the "GUTS" in the H5T_INIT_TYPE macro */
#define H5T_INIT_TYPE_OPAQ_CORE { \
H5T_INIT_TYPE_ALLOC_COMMON(H5T_OPAQUE) \
dt->shared->u.opaque.tag = H5MM_strdup(""); \
}
/* Define the code templates for strings for the "GUTS" in the H5T_INIT_TYPE macro */
#define H5T_INIT_TYPE_STRING_COMMON { \
H5T_INIT_TYPE_ALLOC_COMMON(H5T_STRING) \
H5T_INIT_TYPE_NUM_COMMON(H5T_ORDER_NONE) \
dt->shared->u.atomic.u.s.cset = H5T_CSET_ASCII; \
}
#define H5T_INIT_TYPE_CSTRING_CORE { \
H5T_INIT_TYPE_STRING_COMMON \
dt->shared->u.atomic.u.s.pad = H5T_STR_NULLTERM; \
}
#define H5T_INIT_TYPE_FORSTRING_CORE { \
H5T_INIT_TYPE_STRING_COMMON \
dt->shared->u.atomic.u.s.pad = H5T_STR_SPACEPAD; \
}
/* Define the code templates for references for the "GUTS" in the H5T_INIT_TYPE macro */
#define H5T_INIT_TYPE_REF_COMMON(RTYPE) { \
H5T_INIT_TYPE_ALLOC_COMMON(H5T_REFERENCE) \
H5T_INIT_TYPE_NUM_COMMON(H5T_ORDER_NONE) \
dt->shared->u.atomic.u.r.rtype = RTYPE; \
}
#define H5T_INIT_TYPE_OBJREF_CORE { \
H5T_INIT_TYPE_REF_COMMON(H5R_OBJECT) \
}
#define H5T_INIT_TYPE_REGREF_CORE { \
H5T_INIT_TYPE_REF_COMMON(H5R_DATASET_REGION) \
}
/* Define the code templates for the "SIZE_TMPL" in the H5T_INIT_TYPE macro */
#define H5T_INIT_TYPE_SET_SIZE(SIZE) { \
dt->shared->size = SIZE; \
dt->shared->u.atomic.prec = 8*SIZE; \
}
#define H5T_INIT_TYPE_NOSET_SIZE(SIZE) { \
}
/* Define the code templates for the "CRT_TMPL" in the H5T_INIT_TYPE macro */
#define H5T_INIT_TYPE_COPY_CREATE(BASE) { \
/* Base off of existing datatype */ \
if(NULL==(dt = H5T_copy(BASE,H5T_COPY_TRANSIENT))) \
HGOTO_ERROR (H5E_RESOURCE, H5E_CANTCOPY, FAIL, "duplicating base type failed") \
}
#define H5T_INIT_TYPE_ALLOC_CREATE(BASE) { \
/* Allocate new datatype info */ \
if (NULL==(dt = H5T_alloc())) \
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") \
}
#define H5T_INIT_TYPE(GUTS,GLOBAL,CRT_TMPL,BASE,SIZE_TMPL,SIZE) { \
/* Get new datatype struct */ \
H5_GLUE3(H5T_INIT_TYPE_,CRT_TMPL,_CREATE)(BASE) \
\
/* Adjust information for all types */ \
dt->shared->state = H5T_STATE_IMMUTABLE; \
H5_GLUE3(H5T_INIT_TYPE_,SIZE_TMPL,_SIZE)(SIZE) \
\
/* Adjust information for this type */ \
H5_GLUE3(H5T_INIT_TYPE_,GUTS,_CORE) \
\
/* Atomize result */ \
if ((GLOBAL = H5I_register(H5I_DATATYPE, dt)) < 0) \
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom") \
}
/*-------------------------------------------------------------------------
* Function: H5T_init
*
* Purpose: Initialize the interface from some other package.
*
* Return: Success: non-negative
*
* Failure: negative
*
* Programmer: Robb Matzke
* Wednesday, December 16, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5T_init(void)
{
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5T_init, FAIL);
/* FUNC_ENTER() does all the work */
done:
FUNC_LEAVE_NOAPI(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5T_init_inf
*
* Purpose: Initialize the +/- Infinity floating-poing values for type
* conversion.
*
* Return: Success: non-negative
*
* Failure: negative
*
* Programmer: Quincey Koziol
* Saturday, November 22, 2003
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
H5T_init_inf(void)
{
H5T_t *dst_p; /* Datatype type operate on */
H5T_atomic_t *dst; /* Datatype's atomic info */
uint8_t *d; /* Pointer to value to set */
size_t half_size; /* Half the type size */
size_t u; /* Local index value */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5T_init_inf);
/* Get the float datatype */
if (NULL==(dst_p=H5I_object(H5T_NATIVE_FLOAT_g)))
HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
dst = &dst_p->shared->u.atomic;
/* Check that we can re-order the bytes correctly */
if (H5T_ORDER_LE!=H5T_native_order_g && H5T_ORDER_BE!=H5T_native_order_g)
HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order");
/* +Inf */
d=(uint8_t *)&H5T_NATIVE_FLOAT_POS_INF_g;
H5T_bit_set (d, dst->u.f.sign, (size_t)1, FALSE);
H5T_bit_set (d, dst->u.f.epos, dst->u.f.esize, TRUE);
H5T_bit_set (d, dst->u.f.mpos, dst->u.f.msize, FALSE);
/* Swap the bytes if the machine architecture is big-endian */
if (H5T_ORDER_BE==H5T_native_order_g) {
half_size = dst_p->shared->size/2;
for (u=0; u<half_size; u++) {
uint8_t tmp = d[dst_p->shared->size-(u+1)];
d[dst_p->shared->size-(u+1)] = d[u];
d[u] = tmp;
}
}
/* -Inf */
d=(uint8_t *)&H5T_NATIVE_FLOAT_NEG_INF_g;
H5T_bit_set (d, dst->u.f.sign, (size_t)1, TRUE);
H5T_bit_set (d, dst->u.f.epos, dst->u.f.esize, TRUE);
H5T_bit_set (d, dst->u.f.mpos, dst->u.f.msize, FALSE);
/* Swap the bytes if the machine architecture is big-endian */
if (H5T_ORDER_BE==H5T_native_order_g) {
half_size = dst_p->shared->size/2;
for (u=0; u<half_size; u++) {
uint8_t tmp = d[dst_p->shared->size-(u+1)];
d[dst_p->shared->size-(u+1)] = d[u];
d[u] = tmp;
}
}
/* Get the double datatype */
if (NULL==(dst_p=H5I_object(H5T_NATIVE_DOUBLE_g)))
HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
dst = &dst_p->shared->u.atomic;
/* Check that we can re-order the bytes correctly */
if (H5T_ORDER_LE!=H5T_native_order_g && H5T_ORDER_BE!=H5T_native_order_g)
HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order");
/* +Inf */
d=(uint8_t *)&H5T_NATIVE_DOUBLE_POS_INF_g;
H5T_bit_set (d, dst->u.f.sign, (size_t)1, FALSE);
H5T_bit_set (d, dst->u.f.epos, dst->u.f.esize, TRUE);
H5T_bit_set (d, dst->u.f.mpos, dst->u.f.msize, FALSE);
/* Swap the bytes if the machine architecture is big-endian */
if (H5T_ORDER_BE==H5T_native_order_g) {
half_size = dst_p->shared->size/2;
for (u=0; u<half_size; u++) {
uint8_t tmp = d[dst_p->shared->size-(u+1)];
d[dst_p->shared->size-(u+1)] = d[u];
d[u] = tmp;
}
}
/* -Inf */
d=(uint8_t *)&H5T_NATIVE_DOUBLE_NEG_INF_g;
H5T_bit_set (d, dst->u.f.sign, (size_t)1, TRUE);
H5T_bit_set (d, dst->u.f.epos, dst->u.f.esize, TRUE);
H5T_bit_set (d, dst->u.f.mpos, dst->u.f.msize, FALSE);
/* Swap the bytes if the machine architecture is big-endian */
if (H5T_ORDER_BE==H5T_native_order_g) {
half_size = dst_p->shared->size/2;
for (u=0; u<half_size; u++) {
uint8_t tmp = d[dst_p->shared->size-(u+1)];
d[dst_p->shared->size-(u+1)] = d[u];
d[u] = tmp;
}
}
done:
FUNC_LEAVE_NOAPI(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5T_init_hw
*
* Purpose: Perform hardware specific [floating-point] initialization
*
* Return: Success: non-negative
*
* Failure: negative
*
* Programmer: Quincey Koziol
* Monday, November 24, 2003
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
H5T_init_hw(void)
{
#ifdef H5_HAVE_GET_FPC_CSR
union fpc_csr csr; /* Union to hold results of floating-point status register query */
#endif /* H5_HAVE_GET_FPC_CSR */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_init_hw);
#ifdef H5_HAVE_GET_FPC_CSR
/* [This code is specific to SGI machines] */
/* Get the floating-point status register */
csr.fc_word=get_fpc_csr();
/* If the "flush denormalized values to zero" flag is set, unset it */
if(csr.fc_struct.flush) {
csr.fc_struct.flush=0;
set_fpc_csr(csr.fc_word);
} /* end if */
#endif /* H5_HAVE_GET_FPC_CSR */
FUNC_LEAVE_NOAPI(ret_value);
}
/*--------------------------------------------------------------------------
NAME
H5T_init_interface -- Initialize interface-specific information
USAGE
herr_t H5T_init_interface()
RETURNS
Non-negative on success/Negative on failure
DESCRIPTION
Initializes any interface-specific data or routines.
--------------------------------------------------------------------------*/
herr_t
H5T_init_interface(void)
{
H5T_t *native_schar=NULL; /* Datatype structure for native signed char */
H5T_t *native_uchar=NULL; /* Datatype structure for native unsigned char */
H5T_t *native_short=NULL; /* Datatype structure for native short */
H5T_t *native_ushort=NULL; /* Datatype structure for native unsigned short */
H5T_t *native_int=NULL; /* Datatype structure for native int */
H5T_t *native_uint=NULL; /* Datatype structure for native unsigned int */
H5T_t *native_long=NULL; /* Datatype structure for native long */
H5T_t *native_ulong=NULL; /* Datatype structure for native unsigned long */
H5T_t *native_llong=NULL; /* Datatype structure for native long long */
H5T_t *native_ullong=NULL; /* Datatype structure for native unsigned long long */
H5T_t *native_float=NULL; /* Datatype structure for native float */
H5T_t *native_double=NULL; /* Datatype structure for native double */
H5T_t *std_u8le=NULL; /* Datatype structure for unsigned 8-bit little-endian integer */
H5T_t *std_u8be=NULL; /* Datatype structure for unsigned 8-bit big-endian integer */
H5T_t *std_u16le=NULL; /* Datatype structure for unsigned 16-bit little-endian integer */
H5T_t *std_u16be=NULL; /* Datatype structure for unsigned 16-bit big-endian integer */
H5T_t *std_u32le=NULL; /* Datatype structure for unsigned 32-bit little-endian integer */
H5T_t *std_u32be=NULL; /* Datatype structure for unsigned 32-bit big-endian integer */
H5T_t *std_i32le=NULL; /* Datatype structure for signed 32-bit little-endian integer */
H5T_t *std_u64le=NULL; /* Datatype structure for unsigned 64-bit little-endian integer */
H5T_t *std_u64be=NULL; /* Datatype structure for unsigned 64-bit big-endian integer */
H5T_t *ieee_f64le=NULL; /* Datatype structure for IEEE 64-bit little-endian floating-point */
H5T_t *dt = NULL;
H5T_t *fixedpt=NULL; /* Datatype structure for native int */
H5T_t *floatpt=NULL; /* Datatype structure for native float */
H5T_t *string=NULL; /* Datatype structure for C string */
H5T_t *bitfield=NULL; /* Datatype structure for bitfield */
H5T_t *compound=NULL; /* Datatype structure for compound objects */
H5T_t *enum_type=NULL; /* Datatype structure for enum objects */
H5T_t *vlen=NULL; /* Datatype structure for vlen objects */
H5T_t *array=NULL; /* Datatype structure for array objects */
hsize_t dim[1]={1}; /* Dimension info for array datatype */
herr_t status;
unsigned copied_dtype=1; /* Flag to indicate whether datatype was copied or allocated (for error cleanup) */
herr_t ret_value=SUCCEED;
FUNC_ENTER_NOAPI_NOINIT(H5T_init_interface);
/* Initialize the atom group for the file IDs */
if (H5I_init_group(H5I_DATATYPE, (size_t)H5I_DATATYPEID_HASHSIZE, H5T_RESERVED_ATOMS, (H5I_free_t)H5T_close)<0)
HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize interface");
/* Make certain there aren't too many classes of datatypes defined */
/* Only 16 (numbered 0-15) are supported in the current file format */
assert(H5T_NCLASSES<16);
/* Perform any necessary hardware initializations */
if(H5T_init_hw()<0)
HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize interface");
/*
* Initialize pre-defined native data types from code generated during
* the library configuration by H5detect.
*/
if (H5TN_init_interface()<0)
HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize interface");
/* Get the atomic datatype structures needed by the initialization code below */
if (NULL==(native_schar=H5I_object(H5T_NATIVE_SCHAR_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
if (NULL==(native_uchar=H5I_object(H5T_NATIVE_UCHAR_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
if (NULL==(native_short=H5I_object(H5T_NATIVE_SHORT_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
if (NULL==(native_ushort=H5I_object(H5T_NATIVE_USHORT_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
if (NULL==(native_int=H5I_object(H5T_NATIVE_INT_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
if (NULL==(native_uint=H5I_object(H5T_NATIVE_UINT_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
if (NULL==(native_long=H5I_object(H5T_NATIVE_LONG_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
if (NULL==(native_ulong=H5I_object(H5T_NATIVE_ULONG_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
if (NULL==(native_llong=H5I_object(H5T_NATIVE_LLONG_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
if (NULL==(native_ullong=H5I_object(H5T_NATIVE_ULLONG_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
if (NULL==(native_float=H5I_object(H5T_NATIVE_FLOAT_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
if (NULL==(native_double=H5I_object(H5T_NATIVE_DOUBLE_g)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object");
/*------------------------------------------------------------
* Native types
*------------------------------------------------------------
*/
/* 1-byte bit field */
H5T_INIT_TYPE(BITFIELD,H5T_NATIVE_B8_g,COPY,native_uint,SET,1)
/* 2-byte bit field */
H5T_INIT_TYPE(BITFIELD,H5T_NATIVE_B16_g,COPY,native_uint,SET,2)
/* 4-byte bit field */
H5T_INIT_TYPE(BITFIELD,H5T_NATIVE_B32_g,COPY,native_uint,SET,4)
/* 8-byte bit field */
H5T_INIT_TYPE(BITFIELD,H5T_NATIVE_B64_g,COPY,native_uint,SET,8)
/* haddr_t */
H5T_INIT_TYPE(OFFSET,H5T_NATIVE_HADDR_g,COPY,native_uint,SET,sizeof(haddr_t))
/* hsize_t */
H5T_INIT_TYPE(OFFSET,H5T_NATIVE_HSIZE_g,COPY,native_uint,SET,sizeof(hsize_t))
/* hssize_t */
H5T_INIT_TYPE(OFFSET,H5T_NATIVE_HSSIZE_g,COPY,native_int,SET,sizeof(hssize_t))
/* herr_t */
H5T_INIT_TYPE(OFFSET,H5T_NATIVE_HERR_g,COPY,native_int,SET,sizeof(herr_t))
/* hbool_t */
H5T_INIT_TYPE(OFFSET,H5T_NATIVE_HBOOL_g,COPY,native_int,SET,sizeof(hbool_t))
/*------------------------------------------------------------
* IEEE Types
*------------------------------------------------------------
*/
/* IEEE 4-byte little-endian float */
H5T_INIT_TYPE(FLOATLE,H5T_IEEE_F32LE_g,COPY,native_double,SET,4)
/* IEEE 4-byte big-endian float */
H5T_INIT_TYPE(FLOATBE,H5T_IEEE_F32BE_g,COPY,native_double,SET,4)
/* IEEE 8-byte little-endian float */
H5T_INIT_TYPE(DOUBLELE,H5T_IEEE_F64LE_g,COPY,native_double,SET,8)
ieee_f64le=dt; /* Keep type for later */
/* IEEE 8-byte big-endian float */
H5T_INIT_TYPE(DOUBLEBE,H5T_IEEE_F64BE_g,COPY,native_double,SET,8)
/*------------------------------------------------------------
* Other "standard" types
*------------------------------------------------------------
*/
/* 1-byte little-endian (endianness is irrelevant) signed integer */
H5T_INIT_TYPE(SINTLE,H5T_STD_I8LE_g,COPY,native_int,SET,1)
/* 1-byte big-endian (endianness is irrelevant) signed integer */
H5T_INIT_TYPE(SINTBE,H5T_STD_I8BE_g,COPY,native_int,SET,1)
/* 2-byte little-endian signed integer */
H5T_INIT_TYPE(SINTLE,H5T_STD_I16LE_g,COPY,native_int,SET,2)
/* 2-byte big-endian signed integer */
H5T_INIT_TYPE(SINTBE,H5T_STD_I16BE_g,COPY,native_int,SET,2)
/* 4-byte little-endian signed integer */
H5T_INIT_TYPE(SINTLE,H5T_STD_I32LE_g,COPY,native_int,SET,4)
std_i32le=dt; /* Keep type for later */
/* 4-byte big-endian signed integer */
H5T_INIT_TYPE(SINTBE,H5T_STD_I32BE_g,COPY,native_int,SET,4)
/* 8-byte little-endian signed integer */
H5T_INIT_TYPE(SINTLE,H5T_STD_I64LE_g,COPY,native_int,SET,8)
/* 8-byte big-endian signed integer */
H5T_INIT_TYPE(SINTBE,H5T_STD_I64BE_g,COPY,native_int,SET,8)
/* 1-byte little-endian (endianness is irrelevant) unsigned integer */
H5T_INIT_TYPE(UINTLE,H5T_STD_U8LE_g,COPY,native_uint,SET,1)
std_u8le=dt; /* Keep type for later */
/* 1-byte big-endian (endianness is irrelevant) unsigned integer */
H5T_INIT_TYPE(UINTBE,H5T_STD_U8BE_g,COPY,native_uint,SET,1)
std_u8be=dt; /* Keep type for later */
/* 2-byte little-endian unsigned integer */
H5T_INIT_TYPE(UINTLE,H5T_STD_U16LE_g,COPY,native_uint,SET,2)
std_u16le=dt; /* Keep type for later */
/* 2-byte big-endian unsigned integer */
H5T_INIT_TYPE(UINTBE,H5T_STD_U16BE_g,COPY,native_uint,SET,2)
std_u16be=dt; /* Keep type for later */
/* 4-byte little-endian unsigned integer */
H5T_INIT_TYPE(UINTLE,H5T_STD_U32LE_g,COPY,native_uint,SET,4)
std_u32le=dt; /* Keep type for later */
/* 4-byte big-endian unsigned integer */
H5T_INIT_TYPE(UINTBE,H5T_STD_U32BE_g,COPY,native_uint,SET,4)
std_u32be=dt; /* Keep type for later */
/* 8-byte little-endian unsigned integer */
H5T_INIT_TYPE(UINTLE,H5T_STD_U64LE_g,COPY,native_uint,SET,8)
std_u64le=dt; /* Keep type for later */
/* 8-byte big-endian unsigned integer */
H5T_INIT_TYPE(UINTBE,H5T_STD_U64BE_g,COPY,native_uint,SET,8)
std_u64be=dt; /* Keep type for later */
/*------------------------------------------------------------
* Little- & Big-endian bitfields
*------------------------------------------------------------
*/
/* little-endian (order is irrelevant) 8-bit bitfield */
H5T_INIT_TYPE(BITFIELD,H5T_STD_B8LE_g,COPY,std_u8le,NOSET,-)
bitfield=dt; /* Keep type for later */
/* big-endian (order is irrelevant) 8-bit bitfield */
H5T_INIT_TYPE(BITFIELD,H5T_STD_B8BE_g,COPY,std_u8be,NOSET,-)
/* Little-endian 16-bit bitfield */
H5T_INIT_TYPE(BITFIELD,H5T_STD_B16LE_g,COPY,std_u16le,NOSET,-)
/* Big-endian 16-bit bitfield */
H5T_INIT_TYPE(BITFIELD,H5T_STD_B16BE_g,COPY,std_u16be,NOSET,-)
/* Little-endian 32-bit bitfield */
H5T_INIT_TYPE(BITFIELD,H5T_STD_B32LE_g,COPY,std_u32le,NOSET,-)
/* Big-endian 32-bit bitfield */
H5T_INIT_TYPE(BITFIELD,H5T_STD_B32BE_g,COPY,std_u32be,NOSET,-)
/* Little-endian 64-bit bitfield */
H5T_INIT_TYPE(BITFIELD,H5T_STD_B64LE_g,COPY,std_u64le,NOSET,-)
/* Big-endian 64-bit bitfield */
H5T_INIT_TYPE(BITFIELD,H5T_STD_B64BE_g,COPY,std_u64be,NOSET,-)
/*------------------------------------------------------------
* The Unix architecture for dates and times.
*------------------------------------------------------------
*/
/* Little-endian 32-bit UNIX time_t */
H5T_INIT_TYPE(TIME,H5T_UNIX_D32LE_g,COPY,std_u32le,NOSET,-)
/* Big-endian 32-bit UNIX time_t */
H5T_INIT_TYPE(TIME,H5T_UNIX_D32BE_g,COPY,std_u32be,NOSET,-)
/* Little-endian 64-bit UNIX time_t */
H5T_INIT_TYPE(TIME,H5T_UNIX_D64LE_g,COPY,std_u64le,NOSET,-)
/* Big-endian 64-bit UNIX time_t */
H5T_INIT_TYPE(TIME,H5T_UNIX_D64BE_g,COPY,std_u64be,NOSET,-)
/* Indicate that the types that are created from here down are allocated
* H5FL_ALLOC(), not copied with H5T_copy()
*/
copied_dtype=0;
/* Opaque data */
H5T_INIT_TYPE(OPAQ,H5T_NATIVE_OPAQUE_g,ALLOC,-,SET,1)
/*------------------------------------------------------------
* The `C' architecture
*------------------------------------------------------------
*/
/* One-byte character string */
H5T_INIT_TYPE(CSTRING,H5T_C_S1_g,ALLOC,-,SET,1)
string=dt; /* Keep type for later */
/*------------------------------------------------------------
* The `Fortran' architecture
*------------------------------------------------------------
*/
/* One-byte character string */
H5T_INIT_TYPE(FORSTRING,H5T_FORTRAN_S1_g,ALLOC,-,SET,1)
/*------------------------------------------------------------
* Pointer types
*------------------------------------------------------------
*/
/* Object pointer (i.e. object header address in file) */
H5T_INIT_TYPE(OBJREF,H5T_STD_REF_OBJ_g,ALLOC,-,SET,H5R_OBJ_REF_BUF_SIZE)
/* Dataset Region pointer (i.e. selection inside a dataset) */
H5T_INIT_TYPE(REGREF,H5T_STD_REF_DSETREG_g,ALLOC,-,SET,H5R_DSET_REG_REF_BUF_SIZE)
/*
* Register conversion functions beginning with the most general and
* ending with the most specific.
*/
fixedpt = native_int;
floatpt = native_float;
if (NULL == (compound = H5T_create(H5T_COMPOUND, (size_t)1)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
if (NULL == (enum_type = H5T_create(H5T_ENUM, (size_t)1)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
if (NULL == (vlen = H5T_vlen_create(native_int)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
if (NULL == (array = H5T_array_create(native_int,1,dim,NULL)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
status = 0;
status |= H5T_register(H5T_PERS_SOFT, "i_i", fixedpt, fixedpt, H5T_conv_i_i, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_SOFT, "f_f", floatpt, floatpt, H5T_conv_f_f, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_SOFT, "s_s", string, string, H5T_conv_s_s, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_SOFT, "b_b", bitfield, bitfield, H5T_conv_b_b, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_SOFT, "ibo", fixedpt, fixedpt, H5T_conv_order, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_SOFT, "ibo(opt)", fixedpt, fixedpt, H5T_conv_order_opt, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_SOFT, "fbo", floatpt, floatpt, H5T_conv_order, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_SOFT, "fbo(opt)", floatpt, floatpt, H5T_conv_order_opt, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_SOFT, "struct(no-opt)", compound, compound, H5T_conv_struct, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_SOFT, "struct(opt)", compound, compound, H5T_conv_struct_opt, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_SOFT, "enum", enum_type, enum_type, H5T_conv_enum, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_SOFT, "vlen", vlen, vlen, H5T_conv_vlen, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_SOFT, "array", array, array, H5T_conv_array, H5AC_dxpl_id);
/* Custom conversion for 32-bit ints to 64-bit floats (undocumented) */
status |= H5T_register(H5T_PERS_HARD, "u32le_f64le", std_u32le, ieee_f64le, H5T_conv_i32le_f64le, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "i32le_f64le", std_i32le, ieee_f64le, H5T_conv_i32le_f64le, H5AC_dxpl_id);
/*
* Native conversions should be listed last since we can use hardware to
* perform the conversion. We list the odd types like `llong', `long',
* and `short' before the usual types like `int' and `char' so that when
* diagnostics are printed we favor the usual names over the odd names
* when two or more types are the same size.
*/
/* floating point */
status |= H5T_register(H5T_PERS_HARD, "flt_dbl", native_float, native_double, H5T_conv_float_double, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "dbl_flt", native_double, native_float, H5T_conv_double_float, H5AC_dxpl_id);
/* from long_long */
status |= H5T_register(H5T_PERS_HARD, "llong_ullong", native_llong, native_ullong, H5T_conv_llong_ullong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ullong_llong", native_ullong, native_llong, H5T_conv_ullong_llong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "llong_long", native_llong, native_long, H5T_conv_llong_long, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "llong_ulong", native_llong, native_ulong, H5T_conv_llong_ulong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ullong_long", native_ullong, native_long, H5T_conv_ullong_long, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ullong_ulong", native_ullong, native_ulong, H5T_conv_ullong_ulong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "llong_short", native_llong, native_short, H5T_conv_llong_short, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "llong_ushort", native_llong, native_ushort, H5T_conv_llong_ushort, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ullong_short", native_ullong, native_short, H5T_conv_ullong_short, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ullong_ushort", native_ullong, native_ushort, H5T_conv_ullong_ushort, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "llong_int", native_llong, native_int, H5T_conv_llong_int, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "llong_uint", native_llong, native_uint, H5T_conv_llong_uint, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ullong_int", native_ullong, native_int, H5T_conv_ullong_int, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ullong_uint", native_ullong, native_uint, H5T_conv_ullong_uint, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "llong_schar", native_llong, native_schar, H5T_conv_llong_schar, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "llong_uchar", native_llong, native_uchar, H5T_conv_llong_uchar, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ullong_schar", native_ullong, native_schar, H5T_conv_ullong_schar, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ullong_uchar", native_ullong, native_uchar, H5T_conv_ullong_uchar, H5AC_dxpl_id);
/* From long */
status |= H5T_register(H5T_PERS_HARD, "long_llong", native_long, native_llong, H5T_conv_long_llong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "long_ullong", native_long, native_ullong, H5T_conv_long_ullong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ulong_llong", native_ulong, native_llong, H5T_conv_ulong_llong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ulong_ullong", native_ulong, native_ullong, H5T_conv_ulong_ullong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "long_ulong", native_long, native_ulong, H5T_conv_long_ulong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ulong_long", native_ulong, native_long, H5T_conv_ulong_long, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "long_short", native_long, native_short, H5T_conv_long_short, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "long_ushort", native_long, native_ushort, H5T_conv_long_ushort, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ulong_short", native_ulong, native_short, H5T_conv_ulong_short, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ulong_ushort", native_ulong, native_ushort, H5T_conv_ulong_ushort, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "long_int", native_long, native_int, H5T_conv_long_int, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "long_uint", native_long, native_uint, H5T_conv_long_uint, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ulong_int", native_ulong, native_int, H5T_conv_ulong_int, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ulong_uint", native_ulong, native_uint, H5T_conv_ulong_uint, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "long_schar", native_long, native_schar, H5T_conv_long_schar, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "long_uchar", native_long, native_uchar, H5T_conv_long_uchar, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ulong_schar", native_ulong, native_schar, H5T_conv_ulong_schar, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ulong_uchar", native_ulong, native_uchar, H5T_conv_ulong_uchar, H5AC_dxpl_id);
/* From short */
status |= H5T_register(H5T_PERS_HARD, "short_llong", native_short, native_llong, H5T_conv_short_llong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "short_ullong", native_short, native_ullong, H5T_conv_short_ullong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ushort_llong", native_ushort, native_llong, H5T_conv_ushort_llong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ushort_ullong", native_ushort, native_ullong, H5T_conv_ushort_ullong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "short_long", native_short, native_long, H5T_conv_short_long, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "short_ulong", native_short, native_ulong, H5T_conv_short_ulong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ushort_long", native_ushort, native_long, H5T_conv_ushort_long, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ushort_ulong", native_ushort, native_ulong, H5T_conv_ushort_ulong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "short_ushort", native_short, native_ushort, H5T_conv_short_ushort, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ushort_short", native_ushort, native_short, H5T_conv_ushort_short, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "short_int", native_short, native_int, H5T_conv_short_int, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "short_uint", native_short, native_uint, H5T_conv_short_uint, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ushort_int", native_ushort, native_int, H5T_conv_ushort_int, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ushort_uint", native_ushort, native_uint, H5T_conv_ushort_uint, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "short_schar", native_short, native_schar, H5T_conv_short_schar, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "short_uchar", native_short, native_uchar, H5T_conv_short_uchar, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ushort_schar", native_ushort, native_schar, H5T_conv_ushort_schar, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "ushort_uchar", native_ushort, native_uchar, H5T_conv_ushort_uchar, H5AC_dxpl_id);
/* From int */
status |= H5T_register(H5T_PERS_HARD, "int_llong", native_int, native_llong, H5T_conv_int_llong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "int_ullong", native_int, native_ullong, H5T_conv_int_ullong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uint_llong", native_uint, native_llong, H5T_conv_uint_llong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uint_ullong", native_uint, native_ullong, H5T_conv_uint_ullong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "int_long", native_int, native_long, H5T_conv_int_long, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "int_ulong", native_int, native_ulong, H5T_conv_int_ulong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uint_long", native_uint, native_long, H5T_conv_uint_long, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uint_ulong", native_uint, native_ulong, H5T_conv_uint_ulong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "int_short", native_int, native_short, H5T_conv_int_short, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "int_ushort", native_int, native_ushort, H5T_conv_int_ushort, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uint_short", native_uint, native_short, H5T_conv_uint_short, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uint_ushort", native_uint, native_ushort, H5T_conv_uint_ushort, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "int_uint", native_int, native_uint, H5T_conv_int_uint, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uint_int", native_uint, native_int, H5T_conv_uint_int, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "int_schar", native_int, native_schar, H5T_conv_int_schar, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "int_uchar", native_int, native_uchar, H5T_conv_int_uchar, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uint_schar", native_uint, native_schar, H5T_conv_uint_schar, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uint_uchar", native_uint, native_uchar, H5T_conv_uint_uchar, H5AC_dxpl_id);
/* From char */
status |= H5T_register(H5T_PERS_HARD, "schar_llong", native_schar, native_llong, H5T_conv_schar_llong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "schar_ullong", native_schar, native_ullong, H5T_conv_schar_ullong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uchar_llong", native_uchar, native_llong, H5T_conv_uchar_llong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uchar_ullong", native_uchar, native_ullong, H5T_conv_uchar_ullong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "schar_long", native_schar, native_long, H5T_conv_schar_long, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "schar_ulong", native_schar, native_ulong, H5T_conv_schar_ulong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uchar_long", native_uchar, native_long, H5T_conv_uchar_long, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uchar_ulong", native_uchar, native_ulong, H5T_conv_uchar_ulong, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "schar_short", native_schar, native_short, H5T_conv_schar_short, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "schar_ushort", native_schar, native_ushort, H5T_conv_schar_ushort, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uchar_short", native_uchar, native_short, H5T_conv_uchar_short, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uchar_ushort", native_uchar, native_ushort, H5T_conv_uchar_ushort, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "schar_int", native_schar, native_int, H5T_conv_schar_int, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "schar_uint", native_schar, native_uint, H5T_conv_schar_uint, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uchar_int", native_uchar, native_int, H5T_conv_uchar_int, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uchar_uint", native_uchar, native_uint, H5T_conv_uchar_uint, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "schar_uchar", native_schar, native_uchar, H5T_conv_schar_uchar, H5AC_dxpl_id);
status |= H5T_register(H5T_PERS_HARD, "uchar_schar", native_uchar, native_schar, H5T_conv_uchar_schar, H5AC_dxpl_id);
/*
* The special no-op conversion is the fastest, so we list it last. The
* data types we use are not important as long as the source and
* destination are equal.
*/
status |= H5T_register(H5T_PERS_HARD, "no-op", native_int, native_int, H5T_conv_noop, H5AC_dxpl_id);
/* Initialize the +/- Infinity values for floating-point types */
status |= H5T_init_inf();
if (status<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to register conversion function(s)");
done:
/* General cleanup */
if (compound!=NULL)
H5T_close(compound);
if (enum_type!=NULL)
H5T_close(enum_type);
if (vlen!=NULL)
H5T_close(vlen);
if (array!=NULL)
H5T_close(array);
/* Error cleanup */
if(ret_value<0) {
if(dt!=NULL) {
/* Check if we should call H5T_close or H5FL_FREE */
if(copied_dtype)
H5T_close(dt);
else
{
H5FL_FREE(H5T_shared_t, dt->shared);
H5FL_FREE(H5T_t,dt);
}
} /* end if */
} /* end if */
FUNC_LEAVE_NOAPI(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5T_unlock_cb
*
* Purpose: Clear the immutable flag for a data type. This function is
* called when the library is closing in order to unlock all
* registered data types and thus make them free-able.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Monday, April 27, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static int
H5T_unlock_cb (void *_dt, hid_t UNUSED id, void UNUSED *key)
{
H5T_t *dt = (H5T_t *)_dt;
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_unlock_cb);
assert (dt);
if (H5T_STATE_IMMUTABLE==dt->shared->state)
dt->shared->state = H5T_STATE_RDONLY;
FUNC_LEAVE_NOAPI(SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5T_term_interface
*
* Purpose: Close this interface.
*
* Return: Success: Positive if any action might have caused a
* change in some other interface; zero
* otherwise.
*
* Failure: Negative
*
* Programmer: Robb Matzke
* Friday, November 20, 1998
*
* Modifications:
* Robb Matzke, 1998-06-11
* Statistics are only printed for conversion functions that were
* called.
*-------------------------------------------------------------------------
*/
int
H5T_term_interface(void)
{
int i, nprint=0, n=0;
H5T_path_t *path = NULL;
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_term_interface);
if (H5_interface_initialize_g) {
/* Unregister all conversion functions */
for (i=0; i<H5T_g.npaths; i++) {
path = H5T_g.path[i];
assert (path);
if (path->func) {
H5T_print_stats(path, &nprint/*in,out*/);
path->cdata.command = H5T_CONV_FREE;
if ((path->func)(FAIL, FAIL, &(path->cdata),
(size_t)0, (size_t)0, (size_t)0,
NULL, NULL,H5AC_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
H5E_clear(); /*ignore the error*/
}
}
if(path->src)
H5T_close (path->src);
if(path->dst)
H5T_close (path->dst);
H5FL_FREE(H5T_path_t,path);
H5T_g.path[i] = NULL;
}
/* Clear conversion tables */
H5T_g.path = H5MM_xfree(H5T_g.path);
H5T_g.npaths = H5T_g.apaths = 0;
H5T_g.soft = H5MM_xfree(H5T_g.soft);
H5T_g.nsoft = H5T_g.asoft = 0;
/* Unlock all datatypes, then free them */
H5I_search (H5I_DATATYPE, H5T_unlock_cb, NULL);
H5I_destroy_group(H5I_DATATYPE);
/* Reset all the datatype IDs */
H5T_IEEE_F32BE_g = FAIL;
H5T_IEEE_F32LE_g = FAIL;
H5T_IEEE_F64BE_g = FAIL;
H5T_IEEE_F64LE_g = FAIL;
H5T_STD_I8BE_g = FAIL;
H5T_STD_I8LE_g = FAIL;
H5T_STD_I16BE_g = FAIL;
H5T_STD_I16LE_g = FAIL;
H5T_STD_I32BE_g = FAIL;
H5T_STD_I32LE_g = FAIL;
H5T_STD_I64BE_g = FAIL;
H5T_STD_I64LE_g = FAIL;
H5T_STD_U8BE_g = FAIL;
H5T_STD_U8LE_g = FAIL;
H5T_STD_U16BE_g = FAIL;
H5T_STD_U16LE_g = FAIL;
H5T_STD_U32BE_g = FAIL;
H5T_STD_U32LE_g = FAIL;
H5T_STD_U64BE_g = FAIL;
H5T_STD_U64LE_g = FAIL;
H5T_STD_B8BE_g = FAIL;
H5T_STD_B8LE_g = FAIL;
H5T_STD_B16BE_g = FAIL;
H5T_STD_B16LE_g = FAIL;
H5T_STD_B32BE_g = FAIL;
H5T_STD_B32LE_g = FAIL;
H5T_STD_B64BE_g = FAIL;
H5T_STD_B64LE_g = FAIL;
H5T_STD_REF_OBJ_g = FAIL;
H5T_STD_REF_DSETREG_g = FAIL;
H5T_UNIX_D32BE_g = FAIL;
H5T_UNIX_D32LE_g = FAIL;
H5T_UNIX_D64BE_g = FAIL;
H5T_UNIX_D64LE_g = FAIL;
H5T_C_S1_g = FAIL;
H5T_FORTRAN_S1_g = FAIL;
H5T_NATIVE_SCHAR_g = FAIL;
H5T_NATIVE_UCHAR_g = FAIL;
H5T_NATIVE_SHORT_g = FAIL;
H5T_NATIVE_USHORT_g = FAIL;
H5T_NATIVE_INT_g = FAIL;
H5T_NATIVE_UINT_g = FAIL;
H5T_NATIVE_LONG_g = FAIL;
H5T_NATIVE_ULONG_g = FAIL;
H5T_NATIVE_LLONG_g = FAIL;
H5T_NATIVE_ULLONG_g = FAIL;
H5T_NATIVE_FLOAT_g = FAIL;
H5T_NATIVE_DOUBLE_g = FAIL;
H5T_NATIVE_LDOUBLE_g = FAIL;
H5T_NATIVE_B8_g = FAIL;
H5T_NATIVE_B16_g = FAIL;
H5T_NATIVE_B32_g = FAIL;
H5T_NATIVE_B64_g = FAIL;
H5T_NATIVE_OPAQUE_g = FAIL;
H5T_NATIVE_HADDR_g = FAIL;
H5T_NATIVE_HSIZE_g = FAIL;
H5T_NATIVE_HSSIZE_g = FAIL;
H5T_NATIVE_HERR_g = FAIL;
H5T_NATIVE_HBOOL_g = FAIL;
H5T_NATIVE_INT8_g = FAIL;
H5T_NATIVE_UINT8_g = FAIL;
H5T_NATIVE_INT_LEAST8_g = FAIL;
H5T_NATIVE_UINT_LEAST8_g = FAIL;
H5T_NATIVE_INT_FAST8_g = FAIL;
H5T_NATIVE_UINT_FAST8_g = FAIL;
H5T_NATIVE_INT16_g = FAIL;
H5T_NATIVE_UINT16_g = FAIL;
H5T_NATIVE_INT_LEAST16_g = FAIL;
H5T_NATIVE_UINT_LEAST16_g = FAIL;
H5T_NATIVE_INT_FAST16_g = FAIL;
H5T_NATIVE_UINT_FAST16_g = FAIL;
H5T_NATIVE_INT32_g = FAIL;
H5T_NATIVE_UINT32_g = FAIL;
H5T_NATIVE_INT_LEAST32_g = FAIL;
H5T_NATIVE_UINT_LEAST32_g = FAIL;
H5T_NATIVE_INT_FAST32_g = FAIL;
H5T_NATIVE_UINT_FAST32_g = FAIL;
H5T_NATIVE_INT64_g = FAIL;
H5T_NATIVE_UINT64_g = FAIL;
H5T_NATIVE_INT_LEAST64_g = FAIL;
H5T_NATIVE_UINT_LEAST64_g = FAIL;
H5T_NATIVE_INT_FAST64_g = FAIL;
H5T_NATIVE_UINT_FAST64_g = FAIL;
/* Mark interface as closed */
H5_interface_initialize_g = 0;
n = 1; /*H5I*/
}
FUNC_LEAVE_NOAPI(n);
}
/*-------------------------------------------------------------------------
* Function: H5Tcreate
*
* Purpose: Create a new type and initialize it to reasonable values.
* The type is a member of type class TYPE and is SIZE bytes.
*
* Return: Success: A new type identifier.
*
* Failure: Negative
*
* Errors:
* ARGS BADVALUE Invalid size.
* DATATYPE CANTINIT Can't create type.
* DATATYPE CANTREGISTER Can't register data type atom.
*
* Programmer: Robb Matzke
* Friday, December 5, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
hid_t
H5Tcreate(H5T_class_t type, size_t size)
{
H5T_t *dt = NULL;
hid_t ret_value;
FUNC_ENTER_API(H5Tcreate, FAIL);
H5TRACE2("i","Ttz",type,size);
/* check args */
if (size == 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid size");
/* create the type */
if (NULL == (dt = H5T_create(type, size)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create type");
/* Make it an atom */
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: H5Tcopy
*
* Purpose: Copies a data type. The resulting data type is not locked.
* The data type should be closed when no longer needed by
* calling H5Tclose().
*
* Return: Success: The ID of a new data type.
*
* Failure: Negative
*
* Programmer: Robb Matzke
* Tuesday, December 9, 1997
*
* Modifications:
*
* Robb Matzke, 4 Jun 1998
* The returned type is always transient and unlocked. If the TYPE_ID
* argument is a dataset instead of a data type then this function
* returns a transient, modifiable data type which is a copy of the
* dataset's data type.
*
*-------------------------------------------------------------------------
*/
hid_t
H5Tcopy(hid_t type_id)
{
H5T_t *dt = NULL;
H5T_t *new_dt = NULL;
H5D_t *dset = NULL;
hid_t ret_value;
FUNC_ENTER_API(H5Tcopy, FAIL);
H5TRACE1("i","i",type_id);
switch (H5I_get_type (type_id)) {
case H5I_DATATYPE:
/* The argument is a data type handle */
if (NULL==(dt=H5I_object (type_id)))
HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
break;
case H5I_DATASET:
/* The argument is a dataset handle */
if (NULL==(dset=H5I_object (type_id)))
HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset");
if (NULL==(dt=H5D_typeof (dset)))
HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get the dataset data type");
break;
default:
HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type or dataset");
} /* end switch */
/* Copy */
if (NULL == (new_dt = H5T_copy(dt, H5T_COPY_TRANSIENT)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy");
/* Atomize result */
if ((ret_value = H5I_register(H5I_DATATYPE, new_dt)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data type atom");
done:
if(ret_value<0) {
if(new_dt!=NULL)
H5T_close(new_dt);
} /* end if */
FUNC_LEAVE_API(ret_value);
} /* end H5Tcopy() */
/*-------------------------------------------------------------------------
* Function: H5Tclose
*
* Purpose: Frees a data type and all associated memory.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Tuesday, December 9, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5Tclose(hid_t type_id)
{
H5T_t *dt = NULL;
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_API(H5Tclose, FAIL);
H5TRACE1("e","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 (H5T_STATE_IMMUTABLE==dt->shared->state)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "immutable data type");
/* When the reference count reaches zero the resources are freed */
if (H5I_dec_ref(type_id) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "problem freeing id");
done:
FUNC_LEAVE_API(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5Tequal
*
* Purpose: Determines if two data types are equal.
*
* Return: Success: TRUE if equal, FALSE if unequal
*
* Failure: Negative
*
* Errors:
*
* Programmer: Robb Matzke
* Wednesday, December 10, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
htri_t
H5Tequal(hid_t type1_id, hid_t type2_id)
{
const H5T_t *dt1 = NULL;
const H5T_t *dt2 = NULL;
htri_t ret_value;
FUNC_ENTER_API(H5Tequal, FAIL);
H5TRACE2("t","ii",type1_id,type2_id);
/* check args */
if (NULL == (dt1 = H5I_object_verify(type1_id,H5I_DATATYPE)) ||
NULL == (dt2 = H5I_object_verify(type2_id,H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
ret_value = (0 == H5T_cmp(dt1, dt2, FALSE)) ? TRUE : FALSE;
done:
FUNC_LEAVE_API(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5Tlock
*
* Purpose: Locks a type, making it read only and non-destructable. This
* is normally done by the library for predefined data types so
* the application doesn't inadvertently change or delete a
* predefined type.
*
* Once a data type is locked it can never be unlocked unless
* the entire library is closed.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Friday, January 9, 1998
*
* Modifications:
*
* Robb Matzke, 1 Jun 1998
* It is illegal to lock a named data type since we must allow named
* types to be closed (to release file resources) but locking a type
* prevents that.
*-------------------------------------------------------------------------
*/
herr_t
H5Tlock(hid_t type_id)
{
H5T_t *dt = NULL;
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_API(H5Tlock, FAIL);
H5TRACE1("e","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 (H5T_STATE_NAMED==dt->shared->state || H5T_STATE_OPEN==dt->shared->state)
HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "unable to lock named data type");
if (H5T_lock (dt, TRUE)<0)
HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to lock transient data type");
done:
FUNC_LEAVE_API(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5Tget_class
*
* Purpose: Returns the data type class identifier for data type TYPE_ID.
*
* Return: Success: One of the non-negative data type class
* constants.
*
* Failure: H5T_NO_CLASS (Negative)
*
* Programmer: Robb Matzke
* Monday, December 8, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
H5T_class_t
H5Tget_class(hid_t type_id)
{
H5T_t *dt = NULL;
H5T_class_t ret_value; /* Return value */
FUNC_ENTER_API(H5Tget_class, H5T_NO_CLASS);
H5TRACE1("Tt","i",type_id);
/* Check args */
if (NULL == (dt = H5I_object_verify(type_id,H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a data type");
/* Set return value */
ret_value= H5T_get_class(dt, FALSE);
done:
FUNC_LEAVE_API(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5T_get_class
*
* Purpose: Returns the data type class identifier for a datatype ptr.
*
* Return: Success: One of the non-negative data type class
* constants.
*
* Failure: H5T_NO_CLASS (Negative)
*
* Programmer: Robb Matzke
* Monday, December 8, 1997
*
* Modifications:
* Broke out from H5Tget_class - QAK - 6/4/99
*
*-------------------------------------------------------------------------
*/
H5T_class_t
H5T_get_class(const H5T_t *dt, htri_t internal)
{
H5T_class_t ret_value;
FUNC_ENTER_NOAPI(H5T_get_class, H5T_NO_CLASS);
assert(dt);
/* Externally, a VL string is a string; internally, a VL string is a VL. */
if(internal) {
ret_value=dt->shared->type;
} else {
if(H5T_IS_VL_STRING(dt->shared))
ret_value=H5T_STRING;
else
ret_value=dt->shared->type;
}
done:
FUNC_LEAVE_NOAPI(ret_value);
} /* end H5T_get_class() */
/*-------------------------------------------------------------------------
* Function: H5Tdetect_class
*
* Purpose: Check whether a datatype contains (or is) a certain type of
* datatype.
*
* Return: TRUE (1) or FALSE (0) on success/Negative on failure
*
* Programmer: Quincey Koziol
* Wednesday, November 29, 2000
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
htri_t
H5Tdetect_class(hid_t type, H5T_class_t cls)
{
H5T_t *dt = NULL;
htri_t ret_value; /* Return value */
FUNC_ENTER_API(H5Tdetect_class, FAIL);
H5TRACE2("t","iTt",type,cls);
/* Check args */
if (NULL == (dt = H5I_object_verify(type,H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a data type");
if (!(cls>H5T_NO_CLASS && cls<H5T_NCLASSES))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a data type class");
/* Set return value. Consider VL string as a string for API, as a VL for
* internal use. */
if(H5T_IS_VL_STRING(dt->shared))
ret_value = (H5T_STRING==cls);
else
ret_value=H5T_detect_class(dt,cls);
done:
FUNC_LEAVE_API(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5T_detect_class
*
* Purpose: Check whether a datatype contains (or is) a certain type of
* datatype.
*
* Return: TRUE (1) or FALSE (0) on success/Negative on failure
*
* Programmer: Quincey Koziol
* Wednesday, November 29, 2000
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
htri_t
H5T_detect_class (const H5T_t *dt, H5T_class_t cls)
{
unsigned i;
htri_t ret_value=FALSE; /* Return value */
FUNC_ENTER_NOAPI(H5T_detect_class, FAIL);
assert(dt);
assert(cls>H5T_NO_CLASS && cls<H5T_NCLASSES);
/* Check if this type is the correct type */
if(dt->shared->type==cls)
HGOTO_DONE(TRUE);
/* check for types that might have the correct type as a component */
switch(dt->shared->type) {
case H5T_COMPOUND:
for (i=0; i<dt->shared->u.compnd.nmembs; i++) {
htri_t nested_ret; /* Return value from nested call */
/* Check if this field's type is the correct type */
if(dt->shared->u.compnd.memb[i].type->shared->type==cls)
HGOTO_DONE(TRUE);
/* Recurse if it's VL, compound, enum or array */
if(H5T_IS_COMPLEX(dt->shared->u.compnd.memb[i].type->shared->type))
if((nested_ret=H5T_detect_class(dt->shared->u.compnd.memb[i].type,cls))!=FALSE)
HGOTO_DONE(nested_ret);
} /* end for */
break;
case H5T_ARRAY:
case H5T_VLEN:
case H5T_ENUM:
HGOTO_DONE(H5T_detect_class(dt->shared->parent,cls));
default:
break;
} /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5Tis_variable_str
*
* Purpose: Check whether a datatype is a variable-length string
*
* Return: TRUE (1) or FALSE (0) on success/Negative on failure
*
* Programmer: Raymond Lu
* November 4, 2002
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
htri_t
H5Tis_variable_str(hid_t dtype_id)
{
H5T_t *dt; /* Datatype to query */
htri_t ret_value; /* Return value */
FUNC_ENTER_API(H5Tis_variable_str, FAIL);
H5TRACE1("t","i",dtype_id);
/* Check args */
if (NULL == (dt = H5I_object_verify(dtype_id,H5I_DATATYPE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
/* Set return value */
ret_value=H5T_IS_VL_STRING(dt->shared);
done:
FUNC_LEAVE_API(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5Tget_size
*
* Purpose: Determines the total size of a datatype in bytes.
*
* Return: Success: Size of the datatype in bytes. The size of
* datatype is the size of an instance of that
* datatype.
*
* Failure: 0 (valid datatypes are never zero size)
*
* Programmer: Robb Matzke
* Monday, December 8, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
size_t
H5Tget_size(hid_t type_id)
{
H5T_t *dt = NULL;
size_t ret_value;
FUNC_ENTER_API(H5Tget_size, 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 datatype");
/* size */
ret_value = H5T_get_size(dt);
done:
FUNC_LEAVE_API(ret_value);
} /* end H5Tget_size() */
/*-------------------------------------------------------------------------
* Function: H5Tset_size
*
* Purpose: Sets the total size in bytes for a datatype (this operation
* is not permitted on reference datatypes). If the size is
* decreased so that the significant bits of the datatype
* 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 datatype 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: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Wednesday, January 7, 1998
*
* Modifications:
* Robb Matzke, 22 Dec 1998
* Moved the real work into a private function.
*
*-------------------------------------------------------------------------
*/
herr_t
H5Tset_size(hid_t type_id, size_t size)
{
H5T_t *dt = NULL;
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_API(H5Tset_size, FAIL);
H5TRACE2("e","iz",type_id,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->shared->state)
HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only");
if (size <= 0 && size!=H5T_VARIABLE)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "size must be positive");
if (size == H5T_VARIABLE && dt->shared->type!=H5T_STRING)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "only strings may be variable length");
if (H5T_ENUM==dt->shared->type && dt->shared->u.enumer.nmembs>0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined");
if (H5T_REFERENCE==dt->shared->type)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for this datatype");
if (size==0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "can't adjust size to 0");
/* Do the work */
if (H5T_set_size(dt, size)<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set size for data type");
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->shared->parent)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "not a derived data type");
if (NULL==(ret_value=H5T_copy(dt->shared->parent, H5T_COPY_ALL)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy parent data type");
done:
FUNC_LEAVE_NOAPI(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_NOAPI_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) {
/* Only bother to register the path if it's not a no-op path (for this machine) */
if(H5T_cmp(src, dst, FALSE)) {
/* 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; i<H5T_g.npaths; i++) {
if (new_path != H5T_g.path[i])
H5T_g.path[i]->cdata.recalc = TRUE;
} /* end for */
} /* end if */
} 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, (size_t)H5T_NAMELEN);
H5T_g.soft[H5T_g.nsoft].name[H5T_NAMELEN-1] = '\0';
H5T_g.soft[H5T_g.nsoft].src = src->shared->type;
H5T_g.soft[H5T_g.nsoft].dst = dst->shared->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; i<H5T_g.npaths; i++) {
old_path = H5T_g.path[i];
assert(old_path);
/* Does the new soft conversion function apply to this path? */
if (old_path->is_hard ||
old_path->src->shared->type!=src->shared->type ||
old_path->dst->shared->type!=dst->shared->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, (size_t)0, (size_t)0, (size_t)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, (size_t)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),
(size_t)0, (size_t)0, (size_t)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
*
*-------------------------------------------------------------------------
*/
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_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->shared->type!=soft->src) continue;
if (dst && dst->shared->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);
/* Not a match */
if (((H5T_PERS_SOFT==pers && path->is_hard) ||
(H5T_PERS_HARD==pers && !path->is_hard)) ||
(name && *name && HDstrcmp(name, path->name)) ||
(src && H5T_cmp(src, path->src, FALSE)) ||
(dst && H5T_cmp(dst, path->dst, FALSE)) ||
(func && func!=path->func)) {
/*
* 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 removing a function should cause
* the list to be recalculated to avoid the removed function.
*/
path->cdata.recalc = TRUE;
} /* end if */
else {
/* 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),
(size_t)0, (size_t)0, (size_t)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*/
} /* end else */
} /* end for */
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, size_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","iizxxi",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, (size_t)0, (size_t)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);
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 = H5T_alloc()))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
dt->shared->type = type;
if(type==H5T_COMPOUND)
dt->shared->u.compnd.packed=TRUE; /* Start out packed */
else if(type==H5T_OPAQUE)
/* Initialize the tag in case it's not set later. A null tag will
* cause problems for later operations. */
dt->shared->u.opaque.tag = H5MM_strdup("");
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 = H5T_alloc()))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
dt->shared->type = type;
if (NULL==(dt->shared->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->shared->size = size;
/* Set return value */
ret_value=dt;
done:
if(ret_value==NULL) {
if(dt->shared != NULL)
H5FL_FREE(H5T_shared_t, dt->shared);
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_ID, 0, dxpl_id))<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to read object header");
done:
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, <pvn@ncsa.uiuc.edu> 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;
H5T_shared_t *reopened_fo;
unsigned 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");
if (NULL==(new_dt->shared = H5FL_MALLOC(H5T_shared_t)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
/* Copy shared information (entry information is copied last) */
*(new_dt->shared) = *(old_dt->shared);
/* Copy parent information */
if (new_dt->shared->parent)
new_dt->shared->parent = H5T_copy(new_dt->shared->parent, method);
/* Check what sort of copy we are making */
switch (method) {
case H5T_COPY_TRANSIENT:
/*
* Return an unlocked transient type.
*/
new_dt->shared->state = H5T_STATE_TRANSIENT;
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==old_dt->shared->state) {
new_dt->shared->state = H5T_STATE_NAMED;
} else if (H5T_STATE_IMMUTABLE==old_dt->shared->state) {
new_dt->shared->state = H5T_STATE_RDONLY;
}
break;
case H5T_COPY_REOPEN:
/*
* Return a transient type (locked or unlocked) or an opened named
* type. Immutable transient types are degraded to read-only.
*/
if (H5F_addr_defined(old_dt->ent.header)) {
/* Check if the object is already open */
if((reopened_fo=H5FO_opened(old_dt->ent.file, old_dt->ent.header))==NULL) {
/* Clear any errors from H5FO_opened() */
H5E_clear();
/* Open named datatype again */
if (H5O_open (&(old_dt->ent))<0)
HGOTO_ERROR (H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reopen named data type");
/* Insert opened named datatype into opened object list for the file */
if(H5FO_insert(old_dt->ent.file, old_dt->ent.header, new_dt->shared)<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, NULL, "can't insert datatype into list of open objects")
/* Increment object count for the object in the top file */
if(H5FO_top_incr(old_dt->ent.file, old_dt->ent.header) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count")
new_dt->shared->fo_count=1;
} else {
/* The object is already open. Free the H5T_shared_t struct
* we had been using and use the one that already exists.
* Not terribly efficient. */
H5FL_FREE(H5T_shared_t, new_dt->shared);
new_dt->shared = reopened_fo;
reopened_fo->fo_count++;
/* Check if the object has been opened through the top file yet */
if(H5FO_top_count(old_dt->ent.file, old_dt->ent.header) == 0) {
/* Open the object through this top file */
if(H5O_open(&(old_dt->ent)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open object header")
} /* end if */
/* Increment object count for the object in the top file */
if(H5FO_top_incr(old_dt->ent.file, old_dt->ent.header) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count")
}
new_dt->shared->state = H5T_STATE_OPEN;
} else if (H5T_STATE_IMMUTABLE==old_dt->shared->state) {
new_dt->shared->state = H5T_STATE_RDONLY;
}
break;
} /* end switch */
switch(new_dt->shared->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->shared->u.compnd.memb = H5MM_malloc(new_dt->shared->u.compnd.nalloc *
sizeof(H5T_cmemb_t));
if (NULL==new_dt->shared->u.compnd.memb)
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
HDmemcpy(new_dt->shared->u.compnd.memb, old_dt->shared->u.compnd.memb,
new_dt->shared->u.compnd.nmembs * sizeof(H5T_cmemb_t));
for (i=0; i<new_dt->shared->u.compnd.nmembs; i++) {
unsigned j;
int old_match;
s = new_dt->shared->u.compnd.memb[i].name;
new_dt->shared->u.compnd.memb[i].name = H5MM_xstrdup(s);
tmp = H5T_copy (old_dt->shared->u.compnd.memb[i].type, method);
new_dt->shared->u.compnd.memb[i].type = tmp;
/* Apply the accumulated size change to the offset of the field */
new_dt->shared->u.compnd.memb[i].offset += accum_change;
if(old_dt->shared->u.compnd.sorted != H5T_SORT_VALUE) {
for (old_match=-1, j=0; j<old_dt->shared->u.compnd.nmembs; j++) {
if(!HDstrcmp(new_dt->shared->u.compnd.memb[i].name,old_dt->shared->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->shared->u.compnd.memb[i].type->shared->size != old_dt->shared->u.compnd.memb[old_match].type->shared->size) {
/* Adjust the size of the member */
new_dt->shared->u.compnd.memb[i].size = (old_dt->shared->u.compnd.memb[old_match].size*tmp->shared->size)/old_dt->shared->u.compnd.memb[old_match].type->shared->size;
accum_change += (new_dt->shared->u.compnd.memb[i].type->shared->size - old_dt->shared->u.compnd.memb[old_match].type->shared->size);
} /* end if */
} /* end for */
/* Apply the accumulated size change to the size of the compound struct */
new_dt->shared->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->shared->u.enumer.name = H5MM_malloc(new_dt->shared->u.enumer.nalloc *
sizeof(char*));
new_dt->shared->u.enumer.value = H5MM_malloc(new_dt->shared->u.enumer.nalloc *
new_dt->shared->size);
if (NULL==new_dt->shared->u.enumer.value)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
HDmemcpy(new_dt->shared->u.enumer.value, old_dt->shared->u.enumer.value,
new_dt->shared->u.enumer.nmembs * new_dt->shared->size);
for (i=0; i<new_dt->shared->u.enumer.nmembs; i++) {
s = old_dt->shared->u.enumer.name[i];
new_dt->shared->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->shared->u.opaque.tag = HDstrdup(new_dt->shared->u.opaque.tag);
break;
case H5T_ARRAY:
/* Re-compute the array's size, in case it's base type changed size */
new_dt->shared->size=new_dt->shared->u.array.nelem*new_dt->shared->parent->shared->size;
break;
default:
break;
} /* end switch */
/* Deep copy of the symbol table entry, if there was one */
if(new_dt->shared->state == H5T_STATE_NAMED || new_dt->shared->state == H5T_STATE_OPEN) {
if(!H5F_addr_defined(old_dt->ent.header))
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "named dataype with invalid address")
if (H5G_ent_copy(&(new_dt->ent), &(old_dt->ent),H5_COPY_DEEP)<0)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to copy entry")
} /* end if */
else {
H5G_ent_reset(&(new_dt->ent));
} /* end else */
/* Set return value */
ret_value=new_dt;
done:
if(ret_value==NULL) {
if(new_dt->shared != NULL)
H5FL_FREE(H5T_shared_t, new_dt->shared);
if(new_dt!=NULL)
H5FL_FREE (H5T_t,new_dt);
} /* end if */
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->shared->state) {
case H5T_STATE_TRANSIENT:
dt->shared->state = immutable ? H5T_STATE_IMMUTABLE : H5T_STATE_RDONLY;
break;
case H5T_STATE_RDONLY:
if (immutable) dt->shared->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_alloc
*
* Purpose: Allocates a new H5T_t structure, initializing it correctly.
*
* Return: Pointer to new H5T_t on success/NULL on failure
*
* Programmer: Quincey Koziol
* Monday, August 29, 2005
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
H5T_t *
H5T_alloc(void)
{
H5T_t *dt = NULL; /* Pointer to datatype allocated */
H5T_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5T_alloc, NULL)
/* Allocate & initialize new datatype info */
if(NULL == (dt = H5FL_CALLOC(H5T_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
H5G_ent_reset(&(dt->ent));
if(NULL == (dt->shared = H5FL_CALLOC(H5T_shared_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
/* Assign return value */
ret_value = dt;
done:
if(ret_value == NULL) {
if(dt != NULL) {
if(dt->shared != NULL)
H5FL_FREE(H5T_shared_t, dt->shared);
H5FL_FREE(H5T_t, dt);
} /* end if */
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_alloc() */
/*-------------------------------------------------------------------------
* Function: H5T_free
*
* Purpose: Frees all memory associated with a datatype, but does not
* free the H5T_t or H5T_shared_t structures (which should
* be done in H5T_close).
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* Monday, January 6, 2003
*
*-------------------------------------------------------------------------
*/
herr_t
H5T_free(H5T_t *dt)
{
unsigned i;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5T_free, FAIL)
HDassert(dt && dt->shared);
/*
* If a named type is being closed then close the object header and
* remove from the list of open objects in the file.
*/
if(H5T_STATE_OPEN == dt->shared->state) {
HDassert(H5F_addr_defined(dt->ent.header));
/* Remove the datatype from the list of opened objects in the file */
if(H5FO_top_decr(dt->ent.file, dt->ent.header) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't decrement count for object")
if(H5FO_delete(dt->ent.file, H5AC_dxpl_id, dt->ent.header)<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't remove datatype from list of open objects")
if (H5O_close(&(dt->ent))<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close data type object header")
dt->shared->state = H5T_STATE_NAMED;
} /* end if */
/*
* Don't free locked datatypes.
*/
if(H5T_STATE_IMMUTABLE==dt->shared->state)
HGOTO_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to close immutable datatype")
/* Close the datatype */
switch(dt->shared->type) {
case H5T_COMPOUND:
for(i = 0; i < dt->shared->u.compnd.nmembs; i++) {
H5MM_xfree(dt->shared->u.compnd.memb[i].name);
H5T_close(dt->shared->u.compnd.memb[i].type);
} /* end for */
H5MM_xfree(dt->shared->u.compnd.memb);
break;
case H5T_ENUM:
for(i = 0; i < dt->shared->u.enumer.nmembs; i++)
H5MM_xfree(dt->shared->u.enumer.name[i]);
H5MM_xfree(dt->shared->u.enumer.name);
H5MM_xfree(dt->shared->u.enumer.value);
break;
case H5T_OPAQUE:
H5MM_xfree(dt->shared->u.opaque.tag);
break;
default:
break;
} /* end switch */
/* Free the ID to name info */
H5G_name_free(&(dt->ent));
/* Close the parent */
if(dt->shared->parent && H5T_close(dt->shared->parent) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, 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, <pvn@ncsa.uiuc.edu> 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)
HDassert(dt && dt->shared);
dt->shared->fo_count--;
if(dt->shared->state != H5T_STATE_OPEN || dt->shared->fo_count == 0) {
if(H5T_free(dt) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free datatype");
H5FL_FREE(H5T_shared_t, dt->shared);
} else {
/*
* If a named type is being closed then close the object header and
* remove from the list of open objects in the file.
*/
if(H5T_STATE_OPEN == dt->shared->state) {
/* Decrement the ref. count for this object in the top file */
if(H5FO_top_decr(dt->ent.file, dt->ent.header) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't decrement count for object")
/* Check reference count for this object in the top file */
if(H5FO_top_count(dt->ent.file, dt->ent.header) == 0)
if(H5O_close(&(dt->ent)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close")
} /* end if */
/* Free the ID to name info since we're not calling H5T_free*/
H5G_name_free(&(dt->ent));
} /* end else */
/* Free the datatype struct */
H5FL_FREE(H5T_t,dt);
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5T_close() */
/*-------------------------------------------------------------------------
* Function: H5T_set_size
*
* Purpose: Sets the total size in bytes for a data type (this operation
* is not permitted on reference 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_REFERENCE!=dt->shared->type);
assert(!(H5T_ENUM==dt->shared->type && 0==dt->shared->u.enumer.nmembs));
if (dt->shared->parent) {
if (H5T_set_size(dt->shared->parent, size)<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set size for parent data type");
/* Adjust size of datatype appropriately */
if(dt->shared->type==H5T_ARRAY)
dt->shared->size = dt->shared->parent->shared->size * dt->shared->u.array.nelem;
else if(dt->shared->type!=H5T_VLEN)
dt->shared->size = dt->shared->parent->shared->size;
} else {
if (H5T_IS_ATOMIC(dt->shared)) {
offset = dt->shared->u.atomic.offset;
prec = dt->shared->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->shared->type) {
case H5T_INTEGER:
case H5T_TIME:
case H5T_BITFIELD:
case H5T_OPAQUE:
/* nothing to check */
break;
case H5T_COMPOUND:
/* If decreasing size, check the last member isn't being cut. */
if(size<dt->shared->size) {
int num_membs;
unsigned i, max_index=0;
size_t memb_offset, max_offset=0;
size_t max_size;
if((num_membs = H5T_get_nmembers(dt))<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to get number of members");
for(i=0; i<(unsigned)num_membs; i++) {
memb_offset = H5T_get_member_offset(dt, i);
if(memb_offset > max_offset) {
max_offset = memb_offset;
max_index = i;
}
}
max_size = H5T_get_member_size(dt, max_index);
if(size<(max_offset+max_size))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "size shrinking will cut off last member ");
}
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->shared->parent=H5T_copy(base,H5T_COPY_ALL);
/* change this datatype into a VL string */
dt->shared->type = H5T_VLEN;
/*
* Force conversions (i.e. memory to memory conversions
* should duplicate data, not point to the same VL strings)
*/
dt->shared->force_conv = TRUE;
/* Before we mess with the info in the union, extract the
* values we need */
tmp_cset=dt->shared->u.atomic.u.s.cset;
tmp_strpad=dt->shared->u.atomic.u.s.pad;
/* This is a string, not a sequence */
dt->shared->u.vlen.type = H5T_VLEN_STRING;
/* Set character set and padding information */
dt->shared->u.vlen.cset = tmp_cset;
dt->shared->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->shared->u.atomic.u.f.sign >= prec+offset ||
dt->shared->u.atomic.u.f.epos + dt->shared->u.atomic.u.f.esize > prec+offset ||
dt->shared->u.atomic.u.f.mpos + dt->shared->u.atomic.u.f.msize > prec+offset) {
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "adjust sign, mantissa, and exponent fields first");
}
break;
case H5T_ENUM:
case H5T_VLEN:
case H5T_ARRAY:
assert("can't happen" && 0);
case H5T_REFERENCE:
assert("invalid type" && 0);
default:
assert("not implemented yet" && 0);
}
/* Commit (if we didn't convert this type to a VL string) */
if(dt->shared->type!=H5T_VLEN) {
dt->shared->size = size;
if (H5T_IS_ATOMIC(dt->shared)) {
dt->shared->u.atomic.offset = offset;
dt->shared->u.atomic.prec = prec;
}
} /* end if */
}
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_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_get_size);
/* check args */
assert(dt);
FUNC_LEAVE_NOAPI(dt->shared->size);
}
/*-------------------------------------------------------------------------
* Function: H5T_cmp
*
* Purpose: Compares two data types.
*
* Return: Success: 0 if DT1 and DT2 are equal.
* <0 if DT1 is less than DT2.
* >0 if DT1 is greater than DT2.
*
* Failure: 0, never fails
*
* Programmer: Robb Matzke
* Wednesday, December 10, 1997
*
* Modifications:
* Robb Matzke, 22 Dec 1998
* Able to compare enumeration data types.
*
* Robb Matzke, 20 May 1999
* Compares bitfields and opaque types.
*
* Quincey Koziol, 19 Mar 2005
* Allow an enumerated datatypes to compare equal, if the "superset"
* flag is set and dt2 has a superset of the enumerated values in dt1
*-------------------------------------------------------------------------
*/
int
H5T_cmp(const H5T_t *dt1, const H5T_t *dt2, hbool_t superset)
{
unsigned *idx1 = NULL, *idx2 = NULL;
int ret_value = 0;
int i, j;
unsigned u;
int tmp;
hbool_t swapped;
size_t base_size;
FUNC_ENTER_NOAPI(H5T_cmp, 0);
/* the easy case */
if (dt1 == dt2) HGOTO_DONE(0);
assert(dt1);
assert(dt2);
/* compare */
if (dt1->shared->type < dt2->shared->type) HGOTO_DONE(-1);
if (dt1->shared->type > dt2->shared->type) HGOTO_DONE(1);
if (dt1->shared->size < dt2->shared->size) HGOTO_DONE(-1);
if (dt1->shared->size > dt2->shared->size) HGOTO_DONE(1);
if (dt1->shared->parent && !dt2->shared->parent) HGOTO_DONE(-1);
if (!dt1->shared->parent && dt2->shared->parent) HGOTO_DONE(1);
if (dt1->shared->parent) {
tmp = H5T_cmp(dt1->shared->parent, dt2->shared->parent, superset);
if (tmp<0) HGOTO_DONE(-1);
if (tmp>0) HGOTO_DONE(1);
}
switch(dt1->shared->type) {
case H5T_COMPOUND:
/*
* Compound data types...
*/
if (dt1->shared->u.compnd.nmembs < dt2->shared->u.compnd.nmembs)
HGOTO_DONE(-1);
if (dt1->shared->u.compnd.nmembs > dt2->shared->u.compnd.nmembs)
HGOTO_DONE(1);
/* Build an index for each type so the names are sorted */
if (NULL==(idx1 = H5MM_malloc(dt1->shared->u.compnd.nmembs * sizeof(unsigned))) ||
NULL==(idx2 = H5MM_malloc(dt2->shared->u.compnd.nmembs * sizeof(unsigned))))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed");
for (u=0; u<dt1->shared->u.compnd.nmembs; u++)
idx1[u] = idx2[u] = u;
if(dt1->shared->u.enumer.nmembs > 1) {
for (i=dt1->shared->u.compnd.nmembs-1, swapped=TRUE; swapped && i>=0; --i)
for (j=0, swapped=FALSE; j<i; j++)
if (HDstrcmp(dt1->shared->u.compnd.memb[idx1[j]].name,
dt1->shared->u.compnd.memb[idx1[j+1]].name) > 0) {
tmp = idx1[j];
idx1[j] = idx1[j+1];
idx1[j+1] = tmp;
swapped = TRUE;
}
for (i=dt2->shared->u.compnd.nmembs-1, swapped=TRUE; swapped && i>=0; --i)
for (j=0, swapped=FALSE; j<i; j++)
if (HDstrcmp(dt2->shared->u.compnd.memb[idx2[j]].name,
dt2->shared->u.compnd.memb[idx2[j+1]].name) > 0) {
tmp = idx2[j];
idx2[j] = idx2[j+1];
idx2[j+1] = tmp;
swapped = TRUE;
}
} /* end if */
#ifdef H5T_DEBUG
/* I don't quite trust the code above yet :-) --RPM */
for (u=0; u<dt1->shared->u.compnd.nmembs-1; u++) {
assert(HDstrcmp(dt1->shared->u.compnd.memb[idx1[u]].name,
dt1->shared->u.compnd.memb[idx1[u + 1]].name));
assert(HDstrcmp(dt2->shared->u.compnd.memb[idx2[u]].name,
dt2->shared->u.compnd.memb[idx2[u + 1]].name));
}
#endif
/* Compare the members */
for (u=0; u<dt1->shared->u.compnd.nmembs; u++) {
tmp = HDstrcmp(dt1->shared->u.compnd.memb[idx1[u]].name,
dt2->shared->u.compnd.memb[idx2[u]].name);
if (tmp < 0)
HGOTO_DONE(-1);
if (tmp > 0)
HGOTO_DONE(1);
if (dt1->shared->u.compnd.memb[idx1[u]].offset < dt2->shared->u.compnd.memb[idx2[u]].offset) HGOTO_DONE(-1);
if (dt1->shared->u.compnd.memb[idx1[u]].offset > dt2->shared->u.compnd.memb[idx2[u]].offset) HGOTO_DONE(1);
if (dt1->shared->u.compnd.memb[idx1[u]].size < dt2->shared->u.compnd.memb[idx2[u]].size) HGOTO_DONE(-1);
if (dt1->shared->u.compnd.memb[idx1[u]].size > dt2->shared->u.compnd.memb[idx2[u]].size) HGOTO_DONE(1);
tmp = H5T_cmp(dt1->shared->u.compnd.memb[idx1[u]].type,
dt2->shared->u.compnd.memb[idx2[u]].type, superset);
if (tmp < 0) HGOTO_DONE(-1);
if (tmp > 0) HGOTO_DONE(1);
}
break;
case H5T_ENUM:
/*
* Enumeration data types...
*/
/* If we are doing a "superset" comparison, dt2 is allowed to have
* more members than dt1
*/
if(superset) {
if (dt1->shared->u.enumer.nmembs > dt2->shared->u.enumer.nmembs)
HGOTO_DONE(1);
} /* end if */
else {
if (dt1->shared->u.enumer.nmembs < dt2->shared->u.enumer.nmembs)
HGOTO_DONE(-1);
if (dt1->shared->u.enumer.nmembs > dt2->shared->u.enumer.nmembs)
HGOTO_DONE(1);
} /* end else */
/* Build an index for each type so the names are sorted */
if (NULL==(idx1 = H5MM_malloc(dt1->shared->u.enumer.nmembs * sizeof(unsigned))) ||
NULL==(idx2 = H5MM_malloc(dt2->shared->u.enumer.nmembs * sizeof(unsigned))))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed");
for (u=0; u<dt1->shared->u.enumer.nmembs; u++)
idx1[u] = u;
if(dt1->shared->u.enumer.nmembs > 1)
for (i=dt1->shared->u.enumer.nmembs-1, swapped=TRUE; swapped && i>=0; --i)
for (j=0, swapped=FALSE; j<i; j++)
if (HDstrcmp(dt1->shared->u.enumer.name[idx1[j]],
dt1->shared->u.enumer.name[idx1[j+1]]) > 0) {
tmp = idx1[j];
idx1[j] = idx1[j+1];
idx1[j+1] = tmp;
swapped = TRUE;
}
for (u=0; u<dt2->shared->u.enumer.nmembs; u++)
idx2[u] = u;
if(dt2->shared->u.enumer.nmembs > 1)
for (i=dt2->shared->u.enumer.nmembs-1, swapped=TRUE; swapped && i>=0; --i)
for (j=0, swapped=FALSE; j<i; j++)
if (HDstrcmp(dt2->shared->u.enumer.name[idx2[j]],
dt2->shared->u.enumer.name[idx2[j+1]]) > 0) {
tmp = idx2[j];
idx2[j] = idx2[j+1];
idx2[j+1] = tmp;
swapped = TRUE;
}
#ifdef H5T_DEBUG
/* I don't quite trust the code above yet :-) --RPM */
for (u=0; u<dt1->shared->u.enumer.nmembs-1; u++) {
assert(HDstrcmp(dt1->shared->u.enumer.name[idx1[u]],
dt1->shared->u.enumer.name[idx1[u+1]]));
assert(HDstrcmp(dt2->shared->u.enumer.name[idx2[u]],
dt2->shared->u.enumer.name[idx2[u+1]]));
}
#endif
/* Compare the members */
base_size = dt1->shared->parent->shared->size;
for (u=0; u<dt1->shared->u.enumer.nmembs; u++) {
unsigned idx = 0;
if(superset) {
unsigned lt = 0, rt; /* Final, left & right key indices */
int cmp = 1; /* Key comparison value */
/* If a superset is allowed, dt2 may have more members
* than dt1, so binary search for matching member name in
* dt2
*/
rt = dt2->shared->u.enumer.nmembs;
while (lt < rt && cmp) {
idx = (lt + rt) / 2;
/* compare */
if ((cmp = HDstrcmp(dt1->shared->u.enumer.name[idx1[u]],
dt2->shared->u.enumer.name[idx2[idx]] ) ) < 0)
rt = idx;
else
lt = idx+1;
}
/* Leave, if we couldn't find match */
if (cmp)
HGOTO_DONE(-1);
} /* end if */
else {
/* Check for exact member name match when not doing
* "superset" comparison
*/
tmp = HDstrcmp(dt1->shared->u.enumer.name[idx1[u]],
dt2->shared->u.enumer.name[idx2[u]]);
if (tmp<0) HGOTO_DONE(-1);
if (tmp>0) HGOTO_DONE(1);
/* Set index value appropriately */
idx = u;
} /* end else */
tmp = HDmemcmp(dt1->shared->u.enumer.value+idx1[u]*base_size,
dt2->shared->u.enumer.value+idx2[idx]*base_size,
base_size);
if (tmp<0) HGOTO_DONE(-1);
if (tmp>0) HGOTO_DONE(1);
}
break;
case H5T_VLEN:
assert(dt1->shared->u.vlen.type>H5T_VLEN_BADTYPE && dt1->shared->u.vlen.type<H5T_VLEN_MAXTYPE);
assert(dt2->shared->u.vlen.type>H5T_VLEN_BADTYPE && dt2->shared->u.vlen.type<H5T_VLEN_MAXTYPE);
assert(dt1->shared->u.vlen.loc>H5T_VLEN_BADLOC && dt1->shared->u.vlen.loc<H5T_VLEN_MAXLOC);
assert(dt2->shared->u.vlen.loc>H5T_VLEN_BADLOC && dt2->shared->u.vlen.loc<H5T_VLEN_MAXLOC);
/* Arbitrarily sort sequence VL datatypes before string VL datatypes */
if (dt1->shared->u.vlen.type==H5T_VLEN_SEQUENCE &&
dt2->shared->u.vlen.type==H5T_VLEN_STRING) {
HGOTO_DONE(-1);
} else if (dt1->shared->u.vlen.type==H5T_VLEN_STRING &&
dt2->shared->u.vlen.type==H5T_VLEN_SEQUENCE) {
HGOTO_DONE(1);
}
/* Arbitrarily sort VL datatypes in memory before disk */
if (dt1->shared->u.vlen.loc==H5T_VLEN_MEMORY &&
dt2->shared->u.vlen.loc==H5T_VLEN_DISK) {
HGOTO_DONE(-1);
} else if (dt1->shared->u.vlen.loc==H5T_VLEN_DISK &&
dt2->shared->u.vlen.loc==H5T_VLEN_MEMORY) {
HGOTO_DONE(1);
}
/* Don't allow VL types in different files to compare as equal */
if (dt1->shared->u.vlen.f < dt2->shared->u.vlen.f)
HGOTO_DONE(-1);
if (dt1->shared->u.vlen.f > dt2->shared->u.vlen.f)
HGOTO_DONE(1);
break;
case H5T_OPAQUE:
if(dt1->shared->u.opaque.tag && dt2->shared->u.opaque.tag)
HGOTO_DONE(HDstrcmp(dt1->shared->u.opaque.tag,dt2->shared->u.opaque.tag));
break;
case H5T_ARRAY:
if (dt1->shared->u.array.ndims < dt2->shared->u.array.ndims)
HGOTO_DONE(-1);
if (dt1->shared->u.array.ndims > dt2->shared->u.array.ndims)
HGOTO_DONE(1);
for (j=0; j<dt1->shared->u.array.ndims; j++) {
if (dt1->shared->u.array.dim[j] < dt2->shared->u.array.dim[j])
HGOTO_DONE(-1);
if (dt1->shared->u.array.dim[j] > dt2->shared->u.array.dim[j])
HGOTO_DONE(1);
}
for (j=0; j<dt1->shared->u.array.ndims; j++) {
if (dt1->shared->u.array.perm[j] < dt2->shared->u.array.perm[j])
HGOTO_DONE(-1);
if (dt1->shared->u.array.perm[j] > dt2->shared->u.array.perm[j])
HGOTO_DONE(1);
}
tmp = H5T_cmp(dt1->shared->parent, dt2->shared->parent, superset);
if (tmp < 0)
HGOTO_DONE(-1);
if (tmp > 0)
HGOTO_DONE(1);
break;
default:
/*
* Atomic datatypes...
*/
if (dt1->shared->u.atomic.order < dt2->shared->u.atomic.order) HGOTO_DONE(-1);
if (dt1->shared->u.atomic.order > dt2->shared->u.atomic.order) HGOTO_DONE(1);
if (dt1->shared->u.atomic.prec < dt2->shared->u.atomic.prec) HGOTO_DONE(-1);
if (dt1->shared->u.atomic.prec > dt2->shared->u.atomic.prec) HGOTO_DONE(1);
if (dt1->shared->u.atomic.offset < dt2->shared->u.atomic.offset) HGOTO_DONE(-1);
if (dt1->shared->u.atomic.offset > dt2->shared->u.atomic.offset) HGOTO_DONE(1);
if (dt1->shared->u.atomic.lsb_pad < dt2->shared->u.atomic.lsb_pad) HGOTO_DONE(-1);
if (dt1->shared->u.atomic.lsb_pad > dt2->shared->u.atomic.lsb_pad) HGOTO_DONE(1);
if (dt1->shared->u.atomic.msb_pad < dt2->shared->u.atomic.msb_pad) HGOTO_DONE(-1);
if (dt1->shared->u.atomic.msb_pad > dt2->shared->u.atomic.msb_pad) HGOTO_DONE(1);
switch (dt1->shared->type) {
case H5T_INTEGER:
if (dt1->shared->u.atomic.u.i.sign < dt2->shared->u.atomic.u.i.sign)
HGOTO_DONE(-1);
if (dt1->shared->u.atomic.u.i.sign > dt2->shared->u.atomic.u.i.sign)
HGOTO_DONE(1);
break;
case H5T_FLOAT:
if (dt1->shared->u.atomic.u.f.sign < dt2->shared->u.atomic.u.f.sign)
HGOTO_DONE(-1);
if (dt1->shared->u.atomic.u.f.sign > dt2->shared->u.atomic.u.f.sign)
HGOTO_DONE(1);
if (dt1->shared->u.atomic.u.f.epos < dt2->shared->u.atomic.u.f.epos)
HGOTO_DONE(-1);
if (dt1->shared->u.atomic.u.f.epos > dt2->shared->u.atomic.u.f.epos)
HGOTO_DONE(1);
if (dt1->shared->u.atomic.u.f.esize < dt2->shared->u.atomic.u.f.esize) HGOTO_DONE(-1);
if (dt1->shared->u.atomic.u.f.esize > dt2->shared->u.atomic.u.f.esize) HGOTO_DONE(1);
if (dt1->shared->u.atomic.u.f.ebias < dt2->shared->u.atomic.u.f.ebias) HGOTO_DONE(-1);
if (dt1->shared->u.atomic.u.f.ebias > dt2->shared->u.atomic.u.f.ebias) HGOTO_DONE(1);
if (dt1->shared->u.atomic.u.f.mpos < dt2->shared->u.atomic.u.f.mpos)
HGOTO_DONE(-1);
if (dt1->shared->u.atomic.u.f.mpos > dt2->shared->u.atomic.u.f.mpos)
HGOTO_DONE(1);
if (dt1->shared->u.atomic.u.f.msize < dt2->shared->u.atomic.u.f.msize) HGOTO_DONE(-1);
if (dt1->shared->u.atomic.u.f.msize > dt2->shared->u.atomic.u.f.msize) HGOTO_DONE(1);
if (dt1->shared->u.atomic.u.f.norm < dt2->shared->u.atomic.u.f.norm)
HGOTO_DONE(-1);
if (dt1->shared->u.atomic.u.f.norm > dt2->shared->u.atomic.u.f.norm)
HGOTO_DONE(1);
if (dt1->shared->u.atomic.u.f.pad < dt2->shared->u.atomic.u.f.pad)
HGOTO_DONE(-1);
if (dt1->shared->u.atomic.u.f.pad > dt2->shared->u.atomic.u.f.pad)
HGOTO_DONE(1);
break;
case H5T_TIME: /* order and precision are checked above */
/*void */
break;
case H5T_STRING:
if (dt1->shared->u.atomic.u.s.cset < dt2->shared->u.atomic.u.s.cset)
HGOTO_DONE(-1);
if (dt1->shared->u.atomic.u.s.cset > dt2->shared->u.atomic.u.s.cset)
HGOTO_DONE(1);
if (dt1->shared->u.atomic.u.s.pad < dt2->shared->u.atomic.u.s.pad)
HGOTO_DONE(-1);
if (dt1->shared->u.atomic.u.s.pad > dt2->shared->u.atomic.u.s.pad)
HGOTO_DONE(1);
break;
case H5T_BITFIELD:
/*void */
break;
case H5T_REFERENCE:
if (dt1->shared->u.atomic.u.r.rtype < dt2->shared->u.atomic.u.r.rtype)
HGOTO_DONE(-1);
if (dt1->shared->u.atomic.u.r.rtype > dt2->shared->u.atomic.u.r.rtype)
HGOTO_DONE(1);
switch(dt1->shared->u.atomic.u.r.rtype) {
case H5R_OBJECT:
case H5R_DATASET_REGION:
/* Does this need more to distinguish it? -QAK 11/30/98 */
/*void */
break;
default:
assert("not implemented yet" && 0);
}
break;
default:
assert("not implemented yet" && 0);
}
break;
} /* end switch */
done:
if(idx1!=NULL)
H5MM_xfree(idx1);
if(idx2!=NULL)
H5MM_xfree(idx2);
FUNC_LEAVE_NOAPI(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5T_path_find
*
* Purpose: Finds the path which converts type SRC_ID to type DST_ID,
* creating a new path if necessary. If FUNC is non-zero then
* it is set as the hard conversion function for that path
* regardless of whether the path previously existed. Changing
* the conversion function of a path causes statistics to be
* reset to zero after printing them. The NAME is used only
* when creating a new path and is just for debugging.
*
* If SRC and DST are both null pointers then the special no-op
* conversion path is used. This path is always stored as the
* first path in the path table.
*
* Return: Success: Pointer to the path, valid until the path
* database is modified.
*
* Failure: NULL if the path does not exist and no
* function can be found to apply to the new
* path.
*
* Programmer: Robb Matzke
* Tuesday, January 13, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
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)
{
int lt, rt; /*left and right edges */
int md; /*middle */
int cmp; /*comparison result */
int old_npaths; /* Previous number of paths in table */
H5T_path_t *table=NULL; /*path existing in the table */
H5T_path_t *path=NULL; /*new path */
H5T_path_t *ret_value; /*return value */
hid_t src_id=-1, dst_id=-1; /*src and dst type identifiers */
int i; /*counter */
int nprint=0; /*lines of output printed */
FUNC_ENTER_NOAPI(H5T_path_find, NULL);
assert((!src && !dst) || (src && dst));
/*
* Make sure the first entry in the table is the no-op conversion path.
*/
if (0==H5T_g.npaths) {
if (NULL==(H5T_g.path=H5MM_malloc(128*sizeof(H5T_path_t*))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for type conversion path table");
H5T_g.apaths = 128;
if (NULL==(H5T_g.path[0]=H5FL_CALLOC(H5T_path_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for no-op conversion path");
HDstrcpy(H5T_g.path[0]->name, "no-op");
H5T_g.path[0]->func = H5T_conv_noop;
H5T_g.path[0]->cdata.command = H5T_CONV_INIT;
if (H5T_conv_noop(FAIL, FAIL, &(H5T_g.path[0]->cdata),
(size_t)0, (size_t)0, (size_t)0, NULL, NULL, dxpl_id)<0) {
#ifdef H5T_DEBUG
if (H5DEBUG(T)) {
fprintf(H5DEBUG(T), "H5T: unable to initialize no-op "
"conversion function (ignored)\n");
}
#endif
H5E_clear(); /*ignore the error*/
}
H5T_g.path[0]->is_noop = TRUE;
H5T_g.npaths = 1;
}
/*
* Find the conversion path. If source and destination types are equal
* then use entry[0], otherwise do a binary search over the
* remaining entries.
*
* Quincey Koziol, 2 July, 1999
* Only allow the no-op conversion to occur if no "force conversion" flags
* are set
*/
if (src->shared->force_conv==FALSE && dst->shared->force_conv==FALSE && 0==H5T_cmp(src, dst, TRUE)) {
table = H5T_g.path[0];
cmp = 0;
md = 0;
} else {
lt = md = 1;
rt = H5T_g.npaths;
cmp = -1;
while (cmp && lt<rt) {
md = (lt+rt) / 2;
assert(H5T_g.path[md]);
cmp = H5T_cmp(src, H5T_g.path[md]->src, FALSE);
if (0==cmp) cmp = H5T_cmp(dst, H5T_g.path[md]->dst, FALSE);
if (cmp<0) {
rt = md;
} else if (cmp>0) {
lt = md+1;
} else {
table = H5T_g.path[md];
}
}
}
/* Keep a record of the number of paths in the table, in case one of the
* initialization calls below (hard or soft) causes more entries to be
* added to the table - QAK, 1/26/02
*/
old_npaths=H5T_g.npaths;
/*
* If we didn't find the path or if the caller is specifying a new hard
* conversion function then create a new path and add the new function to
* the path.
*/
if (!table || func) {
if (NULL==(path=H5FL_CALLOC(H5T_path_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for type conversion path");
if (name && *name) {
HDstrncpy(path->name, name, (size_t)H5T_NAMELEN);
path->name[H5T_NAMELEN-1] = '\0';
} else {
HDstrcpy(path->name, "NONAME");
}
if ((src && NULL==(path->src=H5T_copy(src, H5T_COPY_ALL))) ||
(dst && NULL==(path->dst=H5T_copy(dst, H5T_COPY_ALL))))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy data type for conversion path");
} else {
path = table;
}
/*
* If a hard conversion function is specified and none is defined for the
* path then add it to the path and initialize its conversion data.
*/
if (func) {
assert(path!=table);
assert(NULL==path->func);
if (path->src && (src_id=H5I_register(H5I_DATATYPE,
H5T_copy(path->src, H5T_COPY_ALL)))<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register source conversion type for query");
if (path->dst && (dst_id=H5I_register(H5I_DATATYPE,
H5T_copy(path->dst, H5T_COPY_ALL)))<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register destination conversion type for query");
path->cdata.command = H5T_CONV_INIT;
if ((func)(src_id, dst_id, &(path->cdata), (size_t)0, (size_t)0, (size_t)0,
NULL, NULL, dxpl_id)<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to initialize conversion function");
if (src_id>=0) H5I_dec_ref(src_id);
if (dst_id>=0) H5I_dec_ref(dst_id);
src_id = dst_id = -1;
path->func = func;
path->is_hard = TRUE;
}
/*
* If the path doesn't have a function by now (because it's a new path
* and the caller didn't supply a hard function) then scan the soft list
* for an applicable function and add it to the path. This can't happen
* for the no-op conversion path.
*/
assert(path->func || (src && dst));
for (i=H5T_g.nsoft-1; i>=0 && !path->func; --i) {
if (src->shared->type!=H5T_g.soft[i].src ||
dst->shared->type!=H5T_g.soft[i].dst) {
continue;
}
if ((src_id=H5I_register(H5I_DATATYPE,
H5T_copy(path->src, H5T_COPY_ALL)))<0 ||
(dst_id=H5I_register(H5I_DATATYPE,
H5T_copy(path->dst, H5T_COPY_ALL)))<0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register conversion types for query");
path->cdata.command = H5T_CONV_INIT;
if ((H5T_g.soft[i].func) (src_id, dst_id, &(path->cdata),
(size_t)0, (size_t)0, (size_t)0, NULL, NULL, dxpl_id)<0) {
HDmemset (&(path->cdata), 0, sizeof(H5T_cdata_t));
H5E_clear(); /*ignore the error*/
} else {
HDstrcpy (path->name, H5T_g.soft[i].name);
path->func = H5T_g.soft[i].func;
path->is_hard = FALSE;
}
H5I_dec_ref(src_id);
H5I_dec_ref(dst_id);
src_id = dst_id = -1;
}
if (!path->func)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "no appropriate function for conversion path");
/* Check if paths were inserted into the table through a recursive call
* and re-compute the correct location for this path if so. - QAK, 1/26/02
*/
if(old_npaths!=H5T_g.npaths) {
lt = md = 1;
rt = H5T_g.npaths;
cmp = -1;
while (cmp && lt<rt) {
md = (lt+rt) / 2;
assert(H5T_g.path[md]);
cmp = H5T_cmp(src, H5T_g.path[md]->src, FALSE);
if (0==cmp) cmp = H5T_cmp(dst, H5T_g.path[md]->dst, FALSE);
if (cmp<0) {
rt = md;
} else if (cmp>0) {
lt = md+1;
} else {
table = H5T_g.path[md];
}
}
} /* end if */
/* Replace an existing table entry or add a new entry */
if (table && path!=table) {
assert(table==H5T_g.path[md]);
H5T_print_stats(table, &nprint/*in,out*/);
table->cdata.command = H5T_CONV_FREE;
if ((table->func)(FAIL, FAIL, &(table->cdata), (size_t)0, (size_t)0, (size_t)0,
NULL, NULL, dxpl_id)<0) {
#ifdef H5T_DEBUG
if (H5DEBUG(T)) {
fprintf(H5DEBUG(T), "H5T: conversion function 0x%08lx free "
"failed for %s (ignored)\n",
(unsigned long)(path->func), path->name);
}
#endif
H5E_clear(); /*ignore the failure*/
}
if (table->src) H5T_close(table->src);
if (table->dst) H5T_close(table->dst);
H5FL_FREE(H5T_path_t,table);
table = path;
H5T_g.path[md] = path;
} else if (path!=table) {
assert(cmp);
if (H5T_g.npaths >= H5T_g.apaths) {
size_t na = MAX(128, 2 * H5T_g.apaths);
H5T_path_t **x = H5MM_realloc (H5T_g.path,
na*sizeof(H5T_path_t*));
if (!x)
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
H5T_g.apaths = (int)na;
H5T_g.path = x;
}
if (cmp>0) md++;
HDmemmove(H5T_g.path+md+1, H5T_g.path+md,
(H5T_g.npaths-md) * sizeof(H5T_path_t*));
H5T_g.npaths++;
H5T_g.path[md] = path;
table = path;
}
/* Set return value */
ret_value = path;
done:
if (!ret_value && path && path!=table) {
if (path->src) H5T_close(path->src);
if (path->dst) H5T_close(path->dst);
H5FL_FREE(H5T_path_t,path);
}
if (src_id>=0) H5I_dec_ref(src_id);
if (dst_id>=0) H5I_dec_ref(dst_id);
FUNC_LEAVE_NOAPI(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5T_path_noop
*
* Purpose: Is the path the special no-op path? The no-op function can be
* set by the application and there might be more than one no-op
* path in a multi-threaded application if one thread is using
* the no-op path when some other thread changes its definition.
*
* Return: TRUE/FALSE (can't fail)
*
* Programmer: Quincey Koziol
* Thursday, May 8, 2003
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
hbool_t
H5T_path_noop(const H5T_path_t *p)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_path_noop);
assert(p);
FUNC_LEAVE_NOAPI(p->is_noop || (p->is_hard && 0==H5T_cmp(p->src, p->dst, FALSE)));
} /* end H5T_path_noop() */
/*-------------------------------------------------------------------------
* Function: H5T_path_bkg
*
* Purpose: Get the "background" flag for the conversion path.
*
* Return: Background flag (can't fail)
*
* Programmer: Quincey Koziol
* Thursday, May 8, 2003
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
H5T_bkg_t
H5T_path_bkg(const H5T_path_t *p)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_path_bkg);
assert(p);
FUNC_LEAVE_NOAPI(p->cdata.need_bkg);
} /* end H5T_path_bkg() */
/*-------------------------------------------------------------------------
* Function: H5T_convert
*
* Purpose: Call a conversion function to convert from source to
* destination data type and accumulate timing statistics.
*
* Return: Success: non-negative
*
* Failure: negative
*
* Programmer: Robb Matzke
* Tuesday, December 15, 1998
*
* Modifications:
* Robb Matzke, 1999-06-16
* The timers are updated only if H5T debugging is enabled at
* runtime in addition to compile time.
*
* Robb Matzke, 1999-06-16
* Added support for non-zero strides. If BUF_STRIDE is non-zero
* then convert one value at each memory location advancing
* BUF_STRIDE bytes each time; otherwise assume both source and
* destination values are packed.
*
* Quincey Koziol, 1999-07-01
* Added dataset transfer properties, to allow custom VL
* datatype allocation function to be passed down to VL
* conversion routine.
*
* Robb Matzke, 2000-05-17
* Added the BKG_STRIDE argument which gets passed to all the
* conversion functions. If BUF_STRIDE is non-zero then each
* data element is at a multiple of BUF_STRIDE bytes in BUF
* (on both input and output). If BKG_STRIDE is also set then
* the BKG buffer is used in such a way that temporary space
* for each element is aligned on a BKG_STRIDE byte boundary.
* If either BUF_STRIDE or BKG_STRIDE are zero then the BKG
* buffer will be accessed as though it were a packed array
* of destination datatype.
*-------------------------------------------------------------------------
*/
herr_t
H5T_convert(H5T_path_t *tpath, hid_t src_id, hid_t dst_id, size_t nelmts,
size_t buf_stride, size_t bkg_stride, void *buf, void *bkg,
hid_t dset_xfer_plist)
{
#ifdef H5T_DEBUG
H5_timer_t timer;
#endif
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5T_convert, FAIL);
#ifdef H5T_DEBUG
if (H5DEBUG(T)) H5_timer_begin(&timer);
#endif
tpath->cdata.command = H5T_CONV_CONV;
if ((tpath->func)(src_id, dst_id, &(tpath->cdata), nelmts, buf_stride,
bkg_stride, buf, bkg, dset_xfer_plist)<0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "data type conversion failed");
#ifdef H5T_DEBUG
if (H5DEBUG(T)) {
H5_timer_end(&(tpath->stats.timer), &timer);
tpath->stats.ncalls++;
tpath->stats.nelmts += nelmts;
}
#endif
done:
FUNC_LEAVE_NOAPI(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5T_entof
*
* Purpose: Returns a pointer to the entry for a named data type.
*
* Return: Success: Ptr directly into named data type
*
* Failure: NULL
*
* Programmer: Robb Matzke
* Friday, June 5, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
H5G_entry_t *
H5T_entof (H5T_t *dt)
{
H5G_entry_t *ret_value = NULL;
FUNC_ENTER_NOAPI(H5T_entof, NULL);
assert (dt);
switch (dt->shared->state) {
case H5T_STATE_TRANSIENT:
case H5T_STATE_RDONLY:
case H5T_STATE_IMMUTABLE:
HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, NULL, "not a named data type");
case H5T_STATE_NAMED:
case H5T_STATE_OPEN:
ret_value = &(dt->ent);
break;
}
done:
FUNC_LEAVE_NOAPI(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5T_is_immutable
*
* Purpose: Check if a datatype is immutable.
*
* Return: TRUE
*
* FALSE
*
* Programmer: Raymond Lu
* Friday, Dec 7, 2001
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
htri_t
H5T_is_immutable(const H5T_t *dt)
{
htri_t ret_value = FALSE;
FUNC_ENTER_NOAPI(H5T_is_immutable, FAIL);
assert(dt);
if(dt->shared->state == H5T_STATE_IMMUTABLE)
ret_value = TRUE;
done:
FUNC_LEAVE_NOAPI(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5T_is_named
*
* Purpose: Check if a datatype is named.
*
* Return: TRUE
*
* FALSE
*
* Programmer: Pedro Vicente
* Tuesday, Sep 3, 2002
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
htri_t
H5T_is_named(const H5T_t *dt)
{
htri_t ret_value = FALSE;
FUNC_ENTER_NOAPI(H5T_is_named, FAIL);
assert(dt);
if(dt->shared->state == H5T_STATE_OPEN || dt->shared->state == H5T_STATE_NAMED)
ret_value = TRUE;
done:
FUNC_LEAVE_NOAPI(ret_value);
}
/*--------------------------------------------------------------------------
NAME
H5T_get_ref_type
PURPOSE
Retrieves the type of reference for a datatype
USAGE
H5R_type_t H5Tget_ref_type(dt)
H5T_t *dt; IN: datatype pointer for the reference datatype
RETURNS
Success: A reference type defined in H5Rpublic.h
Failure: H5R_BADTYPE
DESCRIPTION
Given a reference datatype object, this function returns the reference type
of the datatype.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
H5R_type_t
H5T_get_ref_type(const H5T_t *dt)
{
H5R_type_t ret_value = H5R_BADTYPE;
FUNC_ENTER_NOAPI(H5T_get_ref_type, H5R_BADTYPE);
assert(dt);
if(dt->shared->type==H5T_REFERENCE)
ret_value=dt->shared->u.atomic.u.r.rtype;
done:
FUNC_LEAVE_NOAPI(ret_value);
} /* end H5T_get_ref_type() */
/*-------------------------------------------------------------------------
* Function: H5T_is_sensible
*
* Purpose: Determines if a data type is sensible to store on disk
* (i.e. not partially initialized)
*
* Return: Success: TRUE, FALSE
*
* Failure: Negative
*
* Programmer: Quincey Koziol
* Tuesday, June 11, 2002
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
htri_t
H5T_is_sensible(const H5T_t *dt)
{
htri_t ret_value;
FUNC_ENTER_NOAPI(H5T_is_sensible, FAIL);
assert(dt);
switch(dt->shared->type) {
case H5T_COMPOUND:
/* Only allow compound datatypes with at least one member to be stored on disk */
if(dt->shared->u.compnd.nmembs > 0)
ret_value=TRUE;
else
ret_value=FALSE;
break;
case H5T_ENUM:
/* Only allow enum datatypes with at least one member to be stored on disk */
if(dt->shared->u.enumer.nmembs > 0)
ret_value=TRUE;
else
ret_value=FALSE;
break;
default:
/* Assume all other datatype are sensible to store on disk */
ret_value=TRUE;
break;
} /* end switch */
done:
FUNC_LEAVE_NOAPI(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5T_is_relocatable
*
* Purpose: Check if a datatype will change between disk and memory.
*
* Notes: Currently, only variable-length and object references change
* between disk & memory (see cases where things are changed in
* the H5T_set_loc() code above).
*
* Return:
* One of two values on success:
* TRUE - If the location of any vlen types changed
* FALSE - If the location of any vlen types is the same
* <0 is returned on failure
*
* Programmer: Quincey Koziol
* Thursday, June 24, 2004
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
htri_t
H5T_is_relocatable(const H5T_t *dt)
{
htri_t ret_value = FALSE;
FUNC_ENTER_NOAPI(H5T_is_relocatable, FAIL);
assert(dt);
if(H5T_detect_class(dt, H5T_VLEN))
ret_value = TRUE;
done:
FUNC_LEAVE_NOAPI(ret_value);
} /* end H5T_is_relocatable() */
/*-------------------------------------------------------------------------
* Function: H5T_print_stats
*
* Purpose: Print statistics about a conversion path. Statistics are
* printed only if all the following conditions are true:
*
* 1. The library was compiled with H5T_DEBUG defined.
* 2. Data type debugging is turned on at run time.
* 3. The path was called at least one time.
*
* The optional NPRINT argument keeps track of the number of
* conversions paths for which statistics have been shown. If
* its value is zero then table headers are printed before the
* first line of output.
*
* Return: Success: non-negative
*
* Failure: negative
*
* Programmer: Robb Matzke
* Monday, December 14, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
H5T_print_stats(H5T_path_t UNUSED * path, int UNUSED * nprint/*in,out*/)
{
#ifdef H5T_DEBUG
hsize_t nbytes;
char bandwidth[32];
#endif
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_print_stats);
#ifdef H5T_DEBUG
if (H5DEBUG(T) && path->stats.ncalls>0) {
if (nprint && 0==(*nprint)++) {
HDfprintf (H5DEBUG(T), "H5T: type conversion statistics:\n");
HDfprintf (H5DEBUG(T), " %-16s %10s %10s %8s %8s %8s %10s\n",
"Conversion", "Elmts", "Calls", "User",
"System", "Elapsed", "Bandwidth");
HDfprintf (H5DEBUG(T), " %-16s %10s %10s %8s %8s %8s %10s\n",
"----------", "-----", "-----", "----",
"------", "-------", "---------");
}
if(path->src && path->dst)
nbytes = MAX (H5T_get_size (path->src),
H5T_get_size (path->dst));
else if(path->src)
nbytes = H5T_get_size (path->src);
else if(path->dst)
nbytes = H5T_get_size (path->dst);
else
nbytes = 0;
nbytes *= path->stats.nelmts;
H5_bandwidth(bandwidth, (double)nbytes,
path->stats.timer.etime);
HDfprintf (H5DEBUG(T), " %-16s %10Hd %10d %8.2f %8.2f %8.2f %10s\n",
path->name,
path->stats.nelmts,
path->stats.ncalls,
path->stats.timer.utime,
path->stats.timer.stime,
path->stats.timer.etime,
bandwidth);
}
#endif
FUNC_LEAVE_NOAPI(SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5T_debug
*
* Purpose: Prints information about a data type.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Wednesday, January 7, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5T_debug(const H5T_t *dt, FILE *stream)
{
const char *s1="", *s2="";
unsigned i;
size_t k, base_size;
uint64_t tmp;
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5T_debug, FAIL);
/* Check args */
assert(dt);
assert(stream);
switch (dt->shared->type) {
case H5T_INTEGER:
s1 = "int";
break;
case H5T_FLOAT:
s1 = "float";
break;
case H5T_TIME:
s1 = "time";
break;
case H5T_STRING:
s1 = "str";
break;
case H5T_BITFIELD:
s1 = "bits";
break;
case H5T_OPAQUE:
s1 = "opaque";
break;
case H5T_COMPOUND:
s1 = "struct";
break;
case H5T_ENUM:
s1 = "enum";
break;
case H5T_VLEN:
if(H5T_IS_VL_STRING(dt->shared))
s1 = "str";
else
s1 = "vlen";
break;
default:
s1 = "";
break;
}
switch (dt->shared->state) {
case H5T_STATE_TRANSIENT:
s2 = "[transient]";
break;
case H5T_STATE_RDONLY:
s2 = "[constant]";
break;
case H5T_STATE_IMMUTABLE:
s2 = "[predefined]";
break;
case H5T_STATE_NAMED:
s2 = "[named,closed]";
break;
case H5T_STATE_OPEN:
s2 = "[named,open]";
break;
}
fprintf(stream, "%s%s {nbytes=%lu", s1, s2, (unsigned long)(dt->shared->size));
if (H5T_IS_ATOMIC(dt->shared)) {
switch (dt->shared->u.atomic.order) {
case H5T_ORDER_BE:
s1 = "BE";
break;
case H5T_ORDER_LE:
s1 = "LE";
break;
case H5T_ORDER_VAX:
s1 = "VAX";
break;
case H5T_ORDER_NONE:
s1 = "NONE";
break;
default:
s1 = "order?";
break;
}
fprintf(stream, ", %s", s1);
if (dt->shared->u.atomic.offset) {
fprintf(stream, ", offset=%lu",
(unsigned long) (dt->shared->u.atomic.offset));
}
if (dt->shared->u.atomic.prec != 8 * dt->shared->size) {
fprintf(stream, ", prec=%lu",
(unsigned long) (dt->shared->u.atomic.prec));
}
switch (dt->shared->type) {
case H5T_INTEGER:
switch (dt->shared->u.atomic.u.i.sign) {
case H5T_SGN_NONE:
s1 = "unsigned";
break;
case H5T_SGN_2:
s1 = NULL;
break;
default:
s1 = "sign?";
break;
}
if (s1) fprintf(stream, ", %s", s1);
break;
case H5T_FLOAT:
switch (dt->shared->u.atomic.u.f.norm) {
case H5T_NORM_IMPLIED:
s1 = "implied";
break;
case H5T_NORM_MSBSET:
s1 = "msbset";
break;
case H5T_NORM_NONE:
s1 = "no-norm";
break;
default:
s1 = "norm?";
break;
}
fprintf(stream, ", sign=%lu+1",
(unsigned long) (dt->shared->u.atomic.u.f.sign));
fprintf(stream, ", mant=%lu+%lu (%s)",
(unsigned long) (dt->shared->u.atomic.u.f.mpos),
(unsigned long) (dt->shared->u.atomic.u.f.msize), s1);
fprintf(stream, ", exp=%lu+%lu",
(unsigned long) (dt->shared->u.atomic.u.f.epos),
(unsigned long) (dt->shared->u.atomic.u.f.esize));
tmp = dt->shared->u.atomic.u.f.ebias >> 32;
if (tmp) {
size_t hi=(size_t)tmp;
size_t lo =(size_t)(dt->shared->u.atomic.u.f.ebias & 0xffffffff);
fprintf(stream, " bias=0x%08lx%08lx",
(unsigned long)hi, (unsigned long)lo);
} else {
size_t lo = (size_t)(dt->shared->u.atomic.u.f.ebias & 0xffffffff);
fprintf(stream, " bias=0x%08lx", (unsigned long)lo);
}
break;
default:
/* No additional info */
break;
}
} else if (H5T_COMPOUND==dt->shared->type) {
/* Compound data type */
for (i=0; i<dt->shared->u.compnd.nmembs; i++) {
fprintf(stream, "\n\"%s\" @%lu",
dt->shared->u.compnd.memb[i].name,
(unsigned long) (dt->shared->u.compnd.memb[i].offset));
fprintf(stream, " ");
H5T_debug(dt->shared->u.compnd.memb[i].type, stream);
}
fprintf(stream, "\n");
} else if (H5T_VLEN==dt->shared->type) {
switch(dt->shared->u.vlen.loc) {
case H5T_VLEN_MEMORY:
fprintf(stream, ", loc=memory");
break;
case H5T_VLEN_DISK:
fprintf(stream, ", loc=disk");
break;
default:
fprintf(stream, ", loc=UNKNOWN");
break;
} /* end switch */
if(H5T_IS_VL_STRING(dt->shared)) {
/* Variable length string datatype */
fprintf(stream, ", variable-length");
} /* end if */
else {
/* Variable length sequence datatype */
fprintf(stream, " VLEN ");
H5T_debug(dt->shared->parent, stream);
fprintf(stream, "\n");
} /* end else */
} else if (H5T_ENUM==dt->shared->type) {
/* Enumeration data type */
fprintf(stream, " ");
H5T_debug(dt->shared->parent, stream);
base_size = dt->shared->parent->shared->size;
for (i=0; i<dt->shared->u.enumer.nmembs; i++) {
fprintf(stream, "\n\"%s\" = 0x", dt->shared->u.enumer.name[i]);
for (k=0; k<base_size; k++) {
fprintf(stream, "%02lx",
(unsigned long)(dt->shared->u.enumer.value+i*base_size+k));
}
}
fprintf(stream, "\n");
} else if (H5T_OPAQUE==dt->shared->type) {
fprintf(stream, ", tag=\"%s\"", dt->shared->u.opaque.tag);
} else {
/* Unknown */
fprintf(stream, "unknown class %d\n", (int)(dt->shared->type));
}
fprintf(stream, "}");
done:
FUNC_LEAVE_NOAPI(ret_value);
}
syntax highlighted by Code2HTML, v. 0.9.1