mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-01-30 15:32:37 +08:00
a0445d806c
* Take a stab at using constructors to initialize instead of function-entry macros. This is a work in progress. It's good enough to run `many_dsets`. * Committing clang-format changes * Add the `many_dsets` benchmark and some scripts I used on jelly for setting up the build/test environment and for recording/flame-graphing profiles. * Committing clang-format changes * Change my Makefile and environment script to work both on jelly and on mayll (and probably on Summit). * Disable clang-format "fix." * Replace the `if (!H5_TERM_GLOBAL)` test in each FUNC_ENTER_ macro with `if (true)`. * Fix bad grammar in a comment. * Instead of labeling the H5*__init_package routines constructors, fold each into an initialization routine, H5*_init(), and call each of the H5*_init() routines. Call most of the H5*_init() routines from H5_init_library() in an explicit order that I found out earlier by instrumenting each __init_package routine and running the library tests. Roll H5FD*__init_package routines into H5FD*_init() routines. This change ends just-in-time initialization of package dependencies by package initializers. Don't track in per-package variables (H5_PKG_INIT_VAR) whether each package has been initialized. Instead, track in a single library variable whether the whole library is initialized or not. Drive the initialization of packages by H5_init_library() with a table of initializer routines. Also drive the termination of packages by H5_term_library() with a table. Perform initialization as needed from FUNC_ENTER_API_INIT(err). This basically restores the old behavior of that macro. Delete a bunch of #definitions in H5private.h that have fallen out of use with these changes. * Committing clang-format changes * Undo the bad auto-formatting that appears to have occurred in spite of my disabling it. Bracket some code in /* clang-format off */ /* clang-format on */ to prevent a recurrence. * Remove a diagnostic abort(). * Fix a logic error: print a comma between every package terminator run, and don't print an initial comma. * Complete the changes I started in H5_term_library() that undo the bad auto-formatting. Stop tracking whether package "tops" were initialized in per-package variables H5*_top_package_initialize_s. H5_term_library() takes care of that for them. Remove H5R_top_term_package() and H5R_term_package(), they don't do anything. * Committing clang-format changes * NFCI. Simplify macro text: replace `if (true) {` with `{`. * Fix formatting and suppress clang-format on a longer range. * Quiet some unused label, unused variable complaints that cropped up after I simplified the FUNC_ENTER_ macros for the sake of performance. * Committing clang-format changes * Delete some programs and scripts that don't belong in the pull request. * Use the right function-entry macro. * Use a sensible format and disable auto-formatting. * Stop calling do-nothing initializer H5FS_init(). Delete it. * Document what changes to make if the default VFD changes. * While I am here, change an `await_prior` flag on the terminator table to `true` to match the previous, non-table-driven code that was here. Found the oversight making the following changes: NFCI: insert an empty line and copy over slightly-edited comments from the previous version, where those comments still correctly explained how library termination operated. * NFCI: lower a staircase. * Replace every occurrence of FUNC_ENTER_NOAPI_INIT(...) with H5_PUSH_FUNC since that is all that that macro does any more. Quiet a bunch of new warnings by changing FUNC_ENTER_NOAPI(...) to FUNC_ENTER_NOAPI_NOERR and removing disused `done:` labels. * NFCI: add curly braces around a multiline statement. * Quiet a signed/unsigned comparison warning. * Add some documentation about library initialization and shutdown. * Make sure that the library is initialized, or else that initialization is already underway, before performing any VFD's initialization. * Committing clang-format changes * Committing clang-format changes * Reduce differences from `develop` branch. * Always initialize `tot_init`. * Committing clang-format changes * Fix typo: H5SL_init initializes skip lists, not VOL. * Remove H5_TERM_GLOBAL test in H5T_init. H5T_init was unusual in that it tested H5_TERM_GLOBAL and exited early if it was set. No other module initializers did that, and I cannot find any reason that should be necessary. Tests still pass when I remove it, so away it goes. * Use HD prefix. * Add function header comments. * Drop the intermediate variable, it's only used once. * Extract subroutine `H5FDperform_init(hid_t (*init)(void))` that initializes the library, if necessary, before calling its VFD-initializer argument. Use H5FDperform_init in the definition of the symbols H5FD_<vfd> (e.g., H5FD_SEC2), which may be evaluated before the library is initialized, like so: ``` ``` I implement H5FDperform_init in its own source file, H5FDperform.c, and exclude that file from trace processing because the `bin/trace` cannot deal with the function-pointer type. * Straggler from last: add new source file src/H5FDperform.c. * Committing clang-format changes * Add a missing file to the MANIFEST. * Switch to FUNC_ENTER_API_NOINIT in H5FDperform_init() and hbool_t in H5_term_library(). Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
6292 lines
254 KiB
C
6292 lines
254 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* Copyright by The HDF Group. *
|
|
* Copyright by the Board of Trustees of the University of Illinois. *
|
|
* All rights reserved. *
|
|
* *
|
|
* This file is part of HDF5. The full HDF5 copyright notice, including *
|
|
* terms governing use, modification, and redistribution, is contained in *
|
|
* the COPYING file, which can be found at the root of the source code *
|
|
* distribution tree, or in https://www.hdfgroup.org/licenses. *
|
|
* 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.
|
|
*/
|
|
|
|
/****************/
|
|
/* Module Setup */
|
|
/****************/
|
|
|
|
#include "H5Tmodule.h" /* This source code file is part of the H5T module */
|
|
|
|
/***********/
|
|
/* Headers */
|
|
/***********/
|
|
#include "H5private.h" /* Generic Functions */
|
|
#include "H5ACprivate.h" /* Metadata cache */
|
|
#include "H5CXprivate.h" /* API Contexts */
|
|
#include "H5Dprivate.h" /* Datasets */
|
|
#include "H5Eprivate.h" /* Error handling */
|
|
#include "H5ESprivate.h" /* Event Sets */
|
|
#include "H5Fprivate.h" /* Files */
|
|
#include "H5FLprivate.h" /* Free Lists */
|
|
#include "H5FOprivate.h" /* File objects */
|
|
#include "H5Gprivate.h" /* Groups */
|
|
#include "H5Iprivate.h" /* IDs */
|
|
#include "H5MMprivate.h" /* Memory management */
|
|
#include "H5Pprivate.h" /* Property lists */
|
|
#include "H5Tpkg.h" /* Datatypes */
|
|
#include "H5VLprivate.h" /* Virtual Object Layer */
|
|
|
|
/****************/
|
|
/* Local Macros */
|
|
/****************/
|
|
|
|
#define H5T_ENCODE_VERSION 0
|
|
|
|
/*
|
|
* 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 bitfields for the "GUTS" in the H5T_INIT_TYPE macro */
|
|
#define H5T_INIT_TYPE_BITFIELD_CORE \
|
|
{ \
|
|
dt->shared->type = H5T_BITFIELD; \
|
|
}
|
|
|
|
#define H5T_INIT_TYPE_BITFIELD_COMMON(ENDIANNESS) \
|
|
{ \
|
|
H5T_INIT_TYPE_NUM_COMMON(ENDIANNESS) \
|
|
H5T_INIT_TYPE_BITFIELD_CORE; \
|
|
}
|
|
|
|
#define H5T_INIT_TYPE_BITFIELDLE_CORE \
|
|
{ \
|
|
H5T_INIT_TYPE_BITFIELD_COMMON(H5T_ORDER_LE) \
|
|
}
|
|
|
|
#define H5T_INIT_TYPE_BITFIELDBE_CORE \
|
|
{ \
|
|
H5T_INIT_TYPE_BITFIELD_COMMON(H5T_ORDER_BE) \
|
|
}
|
|
|
|
/* 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 VAX float for the "GUTS" in the H5T_INIT_TYPE macro */
|
|
#define H5T_INIT_TYPE_FLOATVAX_CORE \
|
|
{ \
|
|
H5T_INIT_TYPE_NUM_COMMON(H5T_ORDER_VAX) \
|
|
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 = 0x81; \
|
|
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; \
|
|
dt->shared->version = H5O_DTYPE_VERSION_3; \
|
|
}
|
|
|
|
/* Define the code templates for VAX double for the "GUTS" in the H5T_INIT_TYPE macro */
|
|
#define H5T_INIT_TYPE_DOUBLEVAX_CORE \
|
|
{ \
|
|
H5T_INIT_TYPE_NUM_COMMON(H5T_ORDER_VAX) \
|
|
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 = 0x0401; \
|
|
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; \
|
|
dt->shared->version = H5O_DTYPE_VERSION_3; \
|
|
}
|
|
|
|
/* 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->sh_loc.type = H5O_SHARE_TYPE_UNSHARED; \
|
|
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_xstrdup(""); \
|
|
}
|
|
|
|
/* 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 = H5F_DEFAULT_CSET; \
|
|
}
|
|
|
|
#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 \
|
|
{ \
|
|
H5T_INIT_TYPE_ALLOC_COMMON(H5T_REFERENCE) \
|
|
H5T_INIT_TYPE_NUM_COMMON(H5T_ORDER_NONE) \
|
|
dt->shared->force_conv = TRUE; \
|
|
dt->shared->u.atomic.u.r.file = NULL; \
|
|
dt->shared->u.atomic.u.r.loc = H5T_LOC_BADLOC; \
|
|
dt->shared->u.atomic.u.r.cls = NULL; \
|
|
}
|
|
|
|
#define H5T_INIT_TYPE_OBJREF_CORE \
|
|
{ \
|
|
H5T_INIT_TYPE_REF_COMMON \
|
|
dt->shared->u.atomic.u.r.rtype = H5R_OBJECT1; \
|
|
dt->shared->u.atomic.u.r.opaque = FALSE; \
|
|
dt->shared->u.atomic.u.r.version = 0; \
|
|
}
|
|
|
|
#define H5T_INIT_TYPE_REGREF_CORE \
|
|
{ \
|
|
H5T_INIT_TYPE_REF_COMMON \
|
|
dt->shared->u.atomic.u.r.rtype = H5R_DATASET_REGION1; \
|
|
dt->shared->u.atomic.u.r.opaque = FALSE; \
|
|
dt->shared->u.atomic.u.r.version = 0; \
|
|
}
|
|
|
|
/* rtype value is only used as a placeholder to differentiate the type from
|
|
* other types, any opaque (i.e. "new") reference type could be used.
|
|
*/
|
|
#define H5T_INIT_TYPE_REF_CORE \
|
|
{ \
|
|
H5T_INIT_TYPE_REF_COMMON \
|
|
dt->shared->u.atomic.u.r.rtype = H5R_OBJECT2; \
|
|
dt->shared->u.atomic.u.r.opaque = TRUE; \
|
|
dt->shared->u.atomic.u.r.version = H5R_ENCODE_VERSION; \
|
|
dt->shared->version = H5O_DTYPE_VERSION_4; \
|
|
}
|
|
|
|
/* 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_DATATYPE, 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_DATATYPE, H5E_CANTALLOC, 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) \
|
|
\
|
|
/* Register result */ \
|
|
if (((GLOBAL) = H5I_register(H5I_DATATYPE, dt, FALSE)) < 0) \
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom") \
|
|
}
|
|
|
|
/******************/
|
|
/* Local Typedefs */
|
|
/******************/
|
|
|
|
/* Typedef for recursive const-correct datatype copying routines */
|
|
typedef H5T_t *(*H5T_copy_func_t)(H5T_t *old_dt);
|
|
|
|
/********************/
|
|
/* Local Prototypes */
|
|
/********************/
|
|
static herr_t H5T__register_int(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst,
|
|
H5T_lib_conv_t func);
|
|
static herr_t H5T__register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_conv_func_t *conv);
|
|
static herr_t H5T__unregister(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_conv_t func);
|
|
static htri_t H5T__compiler_conv(H5T_t *src, H5T_t *dst);
|
|
static herr_t H5T__set_size(H5T_t *dt, size_t size);
|
|
static herr_t H5T__close_cb(H5T_t *dt, void **request);
|
|
static H5T_path_t *H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name,
|
|
H5T_conv_func_t *conv);
|
|
static hbool_t H5T__detect_vlen_ref(const H5T_t *dt);
|
|
static H5T_t * H5T__initiate_copy(const H5T_t *old_dt);
|
|
static H5T_t * H5T__copy_transient(H5T_t *old_dt);
|
|
static H5T_t * H5T__copy_all(H5T_t *old_dt);
|
|
static herr_t H5T__complete_copy(H5T_t *new_dt, const H5T_t *old_dt, H5T_shared_t *reopened_fo,
|
|
hbool_t set_memory_type, H5T_copy_func_t copyfn);
|
|
|
|
/*****************************/
|
|
/* Library Private Variables */
|
|
/*****************************/
|
|
|
|
/* The native endianness of the platform */
|
|
H5T_order_t H5T_native_order_g = H5T_ORDER_ERROR;
|
|
|
|
/*********************/
|
|
/* Package Variables */
|
|
/*********************/
|
|
|
|
/*
|
|
* Predefined data types. These are initialized at runtime in H5Tinit.c and
|
|
* by H5T_init() 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_package().
|
|
*/
|
|
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_VAX_F32_g = FAIL;
|
|
hid_t H5T_VAX_F64_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_STD_REF_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;
|
|
size_t H5T_REF_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.0F;
|
|
float H5T_NATIVE_FLOAT_NEG_INF_g = 0.0F;
|
|
double H5T_NATIVE_DOUBLE_POS_INF_g = 0.0;
|
|
double H5T_NATIVE_DOUBLE_NEG_INF_g = 0.0;
|
|
|
|
/* Declare the free list for H5T_t's and H5T_shared_t's */
|
|
H5FL_DEFINE(H5T_t);
|
|
H5FL_DEFINE(H5T_shared_t);
|
|
|
|
/* Format version bounds for datatype */
|
|
const unsigned H5O_dtype_ver_bounds[] = {
|
|
H5O_DTYPE_VERSION_1, /* H5F_LIBVER_EARLIEST */
|
|
H5O_DTYPE_VERSION_3, /* H5F_LIBVER_V18 */
|
|
H5O_DTYPE_VERSION_3, /* H5F_LIBVER_V110 */
|
|
H5O_DTYPE_VERSION_4, /* H5F_LIBVER_V112 */
|
|
H5O_DTYPE_VERSION_LATEST /* H5F_LIBVER_LATEST */
|
|
};
|
|
|
|
/*******************/
|
|
/* Local Variables */
|
|
/*******************/
|
|
|
|
/*
|
|
* 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 */
|
|
size_t apaths; /*number of paths allocated */
|
|
H5T_path_t **path; /*sorted array of path pointers */
|
|
int nsoft; /*number of soft conversions defined */
|
|
size_t asoft; /*number of soft conversions allocated */
|
|
H5T_soft_t * soft; /*unsorted array of soft conversions */
|
|
} H5T_g;
|
|
|
|
/* Declare the free list for H5T_path_t's */
|
|
H5FL_DEFINE_STATIC(H5T_path_t);
|
|
|
|
/* Datatype ID class */
|
|
static const H5I_class_t H5I_DATATYPE_CLS[1] = {{
|
|
H5I_DATATYPE, /* ID class value */
|
|
0, /* Class flags */
|
|
8, /* # of reserved IDs for class */
|
|
(H5I_free_t)H5T__close_cb /* Callback routine for closing objects of this class */
|
|
}};
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
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_STATIC
|
|
|
|
/* Get the float datatype */
|
|
if (NULL == (dst_p = (H5T_t *)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;
|
|
} /* end for */
|
|
} /* end if */
|
|
|
|
/* -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;
|
|
} /* end for */
|
|
} /* end if */
|
|
|
|
/* Get the double datatype */
|
|
if (NULL == (dst_p = (H5T_t *)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;
|
|
} /* end for */
|
|
} /* end if */
|
|
|
|
/* -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;
|
|
} /* end for */
|
|
} /* end if */
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T__init_inf() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_init
|
|
*
|
|
* Purpose: Initialize the interface from some other layer.
|
|
*
|
|
* Return: Success: non-negative
|
|
* Failure: negative
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5T_init(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 * native_ldouble = NULL; /* Datatype structure for native long 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_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 * 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 */
|
|
H5T_t * objref = NULL; /* Datatype structure for deprecated reference objects */
|
|
H5T_t * regref = NULL; /* Datatype structure for deprecated region references */
|
|
H5T_t * ref = NULL; /* Datatype structure for opaque references */
|
|
hsize_t dim[1] = {1}; /* Dimension info for array datatype */
|
|
herr_t status;
|
|
hbool_t copied_dtype =
|
|
TRUE; /* Flag to indicate whether datatype was copied or allocated (for error cleanup) */
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI(FAIL)
|
|
|
|
/* Initialize the ID group for the file IDs */
|
|
if (H5I_register_type(H5I_DATATYPE_CLS) < 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 */
|
|
HDcompile_assert(H5T_NCLASSES < 16);
|
|
|
|
/*
|
|
* Initialize pre-defined native datatypes from code generated during
|
|
* the library configuration by H5detect.
|
|
*/
|
|
if (H5T__init_native() < 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 = (H5T_t *)H5I_object(H5T_NATIVE_SCHAR_g)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object")
|
|
if (NULL == (native_uchar = (H5T_t *)H5I_object(H5T_NATIVE_UCHAR_g)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object")
|
|
if (NULL == (native_short = (H5T_t *)H5I_object(H5T_NATIVE_SHORT_g)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object")
|
|
if (NULL == (native_ushort = (H5T_t *)H5I_object(H5T_NATIVE_USHORT_g)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object")
|
|
if (NULL == (native_int = (H5T_t *)H5I_object(H5T_NATIVE_INT_g)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object")
|
|
if (NULL == (native_uint = (H5T_t *)H5I_object(H5T_NATIVE_UINT_g)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object")
|
|
if (NULL == (native_long = (H5T_t *)H5I_object(H5T_NATIVE_LONG_g)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object")
|
|
if (NULL == (native_ulong = (H5T_t *)H5I_object(H5T_NATIVE_ULONG_g)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object")
|
|
if (NULL == (native_llong = (H5T_t *)H5I_object(H5T_NATIVE_LLONG_g)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object")
|
|
if (NULL == (native_ullong = (H5T_t *)H5I_object(H5T_NATIVE_ULLONG_g)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object")
|
|
if (NULL == (native_float = (H5T_t *)H5I_object(H5T_NATIVE_FLOAT_g)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object")
|
|
if (NULL == (native_double = (H5T_t *)H5I_object(H5T_NATIVE_DOUBLE_g)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object")
|
|
if (NULL == (native_ldouble = (H5T_t *)H5I_object(H5T_NATIVE_LDOUBLE_g)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object")
|
|
|
|
/*------------------------------------------------------------
|
|
* Derived 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_uint, 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 8-byte big-endian float */
|
|
H5T_INIT_TYPE(DOUBLEBE, H5T_IEEE_F64BE_g, COPY, native_double, SET, 8)
|
|
|
|
/*------------------------------------------------------------
|
|
* VAX Types
|
|
*------------------------------------------------------------
|
|
*/
|
|
|
|
/* VAX 4-byte float */
|
|
H5T_INIT_TYPE(FLOATVAX, H5T_VAX_F32_g, COPY, native_double, SET, 4)
|
|
|
|
/* VAX 8-byte double */
|
|
H5T_INIT_TYPE(DOUBLEVAX, H5T_VAX_F64_g, COPY, native_double, SET, 8)
|
|
|
|
/*------------------------------------------------------------
|
|
* C99 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)
|
|
|
|
/* 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 */
|
|
|
|
/*------------------------------------------------------------
|
|
* Native, Little- & Big-endian bitfields
|
|
*------------------------------------------------------------
|
|
*/
|
|
|
|
/* little-endian (order is irrelevant) 8-bit bitfield */
|
|
H5T_INIT_TYPE(BITFIELDLE, 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(BITFIELDBE, H5T_STD_B8BE_g, COPY, std_u8be, NOSET, -)
|
|
|
|
/* Little-endian 16-bit bitfield */
|
|
H5T_INIT_TYPE(BITFIELDLE, H5T_STD_B16LE_g, COPY, std_u16le, NOSET, -)
|
|
|
|
/* Big-endian 16-bit bitfield */
|
|
H5T_INIT_TYPE(BITFIELDBE, H5T_STD_B16BE_g, COPY, std_u16be, NOSET, -)
|
|
|
|
/* Little-endian 32-bit bitfield */
|
|
H5T_INIT_TYPE(BITFIELDLE, H5T_STD_B32LE_g, COPY, std_u32le, NOSET, -)
|
|
|
|
/* Big-endian 32-bit bitfield */
|
|
H5T_INIT_TYPE(BITFIELDBE, H5T_STD_B32BE_g, COPY, std_u32be, NOSET, -)
|
|
|
|
/* Little-endian 64-bit bitfield */
|
|
H5T_INIT_TYPE(BITFIELDLE, H5T_STD_B64LE_g, COPY, std_u64le, NOSET, -)
|
|
|
|
/* Big-endian 64-bit bitfield */
|
|
H5T_INIT_TYPE(BITFIELDBE, 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 = FALSE;
|
|
|
|
/* 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)
|
|
|
|
/*------------------------------------------------------------
|
|
* Reference types
|
|
*------------------------------------------------------------
|
|
*/
|
|
|
|
/* Deprecated object reference type */
|
|
H5T_INIT_TYPE(OBJREF, H5T_STD_REF_OBJ_g, ALLOC, -, NOSET, -)
|
|
if (H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
|
|
objref = dt; /* Keep type for later */
|
|
|
|
/* Deprecated region reference type */
|
|
H5T_INIT_TYPE(REGREF, H5T_STD_REF_DSETREG_g, ALLOC, -, NOSET, -)
|
|
if (H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
|
|
regref = dt; /* Keep type for later */
|
|
|
|
/* Opaque reference type */
|
|
H5T_INIT_TYPE(REF, H5T_STD_REF_g, ALLOC, -, NOSET, -)
|
|
if (H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
|
|
ref = dt; /* Keep type for later */
|
|
|
|
/*
|
|
* 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)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
|
|
status = 0;
|
|
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "i_i", fixedpt, fixedpt, H5T__conv_i_i);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "i_f", fixedpt, floatpt, H5T__conv_i_f);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "f_f", floatpt, floatpt, H5T__conv_f_f);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "f_i", floatpt, fixedpt, H5T__conv_f_i);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "s_s", string, string, H5T__conv_s_s);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "b_b", bitfield, bitfield, H5T__conv_b_b);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "ibo", fixedpt, fixedpt, H5T__conv_order);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "ibo(opt)", fixedpt, fixedpt, H5T__conv_order_opt);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "fbo", floatpt, floatpt, H5T__conv_order);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "fbo(opt)", floatpt, floatpt, H5T__conv_order_opt);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "struct(no-opt)", compound, compound, H5T__conv_struct);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "struct(opt)", compound, compound, H5T__conv_struct_opt);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "enum", enum_type, enum_type, H5T__conv_enum);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "enum_i", enum_type, fixedpt, H5T__conv_enum_numeric);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "enum_f", enum_type, floatpt, H5T__conv_enum_numeric);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "vlen", vlen, vlen, H5T__conv_vlen);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "array", array, array, H5T__conv_array);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "objref", objref, objref, H5T__conv_noop);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "regref", regref, regref, H5T__conv_noop);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "ref", ref, ref, H5T__conv_ref);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "objref_ref", objref, ref, H5T__conv_ref);
|
|
status |= H5T__register_int(H5T_PERS_SOFT, "regref_ref", regref, ref, H5T__conv_ref);
|
|
|
|
/*
|
|
* 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_int(H5T_PERS_HARD, "flt_dbl", native_float, native_double, H5T__conv_float_double);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "dbl_flt", native_double, native_float, H5T__conv_double_float);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "flt_ldbl", native_float, native_ldouble, H5T__conv_float_ldouble);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "dbl_ldbl", native_double, native_ldouble, H5T__conv_double_ldouble);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ldbl_flt", native_ldouble, native_float, H5T__conv_ldouble_float);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ldbl_dbl", native_ldouble, native_double, H5T__conv_ldouble_double);
|
|
|
|
/* from long long */
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "llong_ullong", native_llong, native_ullong, H5T__conv_llong_ullong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ullong_llong", native_ullong, native_llong, H5T__conv_ullong_llong);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "llong_long", native_llong, native_long, H5T__conv_llong_long);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "llong_ulong", native_llong, native_ulong, H5T__conv_llong_ulong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ullong_long", native_ullong, native_long, H5T__conv_ullong_long);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ullong_ulong", native_ullong, native_ulong, H5T__conv_ullong_ulong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "llong_short", native_llong, native_short, H5T__conv_llong_short);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "llong_ushort", native_llong, native_ushort, H5T__conv_llong_ushort);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ullong_short", native_ullong, native_short, H5T__conv_ullong_short);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "ullong_ushort", native_ullong, native_ushort,
|
|
H5T__conv_ullong_ushort);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "llong_int", native_llong, native_int, H5T__conv_llong_int);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "llong_uint", native_llong, native_uint, H5T__conv_llong_uint);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "ullong_int", native_ullong, native_int, H5T__conv_ullong_int);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ullong_uint", native_ullong, native_uint, H5T__conv_ullong_uint);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "llong_schar", native_llong, native_schar, H5T__conv_llong_schar);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "llong_uchar", native_llong, native_uchar, H5T__conv_llong_uchar);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ullong_schar", native_ullong, native_schar, H5T__conv_ullong_schar);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ullong_uchar", native_ullong, native_uchar, H5T__conv_ullong_uchar);
|
|
|
|
/* From long */
|
|
status |= H5T__register_int(H5T_PERS_HARD, "long_llong", native_long, native_llong, H5T__conv_long_llong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "long_ullong", native_long, native_ullong, H5T__conv_long_ullong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ulong_llong", native_ulong, native_llong, H5T__conv_ulong_llong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ulong_ullong", native_ulong, native_ullong, H5T__conv_ulong_ullong);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "long_ulong", native_long, native_ulong, H5T__conv_long_ulong);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "ulong_long", native_ulong, native_long, H5T__conv_ulong_long);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "long_short", native_long, native_short, H5T__conv_long_short);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "long_ushort", native_long, native_ushort, H5T__conv_long_ushort);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ulong_short", native_ulong, native_short, H5T__conv_ulong_short);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ulong_ushort", native_ulong, native_ushort, H5T__conv_ulong_ushort);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "long_int", native_long, native_int, H5T__conv_long_int);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "long_uint", native_long, native_uint, H5T__conv_long_uint);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "ulong_int", native_ulong, native_int, H5T__conv_ulong_int);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "ulong_uint", native_ulong, native_uint, H5T__conv_ulong_uint);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "long_schar", native_long, native_schar, H5T__conv_long_schar);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "long_uchar", native_long, native_uchar, H5T__conv_long_uchar);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ulong_schar", native_ulong, native_schar, H5T__conv_ulong_schar);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ulong_uchar", native_ulong, native_uchar, H5T__conv_ulong_uchar);
|
|
|
|
/* From short */
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "short_llong", native_short, native_llong, H5T__conv_short_llong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "short_ullong", native_short, native_ullong, H5T__conv_short_ullong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ushort_llong", native_ushort, native_llong, H5T__conv_ushort_llong);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "ushort_ullong", native_ushort, native_ullong,
|
|
H5T__conv_ushort_ullong);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "short_long", native_short, native_long, H5T__conv_short_long);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "short_ulong", native_short, native_ulong, H5T__conv_short_ulong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ushort_long", native_ushort, native_long, H5T__conv_ushort_long);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ushort_ulong", native_ushort, native_ulong, H5T__conv_ushort_ulong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "short_ushort", native_short, native_ushort, H5T__conv_short_ushort);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ushort_short", native_ushort, native_short, H5T__conv_ushort_short);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "short_int", native_short, native_int, H5T__conv_short_int);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "short_uint", native_short, native_uint, H5T__conv_short_uint);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "ushort_int", native_ushort, native_int, H5T__conv_ushort_int);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ushort_uint", native_ushort, native_uint, H5T__conv_ushort_uint);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "short_schar", native_short, native_schar, H5T__conv_short_schar);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "short_uchar", native_short, native_uchar, H5T__conv_short_uchar);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ushort_schar", native_ushort, native_schar, H5T__conv_ushort_schar);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ushort_uchar", native_ushort, native_uchar, H5T__conv_ushort_uchar);
|
|
|
|
/* From int */
|
|
status |= H5T__register_int(H5T_PERS_HARD, "int_llong", native_int, native_llong, H5T__conv_int_llong);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "int_ullong", native_int, native_ullong, H5T__conv_int_ullong);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "uint_llong", native_uint, native_llong, H5T__conv_uint_llong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "uint_ullong", native_uint, native_ullong, H5T__conv_uint_ullong);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "int_long", native_int, native_long, H5T__conv_int_long);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "int_ulong", native_int, native_ulong, H5T__conv_int_ulong);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "uint_long", native_uint, native_long, H5T__conv_uint_long);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "uint_ulong", native_uint, native_ulong, H5T__conv_uint_ulong);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "int_short", native_int, native_short, H5T__conv_int_short);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "int_ushort", native_int, native_ushort, H5T__conv_int_ushort);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "uint_short", native_uint, native_short, H5T__conv_uint_short);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "uint_ushort", native_uint, native_ushort, H5T__conv_uint_ushort);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "int_uint", native_int, native_uint, H5T__conv_int_uint);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "uint_int", native_uint, native_int, H5T__conv_uint_int);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "int_schar", native_int, native_schar, H5T__conv_int_schar);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "int_uchar", native_int, native_uchar, H5T__conv_int_uchar);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "uint_schar", native_uint, native_schar, H5T__conv_uint_schar);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "uint_uchar", native_uint, native_uchar, H5T__conv_uint_uchar);
|
|
|
|
/* From char */
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "schar_llong", native_schar, native_llong, H5T__conv_schar_llong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "schar_ullong", native_schar, native_ullong, H5T__conv_schar_ullong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "uchar_llong", native_uchar, native_llong, H5T__conv_uchar_llong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "uchar_ullong", native_uchar, native_ullong, H5T__conv_uchar_ullong);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "schar_long", native_schar, native_long, H5T__conv_schar_long);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "schar_ulong", native_schar, native_ulong, H5T__conv_schar_ulong);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "uchar_long", native_uchar, native_long, H5T__conv_uchar_long);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "uchar_ulong", native_uchar, native_ulong, H5T__conv_uchar_ulong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "schar_short", native_schar, native_short, H5T__conv_schar_short);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "schar_ushort", native_schar, native_ushort, H5T__conv_schar_ushort);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "uchar_short", native_uchar, native_short, H5T__conv_uchar_short);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "uchar_ushort", native_uchar, native_ushort, H5T__conv_uchar_ushort);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "schar_int", native_schar, native_int, H5T__conv_schar_int);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "schar_uint", native_schar, native_uint, H5T__conv_schar_uint);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "uchar_int", native_uchar, native_int, H5T__conv_uchar_int);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "uchar_uint", native_uchar, native_uint, H5T__conv_uchar_uint);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "schar_uchar", native_schar, native_uchar, H5T__conv_schar_uchar);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "uchar_schar", native_uchar, native_schar, H5T__conv_uchar_schar);
|
|
|
|
/* From char to floats */
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "schar_flt", native_schar, native_float, H5T__conv_schar_float);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "schar_dbl", native_schar, native_double, H5T__conv_schar_double);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "schar_ldbl", native_schar, native_ldouble, H5T__conv_schar_ldouble);
|
|
|
|
/* From unsigned char to floats */
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "uchar_flt", native_uchar, native_float, H5T__conv_uchar_float);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "uchar_dbl", native_uchar, native_double, H5T__conv_uchar_double);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "uchar_ldbl", native_uchar, native_ldouble, H5T__conv_uchar_ldouble);
|
|
|
|
/* From short to floats */
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "short_flt", native_short, native_float, H5T__conv_short_float);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "short_dbl", native_short, native_double, H5T__conv_short_double);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "short_ldbl", native_short, native_ldouble, H5T__conv_short_ldouble);
|
|
|
|
/* From unsigned short to floats */
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ushort_flt", native_ushort, native_float, H5T__conv_ushort_float);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ushort_dbl", native_ushort, native_double, H5T__conv_ushort_double);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "ushort_ldbl", native_ushort, native_ldouble,
|
|
H5T__conv_ushort_ldouble);
|
|
|
|
/* From int to floats */
|
|
status |= H5T__register_int(H5T_PERS_HARD, "int_flt", native_int, native_float, H5T__conv_int_float);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "int_dbl", native_int, native_double, H5T__conv_int_double);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "int_ldbl", native_int, native_ldouble, H5T__conv_int_ldouble);
|
|
|
|
/* From unsigned int to floats */
|
|
status |= H5T__register_int(H5T_PERS_HARD, "uint_flt", native_uint, native_float, H5T__conv_uint_float);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "uint_dbl", native_uint, native_double, H5T__conv_uint_double);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "uint_ldbl", native_uint, native_ldouble, H5T__conv_uint_ldouble);
|
|
|
|
/* From long to floats */
|
|
status |= H5T__register_int(H5T_PERS_HARD, "long_flt", native_long, native_float, H5T__conv_long_float);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "long_dbl", native_long, native_double, H5T__conv_long_double);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "long_ldbl", native_long, native_ldouble, H5T__conv_long_ldouble);
|
|
|
|
/* From unsigned long to floats */
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ulong_flt", native_ulong, native_float, H5T__conv_ulong_float);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ulong_dbl", native_ulong, native_double, H5T__conv_ulong_double);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ulong_ldbl", native_ulong, native_ldouble, H5T__conv_ulong_ldouble);
|
|
|
|
/* From long long to floats */
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "llong_flt", native_llong, native_float, H5T__conv_llong_float);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "llong_dbl", native_llong, native_double, H5T__conv_llong_double);
|
|
#ifdef H5T_CONV_INTERNAL_LLONG_LDOUBLE
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "llong_ldbl", native_llong, native_ldouble, H5T__conv_llong_ldouble);
|
|
#endif /* H5T_CONV_INTERNAL_LLONG_LDOUBLE */
|
|
|
|
/* From unsigned long long to floats */
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ullong_flt", native_ullong, native_float, H5T__conv_ullong_float);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ullong_dbl", native_ullong, native_double, H5T__conv_ullong_double);
|
|
#ifdef H5T_CONV_INTERNAL_ULLONG_LDOUBLE
|
|
status |= H5T__register_int(H5T_PERS_HARD, "ullong_ldbl", native_ullong, native_ldouble,
|
|
H5T__conv_ullong_ldouble);
|
|
#endif /* H5T_CONV_INTERNAL_ULLONG_LDOUBLE */
|
|
|
|
/* From floats to char */
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "flt_schar", native_float, native_schar, H5T__conv_float_schar);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "dbl_schar", native_double, native_schar, H5T__conv_double_schar);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ldbl_schar", native_ldouble, native_schar, H5T__conv_ldouble_schar);
|
|
|
|
/* From floats to unsigned char */
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "flt_uchar", native_float, native_uchar, H5T__conv_float_uchar);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "dbl_uchar", native_double, native_uchar, H5T__conv_double_uchar);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ldbl_uchar", native_ldouble, native_uchar, H5T__conv_ldouble_uchar);
|
|
|
|
/* From floats to short */
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "flt_short", native_float, native_short, H5T__conv_float_short);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "dbl_short", native_double, native_short, H5T__conv_double_short);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ldbl_short", native_ldouble, native_short, H5T__conv_ldouble_short);
|
|
|
|
/* From floats to unsigned short */
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "flt_ushort", native_float, native_ushort, H5T__conv_float_ushort);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "dbl_ushort", native_double, native_ushort, H5T__conv_double_ushort);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "ldbl_ushort", native_ldouble, native_ushort,
|
|
H5T__conv_ldouble_ushort);
|
|
|
|
/* From floats to int */
|
|
status |= H5T__register_int(H5T_PERS_HARD, "flt_int", native_float, native_int, H5T__conv_float_int);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "dbl_int", native_double, native_int, H5T__conv_double_int);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "ldbl_int", native_ldouble, native_int, H5T__conv_ldouble_int);
|
|
|
|
/* From floats to unsigned int */
|
|
status |= H5T__register_int(H5T_PERS_HARD, "flt_uint", native_float, native_uint, H5T__conv_float_uint);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "dbl_uint", native_double, native_uint, H5T__conv_double_uint);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ldbl_uint", native_ldouble, native_uint, H5T__conv_ldouble_uint);
|
|
|
|
/* From floats to long */
|
|
status |= H5T__register_int(H5T_PERS_HARD, "flt_long", native_float, native_long, H5T__conv_float_long);
|
|
status |= H5T__register_int(H5T_PERS_HARD, "dbl_long", native_double, native_long, H5T__conv_double_long);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ldbl_long", native_ldouble, native_long, H5T__conv_ldouble_long);
|
|
|
|
/* From floats to unsigned long */
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "flt_ulong", native_float, native_ulong, H5T__conv_float_ulong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "dbl_ulong", native_double, native_ulong, H5T__conv_double_ulong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ldbl_ulong", native_ldouble, native_ulong, H5T__conv_ldouble_ulong);
|
|
|
|
/* From floats to long long */
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "flt_llong", native_float, native_llong, H5T__conv_float_llong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "dbl_llong", native_double, native_llong, H5T__conv_double_llong);
|
|
#ifdef H5T_CONV_INTERNAL_LDOUBLE_LLONG
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "ldbl_llong", native_ldouble, native_llong, H5T__conv_ldouble_llong);
|
|
#endif /* H5T_CONV_INTERNAL_LDOUBLE_LLONG */
|
|
|
|
/* From floats to unsigned long long */
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "flt_ullong", native_float, native_ullong, H5T__conv_float_ullong);
|
|
status |=
|
|
H5T__register_int(H5T_PERS_HARD, "dbl_ullong", native_double, native_ullong, H5T__conv_double_ullong);
|
|
#if H5T_CONV_INTERNAL_LDOUBLE_ULLONG
|
|
status |= H5T__register_int(H5T_PERS_HARD, "ldbl_ullong", native_ldouble, native_ullong,
|
|
H5T__conv_ldouble_ullong);
|
|
#endif /* H5T_CONV_INTERNAL_LDOUBLE_ULLONG */
|
|
|
|
/*
|
|
* 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_int(H5T_PERS_HARD, "no-op", native_int, native_int, H5T__conv_noop);
|
|
|
|
/* 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)")
|
|
|
|
/* Register datatype creation property class properties here. See similar
|
|
* code in H5D_init(), etc. for example.
|
|
*/
|
|
|
|
/* Only register the default property list if it hasn't been created yet */
|
|
if (H5P_LST_DATATYPE_CREATE_ID_g == (-1)) {
|
|
/* ========== Datatype Creation Property Class Initialization ============*/
|
|
HDassert(H5P_CLS_DATATYPE_CREATE_g != NULL);
|
|
|
|
/* Register the default datatype creation property list */
|
|
if ((H5P_LST_DATATYPE_CREATE_ID_g = H5P_create_id(H5P_CLS_DATATYPE_CREATE_g, FALSE)) < 0)
|
|
HGOTO_ERROR(H5E_PLIST, H5E_CANTREGISTER, FAIL, "can't insert property into class")
|
|
} /* end if */
|
|
|
|
done:
|
|
/* General cleanup */
|
|
if (compound != NULL)
|
|
(void)H5T_close_real(compound);
|
|
if (enum_type != NULL)
|
|
(void)H5T_close_real(enum_type);
|
|
if (vlen != NULL)
|
|
(void)H5T_close_real(vlen);
|
|
if (array != NULL)
|
|
(void)H5T_close_real(array);
|
|
|
|
/* Error cleanup */
|
|
if (ret_value < 0) {
|
|
if (dt) {
|
|
/* Check if we should call H5T_close_real or H5FL_FREE */
|
|
if (copied_dtype)
|
|
(void)H5T_close_real(dt);
|
|
else {
|
|
if (dt->shared->owned_vol_obj && H5VL_free_object(dt->shared->owned_vol_obj) < 0)
|
|
HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close owned VOL object")
|
|
dt->shared = H5FL_FREE(H5T_shared_t, dt->shared);
|
|
dt = H5FL_FREE(H5T_t, dt);
|
|
} /* end else */
|
|
} /* end if */
|
|
} /* end if */
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_init() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T__unlock_cb
|
|
*
|
|
* Purpose: Clear the immutable flag for a datatype. This function is
|
|
* called when the library is closing in order to unlock all
|
|
* registered datatypes and thus make them free-able.
|
|
*
|
|
* Return: Non-negative on success/Negative on failure
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Monday, April 27, 1998
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static int
|
|
H5T__unlock_cb(void *_dt, hid_t H5_ATTR_UNUSED id, void *_udata)
|
|
{
|
|
H5T_t *dt = (H5T_t *)_dt;
|
|
int * n = (int *)_udata;
|
|
|
|
FUNC_ENTER_STATIC_NOERR
|
|
|
|
HDassert(dt);
|
|
HDassert(dt->shared);
|
|
|
|
if (H5T_STATE_IMMUTABLE == dt->shared->state) {
|
|
dt->shared->state = H5T_STATE_RDONLY;
|
|
(*n)++;
|
|
} /* end if */
|
|
|
|
FUNC_LEAVE_NOAPI(SUCCEED)
|
|
} /* end H5T__unlock_cb() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_top_term_package
|
|
*
|
|
* Purpose: Close the "top" of the interface, releasing IDs, etc.
|
|
*
|
|
* Return: Success: Positive if any action might have caused a
|
|
* change in some other interface; zero otherwise.
|
|
* Failure: Negative
|
|
*
|
|
* Programmer: Quincey Koziol
|
|
* Thursday, September 10, 2015
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
int
|
|
H5T_top_term_package(void)
|
|
{
|
|
int n = 0;
|
|
|
|
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
|
|
|
/* Unregister all conversion functions */
|
|
if (H5T_g.path) {
|
|
int i, nprint = 0;
|
|
|
|
for (i = 0; i < H5T_g.npaths; i++) {
|
|
H5T_path_t *path;
|
|
|
|
path = H5T_g.path[i];
|
|
HDassert(path);
|
|
if (path->conv.u.app_func) {
|
|
H5T__print_stats(path, &nprint /*in,out*/);
|
|
path->cdata.command = H5T_CONV_FREE;
|
|
if (path->conv.is_app) {
|
|
if ((path->conv.u.app_func)((hid_t)FAIL, (hid_t)FAIL, &(path->cdata), (size_t)0,
|
|
(size_t)0, (size_t)0, NULL, NULL, H5CX_get_dxpl()) < 0) {
|
|
#ifdef H5T_DEBUG
|
|
if (H5DEBUG(T)) {
|
|
HDfprintf(H5DEBUG(T),
|
|
"H5T: conversion function "
|
|
"0x%08lx failed to free private data for "
|
|
"%s (ignored)\n",
|
|
(unsigned long)(path->conv.u.app_func), path->name);
|
|
} /* end if */
|
|
#endif
|
|
H5E_clear_stack(NULL); /*ignore the error*/
|
|
} /* end if */
|
|
} /* end if */
|
|
else {
|
|
if ((path->conv.u.lib_func)((hid_t)FAIL, (hid_t)FAIL, &(path->cdata), (size_t)0,
|
|
(size_t)0, (size_t)0, NULL, NULL) < 0) {
|
|
#ifdef H5T_DEBUG
|
|
if (H5DEBUG(T)) {
|
|
HDfprintf(H5DEBUG(T),
|
|
"H5T: conversion function "
|
|
"0x%08lx failed to free private data for "
|
|
"%s (ignored)\n",
|
|
(unsigned long)(path->conv.u.lib_func), path->name);
|
|
} /* end if */
|
|
#endif
|
|
H5E_clear_stack(NULL); /*ignore the error*/
|
|
} /* end if */
|
|
} /* end else */
|
|
} /* end if */
|
|
|
|
if (path->src)
|
|
(void)H5T_close_real(path->src);
|
|
if (path->dst)
|
|
(void)H5T_close_real(path->dst);
|
|
path = H5FL_FREE(H5T_path_t, path);
|
|
H5T_g.path[i] = NULL;
|
|
} /* end for */
|
|
|
|
/* Clear conversion tables */
|
|
H5T_g.path = (H5T_path_t **)H5MM_xfree(H5T_g.path);
|
|
H5T_g.npaths = 0;
|
|
H5T_g.apaths = 0;
|
|
H5T_g.soft = (H5T_soft_t *)H5MM_xfree(H5T_g.soft);
|
|
H5T_g.nsoft = 0;
|
|
H5T_g.asoft = 0;
|
|
|
|
n++;
|
|
} /* end if */
|
|
|
|
/* Unlock all datatypes, then free them */
|
|
/* note that we are ignoring the return value from H5I_iterate() */
|
|
/* Also note that we are incrementing 'n' in the callback */
|
|
H5I_iterate(H5I_DATATYPE, H5T__unlock_cb, &n, FALSE);
|
|
|
|
/* Release all datatype IDs */
|
|
if (H5I_nmembers(H5I_DATATYPE) > 0) {
|
|
(void)H5I_clear_type(H5I_DATATYPE, FALSE, FALSE);
|
|
n++; /*H5I*/
|
|
} /* end if */
|
|
|
|
/* Reset all the datatype IDs */
|
|
if (H5T_IEEE_F32BE_g > 0) {
|
|
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_STD_REF_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;
|
|
|
|
n++;
|
|
} /* end if */
|
|
|
|
FUNC_LEAVE_NOAPI(n)
|
|
} /* end H5T_top_term_package() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_term_package
|
|
*
|
|
* Purpose: Close this interface.
|
|
*
|
|
* Note: Finishes shutting down the interface, after
|
|
* H5T_top_term_package() is called
|
|
*
|
|
* 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
int
|
|
H5T_term_package(void)
|
|
{
|
|
int n = 0;
|
|
|
|
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
|
|
|
/* Sanity check */
|
|
HDassert(0 == H5I_nmembers(H5I_DATATYPE));
|
|
|
|
/* Destroy the datatype object id group */
|
|
n += (H5I_dec_type_ref(H5I_DATATYPE) > 0);
|
|
|
|
FUNC_LEAVE_NOAPI(n)
|
|
} /* end H5T_term_package() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T__close_cb
|
|
*
|
|
* Purpose: Called when the ref count reaches zero on the datatype's ID
|
|
*
|
|
* Return: SUCCEED/FAIL
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
H5T__close_cb(H5T_t *dt, void **request)
|
|
{
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_STATIC
|
|
|
|
/* Sanity check */
|
|
HDassert(dt);
|
|
HDassert(dt->shared);
|
|
|
|
/* If this datatype is VOL-managed (i.e.: has a VOL object),
|
|
* close it through the VOL connector.
|
|
*/
|
|
if (NULL != dt->vol_obj) {
|
|
/* Close the connector-managed datatype data */
|
|
if (H5VL_datatype_close(dt->vol_obj, H5P_DATASET_XFER_DEFAULT, request) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to close datatype")
|
|
|
|
/* Free the VOL object */
|
|
if (H5VL_free_object(dt->vol_obj) < 0)
|
|
HGOTO_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to free VOL object")
|
|
dt->vol_obj = NULL;
|
|
} /* end if */
|
|
|
|
/* Close the datatype */
|
|
if (H5T_close(dt) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to close datatype")
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T__close_cb() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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 datatype ID.
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Friday, December 5, 1997
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
hid_t
|
|
H5Tcreate(H5T_class_t type, size_t size)
|
|
{
|
|
H5T_t *dt = NULL; /* New datatype constructed */
|
|
hid_t ret_value; /* Return value */
|
|
|
|
FUNC_ENTER_API(FAIL)
|
|
H5TRACE2("i", "Ttz", type, size);
|
|
|
|
/* check args. We support string (fixed-size or variable-length) now. */
|
|
if (size <= 0 && size != H5T_VARIABLE)
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "size must be positive")
|
|
|
|
/* create the type */
|
|
if (NULL == (dt = H5T__create(type, size)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create type")
|
|
|
|
/* Get an ID for the datatype */
|
|
if ((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype ID")
|
|
|
|
done:
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Tcreate() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5Tcopy
|
|
*
|
|
* Purpose: Copies a datatype. The resulting datatype is not locked.
|
|
* The datatype should be closed when no longer needed by
|
|
* calling H5Tclose().
|
|
*
|
|
* Return: Success: The ID of a new datatype
|
|
*
|
|
* Failure: H5I_INVALID_HID
|
|
*
|
|
* Note: The returned type is always transient and unlocked. If the
|
|
* TYPE_ID argument is a dataset instead of a datatype then
|
|
* this function returns a transient, modifiable datatype
|
|
* which is a copy of the dataset's datatype.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
hid_t
|
|
H5Tcopy(hid_t obj_id)
|
|
{
|
|
H5T_t *dt = NULL; /* Pointer to the datatype to copy */
|
|
H5T_t *new_dt = NULL; /* Pointer to the new datatype */
|
|
hid_t dset_tid = H5I_INVALID_HID; /* Datatype ID from dataset */
|
|
hid_t ret_value = H5I_INVALID_HID; /* Return value */
|
|
|
|
FUNC_ENTER_API(H5I_INVALID_HID)
|
|
H5TRACE1("i", "i", obj_id);
|
|
|
|
switch (H5I_get_type(obj_id)) {
|
|
case H5I_DATATYPE:
|
|
/* The argument is a datatype handle */
|
|
if (NULL == (dt = (H5T_t *)H5I_object(obj_id)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "obj_id is not a datatype ID")
|
|
break;
|
|
|
|
case H5I_DATASET: {
|
|
H5VL_object_t * vol_obj; /* Object for obj_id */
|
|
H5VL_dataset_get_args_t vol_cb_args; /* Arguments to VOL callback */
|
|
|
|
/* The argument is a dataset handle */
|
|
if (NULL == (vol_obj = (H5VL_object_t *)H5I_object_verify(obj_id, H5I_DATASET)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "type_id is not a dataset ID")
|
|
|
|
/* Set up VOL callback arguments */
|
|
vol_cb_args.op_type = H5VL_DATASET_GET_TYPE;
|
|
vol_cb_args.args.get_type.type_id = H5I_INVALID_HID;
|
|
|
|
/* Get the datatype from the dataset
|
|
* NOTE: This will have to be closed after we're done with it.
|
|
*/
|
|
if (H5VL_dataset_get(vol_obj, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, H5I_INVALID_HID,
|
|
"unable to get datatype from the dataset")
|
|
dset_tid = vol_cb_args.args.get_type.type_id;
|
|
|
|
/* Unwrap the type ID */
|
|
if (NULL == (dt = (H5T_t *)H5I_object(dset_tid)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, H5I_INVALID_HID,
|
|
"received invalid datatype from the dataset")
|
|
} break;
|
|
|
|
case H5I_UNINIT:
|
|
case H5I_BADID:
|
|
case H5I_FILE:
|
|
case H5I_GROUP:
|
|
case H5I_DATASPACE:
|
|
case H5I_ATTR:
|
|
case H5I_MAP:
|
|
case H5I_VFL:
|
|
case H5I_VOL:
|
|
case H5I_GENPROP_CLS:
|
|
case H5I_GENPROP_LST:
|
|
case H5I_ERROR_CLASS:
|
|
case H5I_ERROR_MSG:
|
|
case H5I_ERROR_STACK:
|
|
case H5I_SPACE_SEL_ITER:
|
|
case H5I_EVENTSET:
|
|
case H5I_NTYPES:
|
|
default:
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a datatype or dataset")
|
|
} /* end switch */
|
|
|
|
/* Copy datatype */
|
|
if (NULL == (new_dt = H5T_copy(dt, H5T_COPY_TRANSIENT)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, "unable to copy");
|
|
|
|
/* Get an ID for the copied datatype */
|
|
if ((ret_value = H5I_register(H5I_DATATYPE, new_dt, TRUE)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register datatype atom")
|
|
|
|
done:
|
|
|
|
/* If we got a type ID from a passed-in dataset, we need to close that */
|
|
if (dset_tid != H5I_INVALID_HID)
|
|
if (H5I_dec_app_ref(dset_tid) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_BADID, FAIL, "problem freeing temporary dataset type ID")
|
|
|
|
/* Close the new datatype on errors */
|
|
if (H5I_INVALID_HID == ret_value)
|
|
if (new_dt && H5T_close_real(new_dt) < 0)
|
|
HDONE_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, H5I_INVALID_HID, "unable to release datatype info")
|
|
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Tcopy() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5Tclose
|
|
*
|
|
* Purpose: Frees a datatype and all associated memory.
|
|
*
|
|
* Return: Non-negative on success/Negative on failure
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Tuesday, December 9, 1997
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5Tclose(hid_t type_id)
|
|
{
|
|
H5T_t *dt; /* Pointer to datatype to close */
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_API(FAIL)
|
|
H5TRACE1("e", "i", type_id);
|
|
|
|
/* Check args */
|
|
if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
|
|
if (H5T_STATE_IMMUTABLE == dt->shared->state)
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "immutable datatype")
|
|
|
|
/* When the reference count reaches zero the resources are freed */
|
|
if (H5I_dec_app_ref(type_id) < 0)
|
|
HGOTO_ERROR(H5E_ID, H5E_BADID, FAIL, "problem freeing id")
|
|
|
|
done:
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Tclose() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5Tclose_async
|
|
*
|
|
* Purpose: Asynchronous version of H5Tclose.
|
|
*
|
|
* Return: Non-negative on success/Negative on failure
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5Tclose_async(const char *app_file, const char *app_func, unsigned app_line, hid_t type_id, hid_t es_id)
|
|
{
|
|
H5T_t * dt; /* Pointer to datatype to close */
|
|
void * token = NULL; /* Request token for async operation */
|
|
void ** token_ptr = H5_REQUEST_NULL; /* Pointer to request token for async operation */
|
|
H5VL_object_t *vol_obj = NULL; /* VOL object of dset_id */
|
|
H5VL_t * connector = NULL; /* VOL connector */
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_API(FAIL)
|
|
H5TRACE5("e", "*s*sIuii", app_file, app_func, app_line, type_id, es_id);
|
|
|
|
/* Check args */
|
|
if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
|
|
if (H5T_STATE_IMMUTABLE == dt->shared->state)
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "immutable datatype")
|
|
|
|
/* Get dataset object's connector */
|
|
if (NULL == (vol_obj = H5VL_vol_object(type_id)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get VOL object for dataset")
|
|
|
|
/* Prepare for possible asynchronous operation */
|
|
if (H5ES_NONE != es_id) {
|
|
/* Increase connector's refcount, so it doesn't get closed if closing
|
|
* the dataset closes the file */
|
|
connector = vol_obj->connector;
|
|
H5VL_conn_inc_rc(connector);
|
|
|
|
/* Point at token for operation to set up */
|
|
token_ptr = &token;
|
|
} /* end if */
|
|
|
|
/* When the reference count reaches zero the resources are freed */
|
|
if (H5I_dec_app_ref_async(type_id, token_ptr) < 0)
|
|
HGOTO_ERROR(H5E_ID, H5E_BADID, FAIL, "problem freeing id")
|
|
|
|
/* If a token was created, add the token to the event set */
|
|
if (NULL != token)
|
|
if (H5ES_insert(es_id, vol_obj->connector, token,
|
|
H5ARG_TRACE5(__func__, "*s*sIuii", app_file, app_func, app_line, type_id, es_id)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "can't insert token into event set")
|
|
|
|
done:
|
|
if (connector && H5VL_conn_dec_rc(connector) < 0)
|
|
HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "can't decrement ref count on connector")
|
|
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Tclose_async() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5Tequal
|
|
*
|
|
* Purpose: Determines if two datatypes are equal.
|
|
*
|
|
* Return: Success: TRUE if equal, FALSE if unequal
|
|
*
|
|
* Failure: Negative
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Wednesday, December 10, 1997
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
htri_t
|
|
H5Tequal(hid_t type1_id, hid_t type2_id)
|
|
{
|
|
const H5T_t *dt1; /* Pointer to first datatype */
|
|
const H5T_t *dt2; /* Pointer to second datatype */
|
|
htri_t ret_value; /* Return value */
|
|
|
|
FUNC_ENTER_API(FAIL)
|
|
H5TRACE2("t", "ii", type1_id, type2_id);
|
|
|
|
/* check args */
|
|
if (NULL == (dt1 = (H5T_t *)H5I_object_verify(type1_id, H5I_DATATYPE)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
|
|
if (NULL == (dt2 = (H5T_t *)H5I_object_verify(type2_id, H5I_DATATYPE)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
|
|
|
|
ret_value = (0 == H5T_cmp(dt1, dt2, FALSE)) ? TRUE : FALSE;
|
|
|
|
done:
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Tequal() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5Tlock
|
|
*
|
|
* Purpose: Locks a type, making it read only and non-destructable.
|
|
* This is normally done by the library for predefined datatypes so
|
|
* the application doesn't inadvertently change or delete a
|
|
* predefined type.
|
|
*
|
|
* Once a datatype 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5Tlock(hid_t type_id)
|
|
{
|
|
H5T_t *dt; /* Datatype to operate on */
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_API(FAIL)
|
|
H5TRACE1("e", "i", type_id);
|
|
|
|
/* Check args */
|
|
if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
|
|
if (H5T_STATE_NAMED == dt->shared->state || H5T_STATE_OPEN == dt->shared->state)
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to lock named datatype")
|
|
|
|
if (H5T_lock(dt, TRUE) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to lock transient datatype")
|
|
|
|
done:
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Tlock() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5Tget_class
|
|
*
|
|
* Purpose: Returns the datatype class identifier for datatype TYPE_ID.
|
|
*
|
|
* Return: Success: One of the non-negative datatype class constants.
|
|
*
|
|
* Failure: H5T_NO_CLASS (Negative)
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Monday, December 8, 1997
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
H5T_class_t
|
|
H5Tget_class(hid_t type_id)
|
|
{
|
|
H5T_t * dt; /* Pointer to datatype */
|
|
H5T_class_t ret_value; /* Return value */
|
|
|
|
FUNC_ENTER_API(H5T_NO_CLASS)
|
|
H5TRACE1("Tt", "i", type_id);
|
|
|
|
/* Check args */
|
|
if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype")
|
|
|
|
/* Set return value */
|
|
ret_value = H5T_get_class(dt, FALSE);
|
|
|
|
done:
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Tget_class() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
H5T_class_t
|
|
H5T_get_class(const H5T_t *dt, htri_t internal)
|
|
{
|
|
H5T_class_t ret_value = H5T_NO_CLASS; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI_NOERR
|
|
|
|
HDassert(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;
|
|
}
|
|
|
|
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
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
htri_t
|
|
H5Tdetect_class(hid_t type, H5T_class_t cls)
|
|
{
|
|
H5T_t *dt; /* Datatype to query */
|
|
htri_t ret_value; /* Return value */
|
|
|
|
FUNC_ENTER_API(FAIL)
|
|
H5TRACE2("t", "iTt", type, cls);
|
|
|
|
/* Check args */
|
|
if (NULL == (dt = (H5T_t *)H5I_object_verify(type, H5I_DATATYPE)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype")
|
|
if (!(cls > H5T_NO_CLASS && cls < H5T_NCLASSES))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a datatype class")
|
|
|
|
/* Set return value */
|
|
if ((ret_value = H5T_detect_class(dt, cls, TRUE)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, H5T_NO_CLASS, "can't get datatype class")
|
|
|
|
done:
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Tdetect_class() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
htri_t
|
|
H5T_detect_class(const H5T_t *dt, H5T_class_t cls, hbool_t from_api)
|
|
{
|
|
unsigned i;
|
|
htri_t ret_value = FALSE; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI_NOERR
|
|
|
|
HDassert(dt);
|
|
HDassert(cls > H5T_NO_CLASS && cls < H5T_NCLASSES);
|
|
|
|
/* Consider VL string as a string for API, as a VL for internal use. */
|
|
/* (note that this check must be performed before checking if the VL
|
|
* string belongs to the H5T_VLEN class, which would otherwise return
|
|
* true. -QAK)
|
|
*/
|
|
if (from_api && H5T_IS_VL_STRING(dt->shared))
|
|
HGOTO_DONE(H5T_STRING == cls);
|
|
|
|
/* 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, from_api)) !=
|
|
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, from_api));
|
|
break;
|
|
case H5T_NO_CLASS:
|
|
case H5T_INTEGER:
|
|
case H5T_FLOAT:
|
|
case H5T_TIME:
|
|
case H5T_STRING:
|
|
case H5T_BITFIELD:
|
|
case H5T_OPAQUE:
|
|
case H5T_REFERENCE:
|
|
case H5T_NCLASSES:
|
|
default:
|
|
break;
|
|
} /* end if */
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_detect_class() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
htri_t
|
|
H5Tis_variable_str(hid_t dtype_id)
|
|
{
|
|
H5T_t *dt; /* Datatype to query */
|
|
htri_t ret_value; /* Return value */
|
|
|
|
FUNC_ENTER_API(FAIL)
|
|
H5TRACE1("t", "i", dtype_id);
|
|
|
|
/* Check args */
|
|
if (NULL == (dt = (H5T_t *)H5I_object_verify(dtype_id, H5I_DATATYPE)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
|
|
|
|
/* Set return value */
|
|
if ((ret_value = H5T_is_variable_str(dt)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "can't determine if datatype is VL-string")
|
|
|
|
done:
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Tis_variable_str() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_is_variable_str
|
|
*
|
|
* Purpose: Check whether a datatype is a variable-length string
|
|
*
|
|
* Return: TRUE (1) or FALSE (0) on success/Negative on failure
|
|
*
|
|
* Programmer: Quincey Koziol
|
|
* October 17, 2007
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
htri_t
|
|
H5T_is_variable_str(const H5T_t *dt)
|
|
{
|
|
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
|
|
|
FUNC_LEAVE_NOAPI(H5T_IS_VL_STRING(dt->shared))
|
|
} /* end H5T_is_variable_str() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
size_t
|
|
H5Tget_size(hid_t type_id)
|
|
{
|
|
H5T_t *dt; /* Datatype to query */
|
|
size_t ret_value; /* Return value */
|
|
|
|
FUNC_ENTER_API(0)
|
|
H5TRACE1("z", "i", type_id);
|
|
|
|
/* Check args */
|
|
if (NULL == (dt = (H5T_t *)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 datatypes have a positive size.
|
|
*
|
|
* Return: Non-negative on success/Negative on failure
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Wednesday, January 7, 1998
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5Tset_size(hid_t type_id, size_t size)
|
|
{
|
|
H5T_t *dt; /* Datatype to modify */
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_API(FAIL)
|
|
H5TRACE2("e", "iz", type_id, size);
|
|
|
|
/* Check args */
|
|
if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
|
|
if (H5T_STATE_TRANSIENT != dt->shared->state)
|
|
HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "datatype is read-only")
|
|
if (size <= 0 && size != H5T_VARIABLE)
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "size must be positive")
|
|
if (size == H5T_VARIABLE && !H5T_IS_STRING(dt->shared))
|
|
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")
|
|
|
|
/* Modify the datatype */
|
|
if (H5T__set_size(dt, size) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set size for datatype")
|
|
|
|
done:
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Tset_size() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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 datatype.
|
|
*
|
|
* Failure: negative
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Wednesday, December 23, 1998
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
hid_t
|
|
H5Tget_super(hid_t type)
|
|
{
|
|
H5T_t *dt; /* Datatype to query */
|
|
H5T_t *super = NULL; /* Supertype */
|
|
hid_t ret_value = H5I_INVALID_HID; /* Return value */
|
|
|
|
FUNC_ENTER_API(H5I_INVALID_HID)
|
|
H5TRACE1("i", "i", type);
|
|
|
|
if (NULL == (dt = (H5T_t *)H5I_object_verify(type, H5I_DATATYPE)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a datatype")
|
|
if (NULL == (super = H5T_get_super(dt)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, "not a datatype")
|
|
if ((ret_value = H5I_register(H5I_DATATYPE, super, TRUE)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register parent datatype")
|
|
|
|
done:
|
|
if (H5I_INVALID_HID == ret_value)
|
|
if (super && H5T_close_real(super) < 0)
|
|
HDONE_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, H5I_INVALID_HID,
|
|
"unable to release super datatype info")
|
|
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Tget_super() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
H5T_t *
|
|
H5T_get_super(const H5T_t *dt)
|
|
{
|
|
H5T_t *ret_value = NULL;
|
|
|
|
FUNC_ENTER_NOAPI(NULL)
|
|
|
|
HDassert(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)
|
|
} /* end H5T_get_super() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T__register_int
|
|
*
|
|
* Purpose: Register a library internal datatype conversion routine.
|
|
*
|
|
* Return: Non-negative on success/Negative on failure
|
|
*
|
|
* Programmer: Quincey Koziol
|
|
* Wednesday, March 7, 1998
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
H5T__register_int(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_lib_conv_t func)
|
|
{
|
|
H5T_conv_func_t conv_func; /* Conversion function wrapper */
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_STATIC
|
|
|
|
/* Check args */
|
|
HDassert(H5T_PERS_HARD == pers || H5T_PERS_SOFT == pers);
|
|
HDassert(name && *name);
|
|
HDassert(src);
|
|
HDassert(dst);
|
|
HDassert(func);
|
|
|
|
/* Set up conversion function wrapper */
|
|
conv_func.is_app = FALSE;
|
|
conv_func.u.lib_func = func;
|
|
|
|
/* Register conversion */
|
|
if (H5T__register(pers, name, src, dst, &conv_func) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,
|
|
"unable to register internal datatype conversion routine")
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T__register_int() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
H5T__register(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_conv_func_t *conv)
|
|
{
|
|
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_STATIC
|
|
|
|
/* Check args */
|
|
HDassert(src);
|
|
HDassert(dst);
|
|
HDassert(conv);
|
|
HDassert(H5T_PERS_HARD == pers || H5T_PERS_SOFT == pers);
|
|
HDassert(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_real(src, dst, name, conv)))
|
|
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 if */
|
|
} /* end if */
|
|
else {
|
|
/* Add function to end of soft list */
|
|
if ((size_t)H5T_g.nsoft >= H5T_g.asoft) {
|
|
size_t na = MAX(32, 2 * H5T_g.asoft);
|
|
H5T_soft_t *x;
|
|
|
|
if (NULL == (x = (H5T_soft_t *)H5MM_realloc(H5T_g.soft, na * sizeof(H5T_soft_t))))
|
|
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
|
|
H5T_g.asoft = 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].conv = *conv;
|
|
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];
|
|
HDassert(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), FALSE)) < 0 ||
|
|
(tmp_did = H5I_register(H5I_DATATYPE, H5T_copy(old_path->dst, H5T_COPY_ALL), FALSE)) < 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 (conv->is_app) {
|
|
if ((conv->u.app_func)(tmp_sid, tmp_did, &cdata, (size_t)0, (size_t)0, (size_t)0, NULL, NULL,
|
|
H5CX_get_dxpl()) < 0) {
|
|
H5I_dec_ref(tmp_sid);
|
|
H5I_dec_ref(tmp_did);
|
|
tmp_sid = tmp_did = -1;
|
|
H5E_clear_stack(NULL);
|
|
continue;
|
|
} /* end if */
|
|
} /* end if */
|
|
else if ((conv->u.lib_func)(tmp_sid, tmp_did, &cdata, (size_t)0, (size_t)0, (size_t)0, NULL,
|
|
NULL) < 0) {
|
|
H5I_dec_ref(tmp_sid);
|
|
H5I_dec_ref(tmp_did);
|
|
tmp_sid = tmp_did = -1;
|
|
H5E_clear_stack(NULL);
|
|
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->conv = *conv;
|
|
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->conv.is_app) {
|
|
if ((old_path->conv.u.app_func)(tmp_sid, tmp_did, &(old_path->cdata), (size_t)0, (size_t)0,
|
|
(size_t)0, NULL, NULL, H5CX_get_dxpl()) < 0) {
|
|
#ifdef H5T_DEBUG
|
|
if (H5DEBUG(T))
|
|
HDfprintf(H5DEBUG(T),
|
|
"H5T: conversion function 0x%08lx "
|
|
"failed to free private data for %s (ignored)\n",
|
|
(unsigned long)(old_path->conv.u.app_func), old_path->name);
|
|
#endif
|
|
} /* end if */
|
|
} /* end if */
|
|
else if ((old_path->conv.u.lib_func)(tmp_sid, tmp_did, &(old_path->cdata), (size_t)0, (size_t)0,
|
|
(size_t)0, NULL, NULL) < 0) {
|
|
#ifdef H5T_DEBUG
|
|
if (H5DEBUG(T))
|
|
HDfprintf(H5DEBUG(T),
|
|
"H5T: conversion function 0x%08lx "
|
|
"failed to free private data for %s (ignored)\n",
|
|
(unsigned long)(old_path->conv.u.lib_func), old_path->name);
|
|
#endif
|
|
} /* end if */
|
|
(void)H5T_close_real(old_path->src);
|
|
(void)H5T_close_real(old_path->dst);
|
|
old_path = 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_stack(NULL);
|
|
} /* end for */
|
|
} /* end else */
|
|
|
|
done:
|
|
if (ret_value < 0) {
|
|
if (new_path) {
|
|
if (new_path->src)
|
|
(void)H5T_close_real(new_path->src);
|
|
if (new_path->dst)
|
|
(void)H5T_close_real(new_path->dst);
|
|
new_path = 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
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 */
|
|
H5T_conv_func_t conv_func; /* Conversion function wrapper */
|
|
herr_t ret_value = SUCCEED; /*return value */
|
|
|
|
FUNC_ENTER_API(FAIL)
|
|
H5TRACE5("e", "Te*siiTC", 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 = (H5T_t *)H5I_object_verify(src_id, H5I_DATATYPE)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type")
|
|
if (NULL == (dst = (H5T_t *)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")
|
|
|
|
/* Set up conversion function wrapper */
|
|
conv_func.is_app = TRUE;
|
|
conv_func.u.app_func = func;
|
|
|
|
/* Go register the function */
|
|
if (H5T__register(pers, name, src, dst, &conv_func) < 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
H5T__unregister(H5T_pers_t pers, const char *name, H5T_t *src, H5T_t *dst, H5T_conv_t func)
|
|
{
|
|
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 */
|
|
|
|
FUNC_ENTER_STATIC_NOERR
|
|
|
|
/* 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;
|
|
HDassert(soft);
|
|
if (name && *name && HDstrcmp(name, soft->name) != 0)
|
|
continue;
|
|
if (src && src->shared->type != soft->src)
|
|
continue;
|
|
if (dst && dst->shared->type != soft->dst)
|
|
continue;
|
|
if (func && func != soft->conv.u.app_func)
|
|
continue;
|
|
|
|
HDmemmove(H5T_g.soft + i, H5T_g.soft + i + 1,
|
|
(size_t)(H5T_g.nsoft - (i + 1)) * sizeof(H5T_soft_t));
|
|
--H5T_g.nsoft;
|
|
} /* end for */
|
|
} /* end if */
|
|
|
|
/* Remove matching conversion paths, except no-op path */
|
|
for (i = H5T_g.npaths - 1; i > 0; --i) {
|
|
path = H5T_g.path[i];
|
|
HDassert(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) != 0) || (src && H5T_cmp(src, path->src, FALSE)) ||
|
|
(dst && H5T_cmp(dst, path->dst, FALSE)) || (func && func != path->conv.u.app_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,
|
|
(size_t)(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->conv.is_app) {
|
|
if ((path->conv.u.app_func)((hid_t)FAIL, (hid_t)FAIL, &(path->cdata), (size_t)0, (size_t)0,
|
|
(size_t)0, NULL, NULL, H5CX_get_dxpl()) < 0) {
|
|
#ifdef H5T_DEBUG
|
|
if (H5DEBUG(T))
|
|
HDfprintf(H5DEBUG(T),
|
|
"H5T: conversion function 0x%08lx failed "
|
|
"to free private data for %s (ignored)\n",
|
|
(unsigned long)(path->conv.u.app_func), path->name);
|
|
#endif
|
|
} /* end if */
|
|
} /* end if */
|
|
else if ((path->conv.u.lib_func)((hid_t)FAIL, (hid_t)FAIL, &(path->cdata), (size_t)0, (size_t)0,
|
|
(size_t)0, NULL, NULL) < 0) {
|
|
#ifdef H5T_DEBUG
|
|
if (H5DEBUG(T))
|
|
HDfprintf(H5DEBUG(T),
|
|
"H5T: conversion function 0x%08lx failed "
|
|
"to free private data for %s (ignored)\n",
|
|
(unsigned long)(path->conv.u.lib_func), path->name);
|
|
#endif
|
|
} /* end if */
|
|
(void)H5T_close_real(path->src);
|
|
(void)H5T_close_real(path->dst);
|
|
path = H5FL_FREE(H5T_path_t, path);
|
|
H5E_clear_stack(NULL); /*ignore all shutdown errors*/
|
|
} /* end else */
|
|
} /* end for */
|
|
|
|
FUNC_LEAVE_NOAPI(SUCCEED)
|
|
} /* 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
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; /* Datatype descriptors */
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_API(FAIL)
|
|
H5TRACE5("e", "Te*siiTC", pers, name, src_id, dst_id, func);
|
|
|
|
/* Check arguments */
|
|
if (src_id > 0 && (NULL == (src = (H5T_t *)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 = (H5T_t *)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) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDELETE, FAIL, "internal unregister function failed")
|
|
|
|
done:
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Tunregister() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
H5T_conv_t
|
|
H5Tfind(hid_t src_id, hid_t dst_id, H5T_cdata_t **pcdata /*out*/)
|
|
{
|
|
H5T_t * src, *dst;
|
|
H5T_path_t *path;
|
|
H5T_conv_t ret_value; /* Return value */
|
|
|
|
FUNC_ENTER_API(NULL)
|
|
H5TRACE3("TC", "iix", src_id, dst_id, pcdata);
|
|
|
|
/* Check args */
|
|
if (NULL == (src = (H5T_t *)H5I_object_verify(src_id, H5I_DATATYPE)) ||
|
|
NULL == (dst = (H5T_t *)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)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "conversion function not found")
|
|
|
|
if (pcdata)
|
|
*pcdata = &(path->cdata);
|
|
|
|
/* Set return value */
|
|
ret_value = path->conv.u.app_func;
|
|
|
|
done:
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Tfind() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5Tcompiler_conv
|
|
*
|
|
* Purpose: Finds out whether the library's conversion function from
|
|
* type src_id to type dst_id is a compiler (hard) conversion.
|
|
* A hard conversion uses compiler's casting; a soft conversion
|
|
* uses the library's own conversion function.
|
|
*
|
|
* Return: TRUE: hard conversion.
|
|
* FALSE: soft conversion.
|
|
* FAIL: failed.
|
|
*
|
|
* Programmer: Raymond Lu
|
|
* Friday, Sept 2, 2005
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
htri_t
|
|
H5Tcompiler_conv(hid_t src_id, hid_t dst_id)
|
|
{
|
|
H5T_t *src, *dst;
|
|
htri_t ret_value; /* Return value */
|
|
|
|
FUNC_ENTER_API(FAIL)
|
|
H5TRACE2("t", "ii", src_id, dst_id);
|
|
|
|
/* Check args */
|
|
if (NULL == (src = (H5T_t *)H5I_object_verify(src_id, H5I_DATATYPE)) ||
|
|
NULL == (dst = (H5T_t *)H5I_object_verify(dst_id, H5I_DATATYPE)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type")
|
|
|
|
/* Find it */
|
|
if ((ret_value = H5T__compiler_conv(src, dst)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, FAIL, "conversion function not found")
|
|
|
|
done:
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Tcompiler_conv() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
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; /* type conversion info */
|
|
H5T_t * src, *dst; /* unregistered types */
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_API(FAIL)
|
|
H5TRACE6("e", "iiz*x*xi", src_id, dst_id, nelmts, buf, background, dxpl_id);
|
|
|
|
/* Check args */
|
|
if (NULL == (src = (H5T_t *)H5I_object_verify(src_id, H5I_DATATYPE)) ||
|
|
NULL == (dst = (H5T_t *)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")
|
|
|
|
/* Set DXPL for operation */
|
|
H5CX_set_dxpl(dxpl_id);
|
|
|
|
/* Find the conversion function */
|
|
if (NULL == (tpath = H5T_path_find(src, dst)))
|
|
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) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed")
|
|
|
|
done:
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Tconvert() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5Treclaim
|
|
*
|
|
* Purpose: Frees the buffers allocated for storing variable-length data
|
|
* in memory. Only frees the VL data in the selection defined in the
|
|
* dataspace. The dataset transfer property list is required to find the
|
|
* correct allocation/free methods for the VL data in the buffer.
|
|
*
|
|
* Return: Non-negative on success, negative on failure
|
|
*
|
|
* Programmer: Quincey Koziol
|
|
* Thursday, June 10, 1999
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5Treclaim(hid_t type_id, hid_t space_id, hid_t dxpl_id, void *buf)
|
|
{
|
|
H5S_t *space; /* Dataspace for iteration */
|
|
herr_t ret_value; /* Return value */
|
|
|
|
FUNC_ENTER_API(FAIL)
|
|
H5TRACE4("e", "iii*x", type_id, space_id, dxpl_id, buf);
|
|
|
|
/* Check args */
|
|
if (H5I_DATATYPE != H5I_get_type(type_id) || buf == NULL)
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument")
|
|
if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataspace")
|
|
if (!(H5S_has_extent(space)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspace does not have extent set")
|
|
|
|
/* Get the default dataset transfer property list if the user didn't provide one */
|
|
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 xfer parms")
|
|
|
|
/* Set DXPL for operation */
|
|
H5CX_set_dxpl(dxpl_id);
|
|
|
|
/* Call internal routine */
|
|
ret_value = H5T_reclaim(type_id, space, buf);
|
|
|
|
done:
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Treclaim() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5Tencode
|
|
*
|
|
* Purpose: Given an datatype ID, converts the object description into
|
|
* binary in a buffer.
|
|
*
|
|
* Return: Success: non-negative
|
|
*
|
|
* Failure: negative
|
|
*
|
|
* Programmer: Raymond Lu
|
|
* July 14, 2004
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5Tencode(hid_t obj_id, void *buf, size_t *nalloc)
|
|
{
|
|
H5T_t *dtype;
|
|
herr_t ret_value = SUCCEED;
|
|
|
|
FUNC_ENTER_API(FAIL)
|
|
H5TRACE3("e", "i*x*z", obj_id, buf, nalloc);
|
|
|
|
/* Check argument and retrieve object */
|
|
if (NULL == (dtype = (H5T_t *)H5I_object_verify(obj_id, H5I_DATATYPE)))
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
|
|
if (nalloc == NULL)
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL pointer for buffer size")
|
|
|
|
/* Go encode the datatype */
|
|
if (H5T_encode(dtype, (unsigned char *)buf, nalloc) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode datatype")
|
|
|
|
done:
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Tencode() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5Tdecode
|
|
*
|
|
* Purpose: Decode a binary object description and return a new object
|
|
* handle.
|
|
*
|
|
* Return: Success: datatype ID(non-negative)
|
|
*
|
|
* Failure: negative
|
|
*
|
|
* Programmer: Raymond Lu
|
|
* July 14, 2004
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
hid_t
|
|
H5Tdecode(const void *buf)
|
|
{
|
|
H5T_t *dt;
|
|
hid_t ret_value; /* Return value */
|
|
|
|
FUNC_ENTER_API(FAIL)
|
|
H5TRACE1("i", "*x", buf);
|
|
|
|
/* Check args */
|
|
if (buf == NULL)
|
|
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "empty buffer")
|
|
|
|
/* Create datatype by decoding buffer
|
|
* There is no way to get the size of the buffer, so we pass in
|
|
* SIZE_MAX and assume the caller knows what they are doing.
|
|
* Really fixing this will require an H5Tdecode2() call that
|
|
* takes a size parameter.
|
|
*/
|
|
if (NULL == (dt = H5T_decode(SIZE_MAX, (const unsigned char *)buf)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "can't decode object")
|
|
|
|
/* Register the type and return the ID */
|
|
if ((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data type")
|
|
|
|
done:
|
|
FUNC_LEAVE_API(ret_value)
|
|
} /* end H5Tdecode() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* API functions are above; library-private functions are below...
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_encode
|
|
*
|
|
* Purpose: Private function for H5Tencode. Converts an object
|
|
* description into binary in a buffer.
|
|
*
|
|
* Return: Success: non-negative
|
|
*
|
|
* Failure: negative
|
|
*
|
|
* Programmer: Raymond Lu
|
|
* July 14, 2004
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5T_encode(H5T_t *obj, unsigned char *buf, size_t *nalloc)
|
|
{
|
|
size_t buf_size; /* Encoded size of datatype */
|
|
H5F_t *f = NULL; /* Fake file structure*/
|
|
herr_t ret_value = SUCCEED;
|
|
|
|
FUNC_ENTER_NOAPI_NOINIT
|
|
|
|
/* Allocate "fake" file structure */
|
|
if (NULL == (f = H5F_fake_alloc((uint8_t)0)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "can't allocate fake file struct")
|
|
|
|
/* Find out the size of buffer needed */
|
|
if ((buf_size = H5O_msg_raw_size(f, H5O_DTYPE_ID, TRUE, obj)) == 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "can't find datatype size")
|
|
|
|
/* Don't encode if buffer size isn't big enough or buffer is empty */
|
|
if (!buf || *nalloc < (buf_size + 1 + 1))
|
|
*nalloc = buf_size + 1 + 1;
|
|
else {
|
|
/* Encode the type of the information */
|
|
*buf++ = H5O_DTYPE_ID;
|
|
|
|
/* Encode the version of the dataspace information */
|
|
*buf++ = H5T_ENCODE_VERSION;
|
|
|
|
/* Encode into user's buffer */
|
|
if (H5O_msg_encode(f, H5O_DTYPE_ID, TRUE, buf, obj) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "can't encode object")
|
|
} /* end else */
|
|
|
|
done:
|
|
/* Release fake file structure */
|
|
if (f && H5F_fake_free(f) < 0)
|
|
HDONE_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to release fake file struct")
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_encode() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_decode
|
|
*
|
|
* Purpose: Private function for H5Tdecode. Reconstructs a binary
|
|
* description of datatype and returns a new object handle.
|
|
*
|
|
* Return: Success: datatype ID(non-negative)
|
|
*
|
|
* Failure: negative
|
|
*
|
|
* Programmer: Raymond Lu
|
|
* July 14, 2004
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
H5T_t *
|
|
H5T_decode(size_t buf_size, const unsigned char *buf)
|
|
{
|
|
H5F_t *f = NULL; /* Fake file structure*/
|
|
H5T_t *ret_value = NULL; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI_NOINIT
|
|
|
|
/* Allocate "fake" file structure */
|
|
if (NULL == (f = H5F_fake_alloc((uint8_t)0)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, NULL, "can't allocate fake file struct")
|
|
|
|
/* Decode the type of the information */
|
|
if (*buf++ != H5O_DTYPE_ID)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_BADMESG, NULL, "not an encoded datatype")
|
|
|
|
/* Decode the version of the datatype information */
|
|
if (*buf++ != H5T_ENCODE_VERSION)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_VERSION, NULL, "unknown version of encoded datatype")
|
|
|
|
/* Decode the serialized datatype message */
|
|
if (NULL == (ret_value = (H5T_t *)H5O_msg_decode(f, NULL, H5O_DTYPE_ID, buf_size, buf)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, NULL, "can't decode object")
|
|
|
|
/* Mark datatype as being in memory now */
|
|
if (H5T_set_loc(ret_value, NULL, H5T_LOC_MEMORY) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location")
|
|
|
|
/* No VOL object */
|
|
ret_value->vol_obj = NULL;
|
|
done:
|
|
/* Release fake file structure */
|
|
if (f && H5F_fake_free(f) < 0)
|
|
HDONE_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, NULL, "unable to release fake file struct")
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_decode() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
H5T_t *
|
|
H5T__create(H5T_class_t type, size_t size)
|
|
{
|
|
H5T_t *dt = NULL;
|
|
H5T_t *ret_value = NULL;
|
|
|
|
FUNC_ENTER_PACKAGE
|
|
|
|
switch (type) {
|
|
case H5T_INTEGER:
|
|
case H5T_FLOAT:
|
|
case H5T_TIME:
|
|
case H5T_STRING: {
|
|
H5T_t *origin_dt = NULL;
|
|
|
|
if (NULL == (origin_dt = (H5T_t *)H5I_object(H5T_C_S1)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, NULL, "can't get structure for string type")
|
|
|
|
/* Copy the default string datatype */
|
|
if (NULL == (dt = H5T_copy(origin_dt, H5T_COPY_TRANSIENT)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy");
|
|
|
|
/* Modify the datatype */
|
|
if (H5T__set_size(dt, size) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to set size for string type")
|
|
} break;
|
|
|
|
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 = FALSE; /* Start out unpacked */
|
|
dt->shared->u.compnd.memb_size = 0;
|
|
} /* end if */
|
|
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: {
|
|
hid_t subtype;
|
|
H5T_t *sub_t_obj;
|
|
|
|
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;
|
|
#if H5_SIZEOF_LONG != H5_SIZEOF_LONG_LONG
|
|
else if (sizeof(long long) == size)
|
|
subtype = H5T_NATIVE_LLONG_g;
|
|
#endif /* H5_SIZEOF_LONG != H5_SIZEOF_LONG_LONG */
|
|
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 == (sub_t_obj = (H5T_t *)H5I_object(subtype)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, NULL, "unable to get datatype object")
|
|
if (NULL == (dt->shared->parent = H5T_copy(sub_t_obj, H5T_COPY_ALL)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "unable to copy base datatype")
|
|
} 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_create2()")
|
|
|
|
case H5T_NO_CLASS:
|
|
case H5T_REFERENCE:
|
|
case H5T_NCLASSES:
|
|
default:
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, NULL, "unknown data type class")
|
|
} /* end switch */
|
|
|
|
/* Set the size except VL string */
|
|
if (H5T_STRING != type || H5T_VARIABLE != size)
|
|
dt->shared->size = size;
|
|
|
|
/* No VOL object */
|
|
dt->vol_obj = NULL;
|
|
|
|
/* Set return value */
|
|
ret_value = dt;
|
|
|
|
done:
|
|
if (NULL == ret_value) {
|
|
if (dt) {
|
|
if (dt->shared->owned_vol_obj && H5VL_free_object(dt->shared->owned_vol_obj) < 0)
|
|
HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close owned VOL object")
|
|
dt->shared = H5FL_FREE(H5T_shared_t, dt->shared);
|
|
dt = H5FL_FREE(H5T_t, dt);
|
|
}
|
|
}
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T__create() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T__initiate_copy
|
|
*
|
|
* Purpose: Allocates datatype structures, copies core fields, and initializes
|
|
* VOL fields.
|
|
*
|
|
* Return: Success: Pointer to a new copy of the OLD_DT argument.
|
|
* Failure: NULL
|
|
*
|
|
* Note: Common code for both H5T_copy and H5T_copy_reopen, as part of
|
|
* the const-correct datatype copying routines.
|
|
*
|
|
* Programmer: David Young
|
|
* January 18, 2020
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static H5T_t *
|
|
H5T__initiate_copy(const H5T_t *old_dt)
|
|
{
|
|
H5T_t *new_dt = NULL; /* Copy of datatype */
|
|
H5T_t *ret_value = NULL; /* Return value */
|
|
|
|
FUNC_ENTER_STATIC
|
|
|
|
/* Allocate space */
|
|
if (NULL == (new_dt = H5FL_MALLOC(H5T_t)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, NULL, "H5T_t memory allocation failed")
|
|
if (NULL == (new_dt->shared = H5FL_MALLOC(H5T_shared_t)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, NULL, "H5T_shared_t memory allocation failed")
|
|
|
|
/* Copy shared information */
|
|
*(new_dt->shared) = *(old_dt->shared);
|
|
|
|
/* Increment ref count on owned VOL object */
|
|
if (new_dt->shared->owned_vol_obj)
|
|
(void)H5VL_object_inc_rc(new_dt->shared->owned_vol_obj);
|
|
|
|
/* Reset vol_obj field */
|
|
new_dt->vol_obj = NULL;
|
|
|
|
/* Set return value */
|
|
ret_value = new_dt;
|
|
|
|
done:
|
|
if (ret_value == NULL)
|
|
if (new_dt) {
|
|
if (new_dt->shared) {
|
|
if (new_dt->shared->owned_vol_obj && H5VL_free_object(new_dt->shared->owned_vol_obj) < 0)
|
|
HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close owned VOL object")
|
|
new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared);
|
|
} /* end if */
|
|
new_dt = H5FL_FREE(H5T_t, new_dt);
|
|
} /* end if */
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T__initiate_copy() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T__copy_transient
|
|
*
|
|
* Purpose: Part of recursive framework for const-correct datatype copying.
|
|
*
|
|
* Return: Success: Pointer to a new copy of the OLD_DT argument.
|
|
* Failure: NULL
|
|
*
|
|
* Programmer: David Young
|
|
* January 18, 2020
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static H5T_t *
|
|
H5T__copy_transient(H5T_t *old_dt)
|
|
{
|
|
H5T_t *ret_value = NULL; /* Return value */
|
|
|
|
FUNC_ENTER_STATIC
|
|
|
|
/* Copy datatype, with correct method */
|
|
if (NULL == (ret_value = H5T_copy(old_dt, H5T_COPY_TRANSIENT)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't make 'transient' copy of datatype")
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T__copy_transient() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T__copy_all
|
|
*
|
|
* Purpose: Part of recursive framework for const-correct datatype copying.
|
|
*
|
|
* Return: Success: Pointer to a new copy of the OLD_DT argument.
|
|
* Failure: NULL
|
|
*
|
|
* Programmer: David Young
|
|
* January 18, 2020
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static H5T_t *
|
|
H5T__copy_all(H5T_t *old_dt)
|
|
{
|
|
H5T_t *ret_value = NULL; /* Return value */
|
|
|
|
FUNC_ENTER_STATIC
|
|
|
|
/* Copy datatype, with correct method */
|
|
if (NULL == (ret_value = H5T_copy(old_dt, H5T_COPY_ALL)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't make 'all' copy of datatype")
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T__copy_transient() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T__complete_copy
|
|
*
|
|
* Purpose: Completes copying datatype fields, as part of the recursive
|
|
* const-correct datatype copy routines.
|
|
*
|
|
* Return: Success: non-negative
|
|
* Failure: negative
|
|
*
|
|
* Note: Common code for both H5T_copy and H5T_copy_reopen.
|
|
*
|
|
* Programmer: David Young
|
|
* January 18, 2020
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
H5T__complete_copy(H5T_t *new_dt, const H5T_t *old_dt, H5T_shared_t *reopened_fo, hbool_t set_memory_type,
|
|
H5T_copy_func_t copyfn)
|
|
{
|
|
H5T_t * tmp = NULL; /* Temporary copy of compound field's datatype */
|
|
char * s; /* Temporary copy of compound field name / enum value name */
|
|
unsigned i; /* Local index variable */
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_STATIC
|
|
|
|
/* Update fields in the new struct, if we aren't sharing an already opened
|
|
* committed datatype */
|
|
if (!reopened_fo) {
|
|
/* Copy parent information */
|
|
if (old_dt->shared->parent)
|
|
if (NULL == (new_dt->shared->parent = (*copyfn)(old_dt->shared->parent)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy datatype's parent type")
|
|
|
|
switch (new_dt->shared->type) {
|
|
case H5T_COMPOUND: {
|
|
ssize_t 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.
|
|
*/
|
|
/* Only malloc if space has been allocated for members - NAF */
|
|
if (new_dt->shared->u.compnd.nalloc > 0) {
|
|
if (NULL == (new_dt->shared->u.compnd.memb =
|
|
H5MM_malloc(new_dt->shared->u.compnd.nalloc * sizeof(H5T_cmemb_t))))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "memory allocation failed")
|
|
|
|
H5MM_memcpy(new_dt->shared->u.compnd.memb, old_dt->shared->u.compnd.memb,
|
|
new_dt->shared->u.compnd.nmembs * sizeof(H5T_cmemb_t));
|
|
} /* end if */
|
|
|
|
for (i = 0; i < new_dt->shared->u.compnd.nmembs; i++) {
|
|
unsigned j;
|
|
int old_match;
|
|
|
|
if (NULL == (s = H5MM_xstrdup(new_dt->shared->u.compnd.memb[i].name)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL,
|
|
"can't copy string for compound field's name")
|
|
new_dt->shared->u.compnd.memb[i].name = s;
|
|
if (NULL == (tmp = (*copyfn)(old_dt->shared->u.compnd.memb[i].type)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy compound field's datatype")
|
|
new_dt->shared->u.compnd.memb[i].type = tmp;
|
|
HDassert(tmp != NULL);
|
|
|
|
/* Range check against compound member's offset */
|
|
if ((accum_change < 0) &&
|
|
((ssize_t)new_dt->shared->u.compnd.memb[i].offset < accum_change))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "invalid field size in datatype")
|
|
|
|
/* Apply the accumulated size change to the offset of the field */
|
|
new_dt->shared->u.compnd.memb[i].offset += (size_t)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 = (int)j;
|
|
break;
|
|
} /* end if */
|
|
} /* end for */
|
|
|
|
/* check if we couldn't find a match */
|
|
if (old_match < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "fields in datatype corrupted")
|
|
} /* end if */
|
|
else
|
|
old_match = (int)i;
|
|
|
|
/* 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 +=
|
|
(ssize_t)(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 */
|
|
|
|
/* Range check against datatype size */
|
|
if ((accum_change < 0) && ((ssize_t)new_dt->shared->size < accum_change))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "invalid field size in datatype")
|
|
|
|
/* Apply the accumulated size change to the size of the compound struct */
|
|
new_dt->shared->size += (size_t)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.
|
|
*/
|
|
if (NULL == (new_dt->shared->u.enumer.name =
|
|
H5MM_malloc(new_dt->shared->u.enumer.nalloc * sizeof(char *))))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "enam name array memory allocation failed")
|
|
if (NULL == (new_dt->shared->u.enumer.value =
|
|
H5MM_malloc(new_dt->shared->u.enumer.nalloc * new_dt->shared->size)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL,
|
|
"enam value array memory allocation failed")
|
|
H5MM_memcpy(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++) {
|
|
if (NULL == (s = H5MM_xstrdup(old_dt->shared->u.enumer.name[i])))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL,
|
|
"can't copy string for enum value's name")
|
|
new_dt->shared->u.enumer.name[i] = s;
|
|
} /* end for */
|
|
break;
|
|
|
|
case H5T_VLEN:
|
|
case H5T_REFERENCE:
|
|
if (set_memory_type)
|
|
/* H5T_copy converts any type into a memory type */
|
|
if (H5T_set_loc(new_dt, NULL, H5T_LOC_MEMORY) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
|
|
break;
|
|
|
|
case H5T_OPAQUE:
|
|
/*
|
|
* Copy the tag name.
|
|
*/
|
|
new_dt->shared->u.opaque.tag = H5MM_xstrdup(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;
|
|
|
|
case H5T_NO_CLASS:
|
|
case H5T_INTEGER:
|
|
case H5T_FLOAT:
|
|
case H5T_TIME:
|
|
case H5T_STRING:
|
|
case H5T_BITFIELD:
|
|
case H5T_NCLASSES:
|
|
default:
|
|
break;
|
|
} /* end switch */
|
|
} /* end if */
|
|
|
|
/* Set the cached location & name path if the original type was a named
|
|
* type and the new type is also named.
|
|
*/
|
|
if (H5O_loc_reset(&new_dt->oloc) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, FAIL, "unable to initialize location")
|
|
if (H5G_name_reset(&new_dt->path) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to reset path")
|
|
|
|
if (new_dt->shared->state == H5T_STATE_NAMED || new_dt->shared->state == H5T_STATE_OPEN) {
|
|
if (H5O_loc_copy_deep(&(new_dt->oloc), &(old_dt->oloc)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy object location")
|
|
if (H5G_name_copy(&(new_dt->path), &(old_dt->path), H5_COPY_DEEP) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to copy path")
|
|
} /* end if */
|
|
|
|
/* Copy shared location information if the new type is named or if it is
|
|
* shared in the heap.
|
|
*/
|
|
if ((old_dt->sh_loc.type == H5O_SHARE_TYPE_SOHM || old_dt->sh_loc.type == H5O_SHARE_TYPE_HERE) ||
|
|
new_dt->shared->state == H5T_STATE_NAMED || new_dt->shared->state == H5T_STATE_OPEN) {
|
|
if (H5O_set_shared(&(new_dt->sh_loc), &(old_dt->sh_loc)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy shared information")
|
|
} /* end if */
|
|
else
|
|
/* Reset shared component info */
|
|
H5O_msg_reset_share(H5O_DTYPE_ID, new_dt);
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T__complete_copy() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
H5T_t *
|
|
H5T_copy(const H5T_t *old_dt, H5T_copy_t method)
|
|
{
|
|
H5T_t * new_dt = NULL; /* New datatype */
|
|
H5T_copy_func_t copyfn; /* Pointer to correct copy routine */
|
|
H5T_t * ret_value = NULL; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI(NULL)
|
|
|
|
/* check args */
|
|
HDassert(old_dt);
|
|
|
|
/* Allocate and copy core datatype information */
|
|
if (NULL == (new_dt = H5T__initiate_copy(old_dt)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy core datatype info")
|
|
|
|
/* 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;
|
|
copyfn = H5T__copy_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;
|
|
copyfn = H5T__copy_all;
|
|
break;
|
|
|
|
default:
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, NULL, "invalid copy method type")
|
|
} /* end switch */
|
|
|
|
/* Finish making the copy of the datatype */
|
|
if (H5T__complete_copy(new_dt, old_dt, NULL, (method == H5T_COPY_TRANSIENT), copyfn) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "can't complete datatype initialization")
|
|
|
|
/* Set return value */
|
|
ret_value = new_dt;
|
|
|
|
done:
|
|
if (ret_value == NULL)
|
|
if (new_dt) {
|
|
HDassert(new_dt->shared);
|
|
if (new_dt->shared->owned_vol_obj && H5VL_free_object(new_dt->shared->owned_vol_obj) < 0)
|
|
HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close owned VOL object")
|
|
new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared);
|
|
new_dt = H5FL_FREE(H5T_t, new_dt);
|
|
} /* end if */
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_copy() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_copy_reopen
|
|
*
|
|
* Purpose: Copy a datatype, possibly reopening a named datatype, as part
|
|
* the const-correct datatype copying routines.
|
|
*
|
|
* Return: Success: Pointer to a new copy of the OLD_DT argument.
|
|
* Failure: NULL
|
|
*
|
|
* Programmer: David Young
|
|
* January 18, 2020
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
H5T_t *
|
|
H5T_copy_reopen(H5T_t *old_dt)
|
|
{
|
|
H5T_t * new_dt = NULL; /* New datatype */
|
|
H5T_shared_t *reopened_fo = NULL; /* Pointer to reopened existing named datatype */
|
|
H5T_t * ret_value = NULL; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI(NULL)
|
|
|
|
/* check args */
|
|
HDassert(old_dt);
|
|
|
|
/* Allocate and copy core datatype information */
|
|
if (NULL == (new_dt = H5T__initiate_copy(old_dt)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy core datatype info")
|
|
|
|
/*
|
|
* Return a transient type (locked or unlocked) or an opened named
|
|
* type. Immutable transient types are degraded to read-only.
|
|
*/
|
|
if (old_dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED) {
|
|
/* Check if the object is already open */
|
|
if (NULL ==
|
|
(reopened_fo = (H5T_shared_t *)H5FO_opened(old_dt->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr))) {
|
|
/* Clear any errors from H5FO_opened() */
|
|
H5E_clear_stack(NULL);
|
|
|
|
/* Open named datatype again */
|
|
if (H5O_open(&old_dt->oloc) < 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->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr, new_dt->shared, FALSE) < 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->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count")
|
|
|
|
new_dt->shared->fo_count = 1;
|
|
} /* end if */
|
|
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. */
|
|
if (new_dt->shared->owned_vol_obj && H5VL_free_object(new_dt->shared->owned_vol_obj) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close owned VOL object")
|
|
new_dt->shared = 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->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) == 0) {
|
|
/* Open the object through this top file */
|
|
if (H5O_open(&old_dt->oloc) < 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->sh_loc.file, old_dt->sh_loc.u.loc.oh_addr) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count")
|
|
} /* end else */
|
|
|
|
/* Set state for new datatype */
|
|
new_dt->shared->state = H5T_STATE_OPEN;
|
|
} /* end if */
|
|
else
|
|
/* Downgrade immutable datatypes to read-only */
|
|
if (H5T_STATE_IMMUTABLE == old_dt->shared->state)
|
|
new_dt->shared->state = H5T_STATE_RDONLY;
|
|
|
|
/* Finish making the copy of the datatype */
|
|
if (H5T__complete_copy(new_dt, old_dt, reopened_fo, TRUE, H5T_copy_reopen) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "can't complete datatype initialization")
|
|
|
|
/* Set return value */
|
|
ret_value = new_dt;
|
|
|
|
done:
|
|
if (ret_value == NULL)
|
|
if (new_dt) {
|
|
HDassert(new_dt->shared);
|
|
if (new_dt->shared->owned_vol_obj && H5VL_free_object(new_dt->shared->owned_vol_obj) < 0)
|
|
HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close owned VOL object")
|
|
new_dt->shared = H5FL_FREE(H5T_shared_t, new_dt->shared);
|
|
new_dt = H5FL_FREE(H5T_t, new_dt);
|
|
} /* end if */
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_copy_reopen() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5T_lock(H5T_t *dt, hbool_t immutable)
|
|
{
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI(FAIL)
|
|
|
|
HDassert(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;
|
|
default:
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "invalid datatype state")
|
|
}
|
|
|
|
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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
H5T_t *
|
|
H5T__alloc(void)
|
|
{
|
|
H5T_t *dt = NULL; /* Pointer to datatype allocated */
|
|
H5T_t *ret_value = NULL; /* Return value */
|
|
|
|
FUNC_ENTER_PACKAGE
|
|
|
|
/* Allocate & initialize datatype wrapper info */
|
|
if (NULL == (dt = H5FL_CALLOC(H5T_t)))
|
|
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
|
|
H5O_loc_reset(&(dt->oloc));
|
|
H5G_name_reset(&(dt->path));
|
|
H5O_msg_reset_share(H5O_DTYPE_ID, dt);
|
|
|
|
/* Allocate & initialize shared datatype structure */
|
|
if (NULL == (dt->shared = H5FL_CALLOC(H5T_shared_t)))
|
|
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
|
|
dt->shared->version = H5O_DTYPE_VERSION_1;
|
|
|
|
/* No VOL object initially */
|
|
dt->vol_obj = NULL;
|
|
|
|
/* Assign return value */
|
|
ret_value = dt;
|
|
|
|
done:
|
|
if (ret_value == NULL)
|
|
if (dt) {
|
|
if (dt->shared) {
|
|
HDassert(!dt->shared->owned_vol_obj);
|
|
dt->shared = H5FL_FREE(H5T_shared_t, dt->shared);
|
|
} /* end if */
|
|
dt = H5FL_FREE(H5T_t, dt);
|
|
} /* 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 / H5T_close_real).
|
|
*
|
|
* 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_PACKAGE
|
|
|
|
HDassert(dt && dt->shared);
|
|
|
|
/* Free the ID to name info */
|
|
H5G_name_free(&(dt->path));
|
|
|
|
/* 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++) {
|
|
dt->shared->u.compnd.memb[i].name = (char *)H5MM_xfree(dt->shared->u.compnd.memb[i].name);
|
|
(void)H5T_close_real(dt->shared->u.compnd.memb[i].type);
|
|
}
|
|
dt->shared->u.compnd.memb = (H5T_cmemb_t *)H5MM_xfree(dt->shared->u.compnd.memb);
|
|
dt->shared->u.compnd.nmembs = 0;
|
|
break;
|
|
|
|
case H5T_ENUM:
|
|
for (i = 0; i < dt->shared->u.enumer.nmembs; i++)
|
|
dt->shared->u.enumer.name[i] = (char *)H5MM_xfree(dt->shared->u.enumer.name[i]);
|
|
dt->shared->u.enumer.name = (char **)H5MM_xfree(dt->shared->u.enumer.name);
|
|
dt->shared->u.enumer.value = (uint8_t *)H5MM_xfree(dt->shared->u.enumer.value);
|
|
dt->shared->u.enumer.nmembs = 0;
|
|
break;
|
|
|
|
case H5T_OPAQUE:
|
|
dt->shared->u.opaque.tag = (char *)H5MM_xfree(dt->shared->u.opaque.tag);
|
|
break;
|
|
|
|
case H5T_NO_CLASS:
|
|
case H5T_INTEGER:
|
|
case H5T_FLOAT:
|
|
case H5T_TIME:
|
|
case H5T_STRING:
|
|
case H5T_BITFIELD:
|
|
case H5T_REFERENCE:
|
|
case H5T_VLEN:
|
|
case H5T_ARRAY:
|
|
case H5T_NCLASSES:
|
|
default:
|
|
break;
|
|
} /* end switch */
|
|
dt->shared->type = H5T_NO_CLASS;
|
|
|
|
/* Close the parent */
|
|
HDassert(dt->shared->parent != dt);
|
|
if (dt->shared->parent && H5T_close_real(dt->shared->parent) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close parent data type")
|
|
dt->shared->parent = NULL;
|
|
|
|
/* Close the owned VOL object */
|
|
if (dt->shared->owned_vol_obj && H5VL_free_object(dt->shared->owned_vol_obj) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close owned VOL object")
|
|
dt->shared->owned_vol_obj = NULL;
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T__free() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_close_real
|
|
*
|
|
* Purpose: Frees a datatype and all associated memory.
|
|
*
|
|
* Note: Does _not_ deal with open named datatypes, etc. so this
|
|
* should never see a type managed by a VOL connector.
|
|
*
|
|
* Return: Non-negative on success/Negative on failure
|
|
*
|
|
* Programmer: Quincey Koziol
|
|
* Monday, February 12, 2018
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5T_close_real(H5T_t *dt)
|
|
{
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI(FAIL)
|
|
|
|
/* Sanity check */
|
|
HDassert(dt && dt->shared);
|
|
|
|
/* Clean up resources, depending on shared state */
|
|
if (dt->shared->state != H5T_STATE_OPEN) {
|
|
if (H5T__free(dt) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free datatype");
|
|
|
|
HDassert(!dt->shared->owned_vol_obj);
|
|
dt->shared = H5FL_FREE(H5T_shared_t, dt->shared);
|
|
} /* end if */
|
|
else
|
|
/* Free the group hier. path since we're not calling H5T__free() */
|
|
H5G_name_free(&(dt->path));
|
|
|
|
/* Free the 'top' datatype struct */
|
|
dt = H5FL_FREE(H5T_t, dt);
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_close_real() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_close
|
|
*
|
|
* Purpose: Frees a data type and all associated memory. Deals with
|
|
* open named datatypes appropriately.
|
|
*
|
|
* Return: Non-negative on success/Negative on failure
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Monday, December 8, 1997
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5T_close(H5T_t *dt)
|
|
{
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI(FAIL)
|
|
|
|
/* Sanity check */
|
|
HDassert(dt);
|
|
HDassert(dt->shared);
|
|
|
|
/* Named datatype cleanups */
|
|
if (dt->shared->state == H5T_STATE_OPEN) {
|
|
/* Decrement refcount count on open named datatype */
|
|
dt->shared->fo_count--;
|
|
|
|
/* Sanity checks */
|
|
HDassert(dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED);
|
|
HDassert(H5F_addr_defined(dt->sh_loc.u.loc.oh_addr));
|
|
HDassert(H5F_addr_defined(dt->oloc.addr));
|
|
|
|
/* If a named type is being closed then close the object header and
|
|
* remove from the list of open objects in the file.
|
|
*/
|
|
|
|
/* Decrement the ref. count for this object in the top file */
|
|
if (H5FO_top_decr(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "can't decrement count for object")
|
|
|
|
/* Close things down if this is the last reference to the open named datatype */
|
|
if (0 == dt->shared->fo_count) {
|
|
hbool_t corked; /* Whether the named datatype is corked or not */
|
|
|
|
/* Uncork cache entries with object address tag for named datatype */
|
|
if (H5AC_cork(dt->oloc.file, dt->oloc.addr, H5AC__GET_CORKED, &corked) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to retrieve an object's cork status")
|
|
if (corked)
|
|
if (H5AC_cork(dt->oloc.file, dt->oloc.addr, H5AC__UNCORK, NULL) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTUNCORK, FAIL, "unable to uncork an object")
|
|
|
|
/* Remove the datatype from the list of opened objects in the file */
|
|
if (H5FO_delete(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL,
|
|
"can't remove datatype from list of open objects")
|
|
if (H5O_close(&dt->oloc, NULL) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close data type object header")
|
|
|
|
/* Mark named datatype closed now */
|
|
dt->shared->state = H5T_STATE_NAMED;
|
|
} /* end if */
|
|
else {
|
|
/* Check reference count for this object in the top file */
|
|
if (H5FO_top_count(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr) == 0) {
|
|
/* Close object location for named datatype */
|
|
if (H5O_close(&dt->oloc, NULL) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to close")
|
|
} /* end if */
|
|
else
|
|
/* Free object location (i.e. "unhold" the file if appropriate) */
|
|
if (H5O_loc_free(&(dt->oloc)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "problem attempting to free location")
|
|
} /* end else */
|
|
} /* end if */
|
|
|
|
/* Clean up resources */
|
|
if (H5T_close_real(dt) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, FAIL, "unable to free datatype");
|
|
|
|
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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
H5T__set_size(H5T_t *dt, size_t size)
|
|
{
|
|
size_t prec, offset;
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_STATIC
|
|
|
|
/* Check args */
|
|
HDassert(dt);
|
|
HDassert(dt->shared);
|
|
HDassert(size != 0);
|
|
HDassert(H5T_REFERENCE != dt->shared->type);
|
|
HDassert(!(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 = 0;
|
|
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");
|
|
|
|
if (num_membs) {
|
|
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;
|
|
} /* end if */
|
|
} /* end for */
|
|
|
|
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 ");
|
|
} /* end if */
|
|
|
|
/* Compound must not have been packed previously */
|
|
/* We will check if resizing changed the packed state of
|
|
* this type at the end of this function */
|
|
HDassert(!dt->shared->u.compnd.packed);
|
|
} /* end if */
|
|
|
|
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 = (H5T_t *)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_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location");
|
|
} /* end if */
|
|
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:
|
|
case H5T_REFERENCE:
|
|
HDassert("can't happen" && 0);
|
|
break;
|
|
|
|
case H5T_NO_CLASS:
|
|
case H5T_NCLASSES:
|
|
HDassert("invalid type" && 0);
|
|
break;
|
|
|
|
default:
|
|
HDassert("not implemented yet" && 0);
|
|
break;
|
|
} /* end switch */
|
|
|
|
/* 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 */
|
|
|
|
/* Check if the new compound type is packed */
|
|
if (dt->shared->type == H5T_COMPOUND)
|
|
H5T__update_packed(dt);
|
|
} /* end else */
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T__set_size() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
size_t
|
|
H5T_get_size(const H5T_t *dt)
|
|
{
|
|
/* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
|
|
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
|
|
|
/* check args */
|
|
HDassert(dt);
|
|
HDassert(dt->shared);
|
|
|
|
FUNC_LEAVE_NOAPI(dt->shared->size)
|
|
} /* end H5T_get_size() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_get_force_conv
|
|
*
|
|
* Purpose: Determines if the type has forced conversion. This will be
|
|
* true if and only if the type keeps a pointer to a file VOL
|
|
* object internally.
|
|
*
|
|
* Return: TRUE/FALSE (never fails)
|
|
*
|
|
* Programmer: Neil Fortner
|
|
* Thursday, January 21, 2021
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
hbool_t
|
|
H5T_get_force_conv(const H5T_t *dt)
|
|
{
|
|
/* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
|
|
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
|
|
|
/* check args */
|
|
HDassert(dt);
|
|
HDassert(dt->shared);
|
|
|
|
FUNC_LEAVE_NOAPI(dt->shared->force_conv)
|
|
} /* end H5T_get_force_conv() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
int
|
|
H5T_cmp(const H5T_t *dt1, const H5T_t *dt2, hbool_t superset)
|
|
{
|
|
unsigned *idx1 = NULL, *idx2 = NULL;
|
|
size_t base_size;
|
|
hbool_t swapped;
|
|
unsigned u;
|
|
int tmp;
|
|
int ret_value = 0;
|
|
|
|
FUNC_ENTER_NOAPI(0)
|
|
|
|
/* Sanity check */
|
|
HDassert(dt1);
|
|
HDassert(dt2);
|
|
|
|
/* the easy case */
|
|
if (dt1 == dt2)
|
|
HGOTO_DONE(0);
|
|
|
|
HDassert(dt1->shared);
|
|
HDassert(dt2->shared);
|
|
|
|
/* 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);
|
|
} /* end if */
|
|
|
|
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 = (unsigned *)H5MM_malloc(dt1->shared->u.compnd.nmembs * sizeof(unsigned))) ||
|
|
NULL == (idx2 = (unsigned *)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) {
|
|
int i;
|
|
|
|
for (i = (int)dt1->shared->u.compnd.nmembs - 1, swapped = TRUE; swapped && i >= 0; --i) {
|
|
int j;
|
|
|
|
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) {
|
|
unsigned tmp_idx = idx1[j];
|
|
idx1[j] = idx1[j + 1];
|
|
idx1[j + 1] = tmp_idx;
|
|
swapped = TRUE;
|
|
}
|
|
}
|
|
for (i = (int)dt2->shared->u.compnd.nmembs - 1, swapped = TRUE; swapped && i >= 0; --i) {
|
|
int j;
|
|
|
|
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) {
|
|
unsigned tmp_idx = idx2[j];
|
|
idx2[j] = idx2[j + 1];
|
|
idx2[j + 1] = tmp_idx;
|
|
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++) {
|
|
HDassert(HDstrcmp(dt1->shared->u.compnd.memb[idx1[u]].name,
|
|
dt1->shared->u.compnd.memb[idx1[u + 1]].name));
|
|
HDassert(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 = (unsigned *)H5MM_malloc(dt1->shared->u.enumer.nmembs * sizeof(unsigned))) ||
|
|
NULL == (idx2 = (unsigned *)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) {
|
|
int i;
|
|
for (i = (int)dt1->shared->u.enumer.nmembs - 1, swapped = TRUE; swapped && i >= 0; --i) {
|
|
int j;
|
|
|
|
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) {
|
|
unsigned tmp_idx = idx1[j];
|
|
idx1[j] = idx1[j + 1];
|
|
idx1[j + 1] = tmp_idx;
|
|
swapped = TRUE;
|
|
}
|
|
}
|
|
}
|
|
for (u = 0; u < dt2->shared->u.enumer.nmembs; u++)
|
|
idx2[u] = u;
|
|
if (dt2->shared->u.enumer.nmembs > 1) {
|
|
int i;
|
|
|
|
for (i = (int)dt2->shared->u.enumer.nmembs - 1, swapped = TRUE; swapped && i >= 0; --i) {
|
|
int j;
|
|
|
|
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) {
|
|
unsigned tmp_idx = idx2[j];
|
|
idx2[j] = idx2[j + 1];
|
|
idx2[j + 1] = tmp_idx;
|
|
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++) {
|
|
HDassert(
|
|
HDstrcmp(dt1->shared->u.enumer.name[idx1[u]], dt1->shared->u.enumer.name[idx1[u + 1]]));
|
|
HDassert(
|
|
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((uint8_t *)dt1->shared->u.enumer.value + idx1[u] * base_size,
|
|
(uint8_t *)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:
|
|
HDassert(dt1->shared->u.vlen.type > H5T_VLEN_BADTYPE &&
|
|
dt1->shared->u.vlen.type < H5T_VLEN_MAXTYPE);
|
|
HDassert(dt2->shared->u.vlen.type > H5T_VLEN_BADTYPE &&
|
|
dt2->shared->u.vlen.type < H5T_VLEN_MAXTYPE);
|
|
HDassert(dt1->shared->u.vlen.loc >= H5T_LOC_BADLOC && dt1->shared->u.vlen.loc < H5T_LOC_MAXLOC);
|
|
HDassert(dt2->shared->u.vlen.loc >= H5T_LOC_BADLOC && dt2->shared->u.vlen.loc < H5T_LOC_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_LOC_MEMORY && dt2->shared->u.vlen.loc == H5T_LOC_DISK) {
|
|
HGOTO_DONE(-1);
|
|
}
|
|
else if (dt1->shared->u.vlen.loc == H5T_LOC_DISK && dt2->shared->u.vlen.loc == H5T_LOC_MEMORY) {
|
|
HGOTO_DONE(1);
|
|
}
|
|
else if (dt1->shared->u.vlen.loc == H5T_LOC_BADLOC && dt2->shared->u.vlen.loc != H5T_LOC_BADLOC) {
|
|
HGOTO_DONE(1);
|
|
}
|
|
|
|
/* Don't allow VL types in different files to compare as equal */
|
|
if (dt1->shared->u.vlen.file < dt2->shared->u.vlen.file)
|
|
HGOTO_DONE(-1);
|
|
if (dt1->shared->u.vlen.file > dt2->shared->u.vlen.file)
|
|
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 (u = 0; u < dt1->shared->u.array.ndims; u++) {
|
|
if (dt1->shared->u.array.dim[u] < dt2->shared->u.array.dim[u])
|
|
HGOTO_DONE(-1);
|
|
if (dt1->shared->u.array.dim[u] > dt2->shared->u.array.dim[u])
|
|
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;
|
|
|
|
case H5T_NO_CLASS:
|
|
case H5T_INTEGER:
|
|
case H5T_FLOAT:
|
|
case H5T_TIME:
|
|
case H5T_STRING:
|
|
case H5T_BITFIELD:
|
|
case H5T_REFERENCE:
|
|
case H5T_NCLASSES:
|
|
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);
|
|
if (dt1->shared->u.atomic.u.r.loc < dt2->shared->u.atomic.u.r.loc)
|
|
HGOTO_DONE(-1);
|
|
if (dt1->shared->u.atomic.u.r.loc > dt2->shared->u.atomic.u.r.loc)
|
|
HGOTO_DONE(1);
|
|
if (dt1->shared->u.atomic.u.r.file < dt2->shared->u.atomic.u.r.file)
|
|
HGOTO_DONE(-1);
|
|
if (dt1->shared->u.atomic.u.r.file > dt2->shared->u.atomic.u.r.file)
|
|
HGOTO_DONE(1);
|
|
break;
|
|
|
|
case H5T_NO_CLASS:
|
|
case H5T_OPAQUE:
|
|
case H5T_COMPOUND:
|
|
case H5T_ENUM:
|
|
case H5T_VLEN:
|
|
case H5T_ARRAY:
|
|
case H5T_NCLASSES:
|
|
default:
|
|
HDassert("not implemented yet" && 0);
|
|
break;
|
|
}
|
|
break;
|
|
} /* end switch */
|
|
|
|
done:
|
|
if (NULL != idx1)
|
|
H5MM_xfree(idx1);
|
|
if (NULL != idx2)
|
|
H5MM_xfree(idx2);
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_cmp() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_path_find
|
|
*
|
|
* Purpose: Library-internal wrapper to find the path which converts type
|
|
* SRC_ID to type DST_ID.
|
|
*
|
|
* If SRC and DST are both null pointers then the special no-op
|
|
* conversion path is used.
|
|
*
|
|
* 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: Quincey Koziol
|
|
* Monday, March 5, 2018
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
H5T_path_t *
|
|
H5T_path_find(const H5T_t *src, const H5T_t *dst)
|
|
{
|
|
H5T_conv_func_t conv_func; /* Conversion function wrapper */
|
|
H5T_path_t * ret_value = NULL; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI(NULL)
|
|
|
|
/* Sanity check */
|
|
HDassert(src);
|
|
HDassert(src->shared);
|
|
HDassert(dst);
|
|
HDassert(dst->shared);
|
|
|
|
/* Set up conversion function wrapper */
|
|
conv_func.is_app = FALSE;
|
|
conv_func.u.lib_func = NULL;
|
|
|
|
/* Call the internal routine, with additional parameters */
|
|
if (NULL == (ret_value = H5T__path_find_real(src, dst, NULL, &conv_func)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, NULL, "can't find datatype conversion path")
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_path_find() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T__path_find_real
|
|
*
|
|
* 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static H5T_path_t *
|
|
H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_conv_func_t *conv)
|
|
{
|
|
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 */
|
|
hid_t src_id = -1, dst_id = -1; /* src and dst type identifiers */
|
|
int i; /* counter */
|
|
int nprint = 0; /* lines of output printed */
|
|
H5T_path_t *ret_value = NULL; /* Return value */
|
|
|
|
FUNC_ENTER_STATIC
|
|
|
|
/* Sanity check */
|
|
HDassert(src);
|
|
HDassert(src->shared);
|
|
HDassert(dst);
|
|
HDassert(dst->shared);
|
|
|
|
/*
|
|
* Make sure the first entry in the table is the no-op conversion path.
|
|
*/
|
|
if (0 == H5T_g.npaths) {
|
|
if (NULL == (H5T_g.path = (H5T_path_t **)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")
|
|
HDsnprintf(H5T_g.path[0]->name, sizeof(H5T_g.path[0]->name), "no-op");
|
|
H5T_g.path[0]->conv.is_app = FALSE;
|
|
H5T_g.path[0]->conv.u.lib_func = H5T__conv_noop;
|
|
H5T_g.path[0]->cdata.command = H5T_CONV_INIT;
|
|
if (H5T__conv_noop((hid_t)FAIL, (hid_t)FAIL, &(H5T_g.path[0]->cdata), (size_t)0, (size_t)0, (size_t)0,
|
|
NULL, NULL) < 0) {
|
|
#ifdef H5T_DEBUG
|
|
if (H5DEBUG(T))
|
|
HDfprintf(H5DEBUG(T), "H5T: unable to initialize no-op conversion function (ignored)\n");
|
|
#endif
|
|
H5E_clear_stack(NULL); /*ignore the error*/
|
|
} /* end if */
|
|
H5T_g.path[0]->is_noop = TRUE;
|
|
H5T_g.npaths = 1;
|
|
} /* end if */
|
|
|
|
/* 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;
|
|
} /* end if */
|
|
else {
|
|
lt = md = 1;
|
|
rt = H5T_g.npaths;
|
|
cmp = -1;
|
|
|
|
while (cmp && lt < rt) {
|
|
md = (lt + rt) / 2;
|
|
HDassert(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 while */
|
|
} /* end else */
|
|
|
|
/* 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, if the caller is an API function specifying
|
|
* a new hard conversion function, or if the caller is a private function
|
|
* specifying a new hard conversion and the path is a soft conversion, then
|
|
* create a new path and add the new function to the path.
|
|
*/
|
|
if (!table || (table && conv->is_app && conv->u.app_func) ||
|
|
(table && !table->is_hard && !conv->is_app && conv->u.lib_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';
|
|
} /* end if */
|
|
else
|
|
HDsnprintf(path->name, sizeof(path->name), "NONAME");
|
|
if (NULL == (path->src = H5T_copy(src, H5T_COPY_ALL)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy datatype for conversion path")
|
|
if (NULL == (path->dst = H5T_copy(dst, H5T_COPY_ALL)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy datatype for conversion path")
|
|
} /* end if */
|
|
else
|
|
path = table;
|
|
|
|
/* If a hard conversion function is specified and none is defined for the
|
|
* path, or the caller is an API function, or the caller is a private function but
|
|
* the existing path is a soft function, then add the new conversion to the path
|
|
* and initialize its conversion data.
|
|
*/
|
|
if (conv->u.app_func &&
|
|
(!table || (table && conv->is_app) || (table && !table->is_hard && !conv->is_app))) {
|
|
HDassert(path != table);
|
|
HDassert(NULL == path->conv.u.app_func);
|
|
if (path->src && (src_id = H5I_register(H5I_DATATYPE, H5T_copy(path->src, H5T_COPY_ALL), FALSE)) < 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), FALSE)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL,
|
|
"unable to register destination conversion type for query")
|
|
path->cdata.command = H5T_CONV_INIT;
|
|
if (conv->is_app) {
|
|
if ((conv->u.app_func)(src_id, dst_id, &(path->cdata), (size_t)0, (size_t)0, (size_t)0, NULL,
|
|
NULL, H5CX_get_dxpl()) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to initialize conversion function")
|
|
} /* end if */
|
|
else if ((conv->u.lib_func)(src_id, dst_id, &(path->cdata), (size_t)0, (size_t)0, (size_t)0, NULL,
|
|
NULL) < 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->conv = *conv;
|
|
path->is_hard = TRUE;
|
|
} /* end if */
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
HDassert(path->conv.u.app_func || (src && dst));
|
|
for (i = H5T_g.nsoft - 1; i >= 0 && !path->conv.u.app_func; --i) {
|
|
hbool_t path_init_error = FALSE;
|
|
|
|
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), FALSE)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL,
|
|
"unable to register src conversion type for query")
|
|
if ((dst_id = H5I_register(H5I_DATATYPE, H5T_copy(path->dst, H5T_COPY_ALL), FALSE)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL,
|
|
"unable to register dst conversion type for query")
|
|
path->cdata.command = H5T_CONV_INIT;
|
|
if (H5T_g.soft[i].conv.is_app) {
|
|
if ((H5T_g.soft[i].conv.u.app_func)(src_id, dst_id, &(path->cdata), (size_t)0, (size_t)0,
|
|
(size_t)0, NULL, NULL, H5CX_get_dxpl()) < 0) {
|
|
HDmemset(&(path->cdata), 0, sizeof(H5T_cdata_t));
|
|
H5E_clear_stack(NULL); /*ignore the error*/
|
|
path_init_error = TRUE;
|
|
} /* end if */
|
|
} /* end if */
|
|
else if ((H5T_g.soft[i].conv.u.lib_func)(src_id, dst_id, &(path->cdata), (size_t)0, (size_t)0,
|
|
(size_t)0, NULL, NULL) < 0) {
|
|
HDmemset(&(path->cdata), 0, sizeof(H5T_cdata_t));
|
|
H5E_clear_stack(NULL); /*ignore the error*/
|
|
path_init_error = TRUE;
|
|
} /* end if */
|
|
|
|
/* Finish operation, if no error */
|
|
if (!path_init_error) {
|
|
HDstrncpy(path->name, H5T_g.soft[i].name, (size_t)H5T_NAMELEN);
|
|
path->name[H5T_NAMELEN - 1] = '\0';
|
|
path->conv = H5T_g.soft[i].conv;
|
|
path->is_hard = FALSE;
|
|
} /* end else */
|
|
H5I_dec_ref(src_id);
|
|
H5I_dec_ref(dst_id);
|
|
src_id = dst_id = -1;
|
|
} /* end for */
|
|
if (!path->conv.u.app_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;
|
|
HDassert(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 while */
|
|
} /* end if */
|
|
|
|
/* Replace an existing table entry or add a new entry */
|
|
if (table && path != table) {
|
|
HDassert(table == H5T_g.path[md]);
|
|
H5T__print_stats(table, &nprint /*in,out*/);
|
|
table->cdata.command = H5T_CONV_FREE;
|
|
if (table->conv.is_app) {
|
|
if ((table->conv.u.app_func)((hid_t)FAIL, (hid_t)FAIL, &(table->cdata), (size_t)0, (size_t)0,
|
|
(size_t)0, NULL, NULL, H5CX_get_dxpl()) < 0) {
|
|
#ifdef H5T_DEBUG
|
|
if (H5DEBUG(T))
|
|
HDfprintf(H5DEBUG(T), "H5T: conversion function 0x%08lx free failed for %s (ignored)\n",
|
|
(unsigned long)(path->conv.u.app_func), path->name);
|
|
#endif
|
|
H5E_clear_stack(NULL); /*ignore the failure*/
|
|
} /* end if */
|
|
} /* end if */
|
|
else if ((table->conv.u.lib_func)((hid_t)FAIL, (hid_t)FAIL, &(table->cdata), (size_t)0, (size_t)0,
|
|
(size_t)0, NULL, NULL) < 0) {
|
|
#ifdef H5T_DEBUG
|
|
if (H5DEBUG(T))
|
|
HDfprintf(H5DEBUG(T), "H5T: conversion function 0x%08lx free failed for %s (ignored)\n",
|
|
(unsigned long)(path->conv.u.lib_func), path->name);
|
|
#endif
|
|
H5E_clear_stack(NULL); /*ignore the failure*/
|
|
} /* end if */
|
|
if (table->src)
|
|
(void)H5T_close_real(table->src);
|
|
if (table->dst)
|
|
(void)H5T_close_real(table->dst);
|
|
table = H5FL_FREE(H5T_path_t, table);
|
|
table = path;
|
|
H5T_g.path[md] = path;
|
|
} /* end if */
|
|
else if (path != table) {
|
|
HDassert(cmp);
|
|
if ((size_t)H5T_g.npaths >= H5T_g.apaths) {
|
|
size_t na = MAX(128, 2 * H5T_g.apaths);
|
|
H5T_path_t **x;
|
|
|
|
if (NULL == (x = (H5T_path_t **)H5MM_realloc(H5T_g.path, na * sizeof(H5T_path_t *))))
|
|
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
|
|
H5T_g.apaths = na;
|
|
H5T_g.path = x;
|
|
} /* end if */
|
|
if (cmp > 0)
|
|
md++;
|
|
HDmemmove(H5T_g.path + md + 1, H5T_g.path + md, (size_t)(H5T_g.npaths - md) * sizeof(H5T_path_t *));
|
|
H5T_g.npaths++;
|
|
H5T_g.path[md] = path;
|
|
table = path;
|
|
} /* end else-if */
|
|
|
|
/* Set the flag to indicate both source and destination types are compound types
|
|
* for the optimization of data reading (in H5Dio.c).
|
|
* Make sure that path->are_compounds is only TRUE for compound types.
|
|
*/
|
|
path->are_compounds = FALSE;
|
|
if (H5T_COMPOUND == H5T_get_class(src, TRUE) && H5T_COMPOUND == H5T_get_class(dst, TRUE))
|
|
path->are_compounds = TRUE;
|
|
|
|
/* Set return value */
|
|
ret_value = path;
|
|
|
|
done:
|
|
if (!ret_value && path && path != table) {
|
|
if (path->src)
|
|
(void)H5T_close_real(path->src);
|
|
if (path->dst)
|
|
(void)H5T_close_real(path->dst);
|
|
path = H5FL_FREE(H5T_path_t, path);
|
|
} /* end if */
|
|
if (src_id >= 0)
|
|
H5I_dec_ref(src_id);
|
|
if (dst_id >= 0)
|
|
H5I_dec_ref(dst_id);
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T__path_find_real() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
hbool_t
|
|
H5T_path_noop(const H5T_path_t *p)
|
|
{
|
|
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
|
|
|
HDassert(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_compound_subset
|
|
*
|
|
* Purpose: Checks if the source and destination types are both compound.
|
|
* Tells whether whether the source members are a subset of
|
|
* destination, and the order is the same, and no conversion
|
|
* is needed. For example:
|
|
* struct source { struct destination {
|
|
* TYPE1 A; --> TYPE1 A;
|
|
* TYPE2 B; --> TYPE2 B;
|
|
* TYPE3 C; --> TYPE3 C;
|
|
* }; TYPE4 D;
|
|
* TYPE5 E;
|
|
* };
|
|
*
|
|
* Return: A pointer to the subset info struct in p, or NULL if there are
|
|
* no compounds. Points directly into the H5T_path_t structure.
|
|
*
|
|
* Programmer: Raymond Lu
|
|
* 8 June 2007
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
H5T_subset_info_t *
|
|
H5T_path_compound_subset(const H5T_path_t *p)
|
|
{
|
|
H5T_subset_info_t *ret_value = NULL;
|
|
|
|
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
|
|
|
HDassert(p);
|
|
|
|
if (p->are_compounds)
|
|
ret_value = H5T__conv_struct_subset(&(p->cdata));
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_path_compound_subset */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
H5T_bkg_t
|
|
H5T_path_bkg(const H5T_path_t *p)
|
|
{
|
|
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
|
|
|
HDassert(p);
|
|
|
|
FUNC_LEAVE_NOAPI(p->cdata.need_bkg)
|
|
} /* end H5T_path_bkg() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T__compiler_conv
|
|
*
|
|
* Purpose: Private function for H5Tcompiler_conv. Finds out whether the
|
|
* library's conversion function from type SRC to type DST
|
|
* is a hard conversion.
|
|
*
|
|
* Return: TRUE: hard conversion.
|
|
* FALSE: soft conversion.
|
|
* FAIL: function failed.
|
|
*
|
|
* Programmer: Raymond Lu
|
|
* Friday, Sept 2, 2005
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static htri_t
|
|
H5T__compiler_conv(H5T_t *src, H5T_t *dst)
|
|
{
|
|
H5T_path_t *path;
|
|
htri_t ret_value = FAIL; /* Return value */
|
|
|
|
FUNC_ENTER_STATIC
|
|
|
|
/* Find it */
|
|
if (NULL == (path = H5T_path_find(src, dst)))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, FAIL, "conversion function not found")
|
|
|
|
ret_value = (htri_t)path->is_hard;
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T__compiler_conv() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
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)
|
|
{
|
|
#ifdef H5T_DEBUG
|
|
H5_timer_t timer; /* Timer for conversion */
|
|
#endif
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI(FAIL)
|
|
|
|
#ifdef H5T_DEBUG
|
|
if (H5DEBUG(T)) {
|
|
/* Initialize and start timer */
|
|
H5_timer_init(&timer);
|
|
H5_timer_start(&timer);
|
|
} /* end if */
|
|
#endif
|
|
|
|
/* Call the appropriate conversion callback */
|
|
tpath->cdata.command = H5T_CONV_CONV;
|
|
if (tpath->conv.is_app) {
|
|
if ((tpath->conv.u.app_func)(src_id, dst_id, &(tpath->cdata), nelmts, buf_stride, bkg_stride, buf,
|
|
bkg, H5CX_get_dxpl()) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
|
|
} /* end if */
|
|
else if ((tpath->conv.u.lib_func)(src_id, dst_id, &(tpath->cdata), nelmts, buf_stride, bkg_stride, buf,
|
|
bkg) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
|
|
#ifdef H5T_DEBUG
|
|
if (H5DEBUG(T)) {
|
|
/* Stop timer */
|
|
H5_timer_stop(&timer);
|
|
|
|
/* Record elapsed timer info */
|
|
H5_timer_get_times(timer, &tpath->stats.times);
|
|
|
|
/* Increment # of calls and # of elements converted */
|
|
tpath->stats.ncalls++;
|
|
tpath->stats.nelmts += nelmts;
|
|
} /* end if */
|
|
#endif
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_convert() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_oloc
|
|
*
|
|
* Purpose: Returns a pointer to the object location for a named datatype.
|
|
*
|
|
* Return: Success: Ptr directly into named datatype
|
|
* Failure: NULL
|
|
*
|
|
* Programmer: Robb Matzke
|
|
* Friday, June 5, 1998
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
H5O_loc_t *
|
|
H5T_oloc(H5T_t *dt)
|
|
{
|
|
H5O_loc_t *ret_value = NULL;
|
|
|
|
FUNC_ENTER_NOAPI(NULL)
|
|
|
|
HDassert(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 datatype")
|
|
case H5T_STATE_NAMED:
|
|
case H5T_STATE_OPEN:
|
|
HDassert(dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED);
|
|
ret_value = &dt->oloc;
|
|
break;
|
|
default:
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, NULL, "invalid datatype state")
|
|
} /* end switch */
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_oloc() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_nameof
|
|
*
|
|
* Purpose: Returns a pointer to the path for a named datatype.
|
|
*
|
|
* Return: Success: Ptr directly into named datatype
|
|
* Failure: NULL
|
|
*
|
|
* Programmer: Quincey Koziol
|
|
* Monday, September 12, 2005
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
H5G_name_t *
|
|
H5T_nameof(const H5T_t *dt)
|
|
{
|
|
H5G_name_t *ret_value = NULL;
|
|
|
|
FUNC_ENTER_NOAPI(NULL)
|
|
|
|
HDassert(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 datatype")
|
|
case H5T_STATE_NAMED:
|
|
case H5T_STATE_OPEN:
|
|
ret_value = &(dt->path);
|
|
break;
|
|
default:
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, NULL, "invalid datatype state")
|
|
} /* end switch */
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_nameof() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_is_immutable
|
|
*
|
|
* Purpose: Check if a datatype is immutable.
|
|
*
|
|
* Return: TRUE
|
|
*
|
|
* FALSE
|
|
*
|
|
* Programmer: Raymond Lu
|
|
* Friday, Dec 7, 2001
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
htri_t
|
|
H5T_is_immutable(const H5T_t *dt)
|
|
{
|
|
htri_t ret_value = FALSE;
|
|
|
|
FUNC_ENTER_NOAPI_NOERR
|
|
|
|
HDassert(dt);
|
|
|
|
if (dt->shared->state == H5T_STATE_IMMUTABLE)
|
|
ret_value = TRUE;
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_is_named
|
|
*
|
|
* Purpose: Check if a datatype is named/committed.
|
|
*
|
|
* Return: TRUE/FALSE/FAIL
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
htri_t
|
|
H5T_is_named(const H5T_t *dt)
|
|
{
|
|
htri_t ret_value = FALSE;
|
|
|
|
FUNC_ENTER_NOAPI_NOERR
|
|
|
|
HDassert(dt);
|
|
|
|
if (dt->vol_obj)
|
|
ret_value = TRUE;
|
|
else
|
|
ret_value = (H5T_STATE_OPEN == dt->shared->state || H5T_STATE_NAMED == dt->shared->state);
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_convert_committed_datatype
|
|
*
|
|
* Purpose: To convert the committed datatype "dt" to a transient embedded
|
|
* type if the file location associated with the committed datatype is
|
|
* different from the parameter "f".
|
|
* "f" is the file location where the dataset or attribute will be created.
|
|
*
|
|
* Notes: See HDFFV-9940
|
|
*
|
|
* Return: Success: non-negative
|
|
* Failure: negative
|
|
*
|
|
* Programmer: Vailin Choi; June 2016
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5T_convert_committed_datatype(H5T_t *dt, H5F_t *f)
|
|
{
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI(FAIL)
|
|
|
|
HDassert(dt);
|
|
HDassert(f);
|
|
|
|
if (H5T_is_named(dt) && (dt->sh_loc.file != f)) {
|
|
HDassert(dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED);
|
|
|
|
H5O_msg_reset_share(H5O_DTYPE_ID, dt);
|
|
if (H5O_loc_free(&dt->oloc) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTRESET, FAIL, "unable to initialize location")
|
|
if (H5G_name_free(&dt->path) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to reset path")
|
|
|
|
/* If the datatype is committed through the VOL, close it */
|
|
if (NULL != dt->vol_obj) {
|
|
H5VL_object_t *vol_obj = dt->vol_obj;
|
|
|
|
/* Close the datatype through the VOL*/
|
|
if (H5VL_datatype_close(vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to close datatype")
|
|
|
|
/* Free the datatype and set the VOL object pointer to NULL */
|
|
if (H5VL_free_object(vol_obj) < 0)
|
|
HGOTO_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to free VOL object")
|
|
dt->vol_obj = NULL;
|
|
} /* end if */
|
|
|
|
dt->shared->state = H5T_STATE_TRANSIENT;
|
|
} /* end if */
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_convert_committed_datatype() */
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* Function: H5T_get_ref_type
|
|
*
|
|
* Purpose: Retrieves the type of reference for a datatype
|
|
* H5T_t *dt; IN: datatype pointer for the reference datatype
|
|
*
|
|
* Return: Success: A reference type defined in H5Rpublic.h
|
|
* Failure: H5R_BADTYPE
|
|
* Notes: Given a reference datatype object, this function returns the reference type
|
|
* of the datatype.
|
|
*--------------------------------------------------------------------------
|
|
*/
|
|
H5R_type_t
|
|
H5T_get_ref_type(const H5T_t *dt)
|
|
{
|
|
H5R_type_t ret_value = H5R_BADTYPE;
|
|
|
|
FUNC_ENTER_NOAPI_NOERR
|
|
|
|
HDassert(dt);
|
|
|
|
if (dt->shared->type == H5T_REFERENCE)
|
|
ret_value = dt->shared->u.atomic.u.r.rtype;
|
|
|
|
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
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
htri_t
|
|
H5T_is_sensible(const H5T_t *dt)
|
|
{
|
|
htri_t ret_value = FAIL; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI_NOERR
|
|
|
|
HDassert(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;
|
|
|
|
case H5T_NO_CLASS:
|
|
case H5T_INTEGER:
|
|
case H5T_FLOAT:
|
|
case H5T_TIME:
|
|
case H5T_STRING:
|
|
case H5T_BITFIELD:
|
|
case H5T_OPAQUE:
|
|
case H5T_REFERENCE:
|
|
case H5T_VLEN:
|
|
case H5T_ARRAY:
|
|
case H5T_NCLASSES:
|
|
default:
|
|
/* Assume all other datatype are sensible to store on disk */
|
|
ret_value = TRUE;
|
|
break;
|
|
} /* end switch */
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
NAME
|
|
H5T_set_loc
|
|
PURPOSE
|
|
Recursively mark any datatypes as on disk/in memory
|
|
USAGE
|
|
htri_t H5T_set_loc(dt,f,loc)
|
|
H5T_t *dt; IN/OUT: Pointer to the datatype to mark
|
|
H5F_t *f; IN: Pointer to the file the datatype is in
|
|
H5T_loc_t loc IN: location of type
|
|
|
|
RETURNS
|
|
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
|
|
DESCRIPTION
|
|
Recursively descends any VL or compound datatypes to mark all VL datatypes
|
|
as either on disk or in memory.
|
|
--------------------------------------------------------------------------
|
|
*/
|
|
htri_t
|
|
H5T_set_loc(H5T_t *dt, H5VL_object_t *file, H5T_loc_t loc)
|
|
{
|
|
htri_t changed; /* Whether H5T_set_loc changed the type (even if the size didn't change) */
|
|
htri_t ret_value = 0; /* Indicate that success, but no location change */
|
|
unsigned i; /* Local index variable */
|
|
size_t old_size; /* Previous size of a field */
|
|
|
|
FUNC_ENTER_NOAPI(FAIL)
|
|
|
|
HDassert(dt);
|
|
HDassert(loc >= H5T_LOC_BADLOC && loc < H5T_LOC_MAXLOC);
|
|
|
|
/* Datatypes can't change in size if the force_conv flag is not set */
|
|
if (dt->shared->force_conv) {
|
|
/* Check the datatype of this element */
|
|
switch (dt->shared->type) {
|
|
case H5T_ARRAY: /* Recurse on VL, compound and array base element type */
|
|
/* Recurse if it's VL, compound, enum or array */
|
|
/* (If the force_conv flag is _not_ set, the type cannot change in size, so don't recurse) */
|
|
if (dt->shared->parent->shared->force_conv &&
|
|
H5T_IS_COMPLEX(dt->shared->parent->shared->type)) {
|
|
/* Keep the old base element size for later */
|
|
old_size = dt->shared->parent->shared->size;
|
|
|
|
/* Mark the VL, compound or array type */
|
|
if ((changed = H5T_set_loc(dt->shared->parent, file, loc)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location")
|
|
if (changed > 0)
|
|
ret_value = changed;
|
|
|
|
/* Check if the field changed size */
|
|
if (old_size != dt->shared->parent->shared->size) {
|
|
/* Adjust the size of the array */
|
|
dt->shared->size = dt->shared->u.array.nelem * dt->shared->parent->shared->size;
|
|
} /* end if */
|
|
} /* end if */
|
|
break;
|
|
|
|
case H5T_COMPOUND: /* Check each field and recurse on VL, compound and array type */
|
|
{
|
|
ssize_t accum_change = 0; /* Amount of change in the offset of the fields */
|
|
|
|
/* Sort the fields based on offsets */
|
|
H5T__sort_value(dt, NULL);
|
|
|
|
for (i = 0; i < dt->shared->u.compnd.nmembs; i++) {
|
|
H5T_t *memb_type; /* Member's datatype pointer */
|
|
|
|
/* Range check against compound member's offset */
|
|
if ((accum_change < 0) && ((ssize_t)dt->shared->u.compnd.memb[i].offset < accum_change))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "invalid field size in datatype");
|
|
|
|
/* Apply the accumulated size change to the offset of the field */
|
|
dt->shared->u.compnd.memb[i].offset += (size_t)accum_change;
|
|
|
|
/* Set the member type pointer (for convenience) */
|
|
memb_type = dt->shared->u.compnd.memb[i].type;
|
|
|
|
/* Recurse if it's VL, compound, enum or array */
|
|
/* (If the force_conv flag is _not_ set, the type cannot change in size, so don't recurse)
|
|
*/
|
|
if (memb_type->shared->force_conv && H5T_IS_COMPLEX(memb_type->shared->type)) {
|
|
/* Keep the old field size for later */
|
|
old_size = memb_type->shared->size;
|
|
|
|
/* Mark the VL, compound, enum or array type */
|
|
if ((changed = H5T_set_loc(memb_type, file, loc)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location");
|
|
if (changed > 0)
|
|
ret_value = changed;
|
|
|
|
/* Check if the field changed size */
|
|
if (old_size != memb_type->shared->size) {
|
|
|
|
/* Fail if the old_size is zero */
|
|
if (0 == old_size)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL,
|
|
"old_size of zero would cause division by zero");
|
|
|
|
/* Adjust the size of the member */
|
|
dt->shared->u.compnd.memb[i].size =
|
|
(dt->shared->u.compnd.memb[i].size * memb_type->shared->size) / old_size;
|
|
|
|
/* Add that change to the accumulated size change */
|
|
accum_change += (ssize_t)(memb_type->shared->size - old_size);
|
|
} /* end if */
|
|
} /* end if */
|
|
} /* end for */
|
|
|
|
/* Range check against datatype size */
|
|
if ((accum_change < 0) && ((ssize_t)dt->shared->size < accum_change))
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "invalid field size in datatype");
|
|
|
|
/* Apply the accumulated size change to the datatype */
|
|
dt->shared->size += (size_t)accum_change;
|
|
} break;
|
|
|
|
case H5T_VLEN: /* Recurse on the VL information if it's VL, compound or array, then free VL
|
|
sequence */
|
|
/* Recurse if it's VL, compound, enum or array (ignore references here so that we can encode
|
|
* them as part of the same blob)*/
|
|
/* (If the force_conv flag is _not_ set, the type cannot change in size, so don't recurse) */
|
|
if (dt->shared->parent->shared->force_conv &&
|
|
H5T_IS_COMPLEX(dt->shared->parent->shared->type) &&
|
|
(dt->shared->parent->shared->type != H5T_REFERENCE)) {
|
|
if ((changed = H5T_set_loc(dt->shared->parent, file, loc)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location");
|
|
if (changed > 0)
|
|
ret_value = changed;
|
|
} /* end if */
|
|
|
|
/* Mark this VL sequence */
|
|
if ((changed = H5T__vlen_set_loc(dt, file, loc)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location");
|
|
if (changed > 0)
|
|
ret_value = changed;
|
|
break;
|
|
|
|
case H5T_REFERENCE:
|
|
/* Reference types go through type conversion */
|
|
if ((ret_value = H5T__ref_set_loc(dt, file, loc)) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "Unable to set reference location");
|
|
break;
|
|
|
|
case H5T_NO_CLASS:
|
|
case H5T_INTEGER:
|
|
case H5T_FLOAT:
|
|
case H5T_TIME:
|
|
case H5T_STRING:
|
|
case H5T_BITFIELD:
|
|
case H5T_OPAQUE:
|
|
case H5T_ENUM:
|
|
case H5T_NCLASSES:
|
|
default:
|
|
break;
|
|
} /* end switch */
|
|
} /* end if */
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_set_loc() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_is_relocatable
|
|
*
|
|
* Purpose: Check if a datatype will change between disk and memory.
|
|
*
|
|
* Notes: Currently, only variable-length and 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
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
htri_t
|
|
H5T_is_relocatable(const H5T_t *dt)
|
|
{
|
|
htri_t ret_value = FALSE;
|
|
|
|
FUNC_ENTER_NOAPI_NOERR
|
|
|
|
/* Sanity check */
|
|
HDassert(dt);
|
|
|
|
/* VL and reference datatypes are relocatable */
|
|
if (H5T_detect_class(dt, H5T_VLEN, FALSE) || H5T_detect_class(dt, H5T_REFERENCE, FALSE))
|
|
ret_value = TRUE;
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_is_relocatable() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T__detect_vlen_ref
|
|
*
|
|
* Purpose: Check whether a datatype contains (or is) a vlen reference
|
|
* datatype.
|
|
*
|
|
* Return: TRUE (1) or FALSE (0) on success
|
|
* (Can't fail)
|
|
*
|
|
* Programmer: Quincey Koziol
|
|
* Saturday, January 5, 2019
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static hbool_t
|
|
H5T__detect_vlen_ref(const H5T_t *dt)
|
|
{
|
|
unsigned u; /* Local index variable */
|
|
hbool_t ret_value = FALSE; /* Return value */
|
|
|
|
FUNC_ENTER_STATIC_NOERR
|
|
|
|
/* Sanity checks */
|
|
HDassert(dt);
|
|
|
|
/* Check if this datatype is a vlen reference */
|
|
/* TODO currently H5T_STD_REF is always considered as a vlen type */
|
|
if (H5T_REFERENCE == dt->shared->type && !dt->shared->u.atomic.u.r.opaque)
|
|
HGOTO_DONE(TRUE);
|
|
|
|
/* Check for types that might have the correct type as a component */
|
|
switch (dt->shared->type) {
|
|
case H5T_COMPOUND:
|
|
/* Iterate over all the compound datatype's fields */
|
|
for (u = 0; u < dt->shared->u.compnd.nmembs; u++)
|
|
/* Recurse on field's datatype */
|
|
if (H5T__detect_vlen_ref(dt->shared->u.compnd.memb[u].type))
|
|
HGOTO_DONE(TRUE);
|
|
break;
|
|
|
|
case H5T_ARRAY:
|
|
case H5T_VLEN:
|
|
case H5T_ENUM:
|
|
HGOTO_DONE(H5T__detect_vlen_ref(dt->shared->parent));
|
|
break;
|
|
|
|
case H5T_NO_CLASS:
|
|
case H5T_INTEGER:
|
|
case H5T_FLOAT:
|
|
case H5T_TIME:
|
|
case H5T_STRING:
|
|
case H5T_BITFIELD:
|
|
case H5T_OPAQUE:
|
|
case H5T_REFERENCE:
|
|
case H5T_NCLASSES:
|
|
default:
|
|
break;
|
|
} /* end if */
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T__detect_vlen_ref() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_is_vl_storage
|
|
*
|
|
* Purpose: Check if a datatype will be stored in a variable-length form.
|
|
*
|
|
* Notes: Currently, only variable-length string & sequences and region
|
|
* references are stored in a variable-length form.
|
|
*
|
|
* Return:
|
|
* One of two values on success:
|
|
* TRUE - If the datatype will be stored in a variable-length form
|
|
* FALSE - If the datatype will NOT be stored in a variable-length form
|
|
* <0 is returned on failure
|
|
*
|
|
* Programmer: Quincey Koziol
|
|
* Saturday, January 5, 2019
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
htri_t
|
|
H5T_is_vl_storage(const H5T_t *dt)
|
|
{
|
|
htri_t ret_value = FALSE;
|
|
|
|
FUNC_ENTER_NOAPI_NOERR
|
|
|
|
/* Sanity check */
|
|
HDassert(dt);
|
|
|
|
/* VL and region reference datatypes are stored in variable-length form */
|
|
if (H5T_detect_class(dt, H5T_VLEN, FALSE))
|
|
ret_value = TRUE;
|
|
else if (H5T_detect_class(dt, H5T_REFERENCE, FALSE))
|
|
ret_value = H5T__detect_vlen_ref(dt);
|
|
else
|
|
ret_value = FALSE;
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_is_vl_storage() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T__upgrade_version_cb
|
|
*
|
|
* Purpose: H5T__visit callback to Upgrade the version of a datatype
|
|
* (if there's any benefit to doing so)
|
|
*
|
|
* Note: The behavior below is tightly coupled with the "better"
|
|
* encodings for datatype messages in the datatype message
|
|
* encoding routine.
|
|
*
|
|
* Return: Non-negative on success/Negative on failure
|
|
*
|
|
* Programmer: Quincey Koziol
|
|
* Thursday, July 19, 2007
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
static herr_t
|
|
H5T__upgrade_version_cb(H5T_t *dt, void *op_value)
|
|
{
|
|
FUNC_ENTER_STATIC_NOERR
|
|
|
|
/* Sanity check */
|
|
HDassert(dt);
|
|
HDassert(op_value);
|
|
|
|
/* Special behavior for each type of datatype */
|
|
switch (dt->shared->type) {
|
|
case H5T_COMPOUND:
|
|
case H5T_ARRAY:
|
|
case H5T_ENUM:
|
|
/* These types benefit from "upgrading" their version */
|
|
if (*(unsigned *)op_value > dt->shared->version)
|
|
dt->shared->version = *(unsigned *)op_value;
|
|
break;
|
|
|
|
case H5T_VLEN:
|
|
if (dt->shared->parent->shared->version > dt->shared->version)
|
|
dt->shared->version = dt->shared->parent->shared->version;
|
|
break;
|
|
|
|
case H5T_NO_CLASS:
|
|
case H5T_INTEGER:
|
|
case H5T_FLOAT:
|
|
case H5T_TIME:
|
|
case H5T_STRING:
|
|
case H5T_BITFIELD:
|
|
case H5T_OPAQUE:
|
|
case H5T_REFERENCE:
|
|
case H5T_NCLASSES:
|
|
default:
|
|
break;
|
|
} /* end switch */
|
|
|
|
FUNC_LEAVE_NOAPI(SUCCEED)
|
|
} /* end H5T__upgrade_version_cb() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T__upgrade_version
|
|
*
|
|
* Purpose: Upgrade the version of a datatype (if there's any benefit to
|
|
* doing so) and recursively apply to compound members and/or
|
|
* parent datatypes.
|
|
*
|
|
* Return: Non-negative on success/Negative on failure
|
|
*
|
|
* Programmer: Quincey Koziol
|
|
* Thursday, July 19, 2007
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5T__upgrade_version(H5T_t *dt, unsigned new_version)
|
|
{
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_PACKAGE
|
|
|
|
/* Sanity check */
|
|
HDassert(dt);
|
|
|
|
/* Iterate over entire datatype, upgrading the version of components, if it's useful */
|
|
if (H5T__visit(dt, (H5T_VISIT_SIMPLE | H5T_VISIT_COMPLEX_LAST), H5T__upgrade_version_cb, &new_version) <
|
|
0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_BADITER, FAIL, "iteration to upgrade datatype encoding version failed")
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T__upgrade_version() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_set_version
|
|
*
|
|
* Purpose: Set the encoding for a datatype to the version indicated by
|
|
* the file's low bound if that is higher than the datatype's
|
|
* version.
|
|
*
|
|
* Return: Non-negative on success/Negative on failure
|
|
*
|
|
* Programmer: Vailin Choi; December 2017
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5T_set_version(H5F_t *f, H5T_t *dt)
|
|
{
|
|
unsigned vers; /* The version */
|
|
herr_t ret_value = SUCCEED; /* Return value */
|
|
|
|
FUNC_ENTER_NOAPI(FAIL)
|
|
|
|
/* Sanity check */
|
|
HDassert(f);
|
|
HDassert(dt);
|
|
|
|
vers = H5O_dtype_ver_bounds[H5F_LOW_BOUND(f)];
|
|
if (vers > dt->shared->version) {
|
|
/* Upgrade the format version for the datatype */
|
|
if (H5T__upgrade_version(dt, vers) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't upgrade datatype encoding")
|
|
}
|
|
|
|
/* Version bounds check */
|
|
if (dt->shared->version > H5O_dtype_ver_bounds[H5F_HIGH_BOUND(f)])
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_BADRANGE, FAIL, "Datatype version out of bounds")
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_set_version() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_patch_file
|
|
*
|
|
* Purpose: Patch the top-level file pointers contained in dt to point
|
|
* to f, if dt is a committed type. This is possible because
|
|
* the top-level file pointer can be closed out from under
|
|
* dt while dt is contained in the shared file's cache.
|
|
*
|
|
* Return: SUCCEED
|
|
*
|
|
* Programmer: Neil Fortner
|
|
* Thursday, July 14, 2011
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5T_patch_file(H5T_t *dt, H5F_t *f)
|
|
{
|
|
herr_t ret_value = SUCCEED;
|
|
|
|
FUNC_ENTER_NOAPI_NOERR
|
|
|
|
/* Sanity check */
|
|
HDassert(dt);
|
|
HDassert(f);
|
|
|
|
if (H5T_STATE_OPEN == dt->shared->state || H5T_STATE_NAMED == dt->shared->state) {
|
|
dt->oloc.file = f;
|
|
dt->sh_loc.file = f;
|
|
} /* end if */
|
|
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_patch_file() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_patch_vlen_file
|
|
*
|
|
* Purpose: Patch the top-level file pointer contained in (dt->shared->u.vlen.file)
|
|
* to point to file. This is possible because
|
|
* the top-level file pointer can be closed out from under
|
|
* dt while dt is contained in the shared file's cache.
|
|
*
|
|
* Return: SUCCEED
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5T_patch_vlen_file(H5T_t *dt, H5VL_object_t *file)
|
|
{
|
|
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
|
|
|
/* Sanity check */
|
|
HDassert(dt);
|
|
HDassert(dt->shared);
|
|
HDassert(file);
|
|
|
|
if ((dt->shared->type == H5T_VLEN) && dt->shared->u.vlen.file != file)
|
|
dt->shared->u.vlen.file = file;
|
|
|
|
FUNC_LEAVE_NOAPI(SUCCEED)
|
|
} /* end H5T_patch_vlen_file() */
|
|
|
|
/*-------------------------------------------------------------------------
|
|
* Function: H5T_own_vol_obj
|
|
*
|
|
* Purpose: Transfers ownership of the supplied VOL object to the
|
|
* datatype, the VOL object will be freed when the datatype
|
|
* is closed.
|
|
*
|
|
* Return: Non-negative on success/Negative on failure
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
herr_t
|
|
H5T_own_vol_obj(H5T_t *dt, H5VL_object_t *vol_obj)
|
|
{
|
|
herr_t ret_value = SUCCEED;
|
|
|
|
FUNC_ENTER_NOAPI(FAIL)
|
|
|
|
/* Sanity check */
|
|
HDassert(dt);
|
|
HDassert(dt->shared);
|
|
HDassert(vol_obj);
|
|
|
|
/* Currently no support for owning multiple VOL objects, free the previous
|
|
* owned object. Currently this is only used for holding open VOL objects
|
|
* used in the "loc" for vlens and references, so if this is being
|
|
* overwritten we don't need the old one anyways. */
|
|
if (dt->shared->owned_vol_obj && H5VL_free_object(dt->shared->owned_vol_obj) < 0)
|
|
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close owned VOL object")
|
|
|
|
/* Take ownership */
|
|
dt->shared->owned_vol_obj = vol_obj;
|
|
(void)H5VL_object_inc_rc(vol_obj);
|
|
|
|
done:
|
|
FUNC_LEAVE_NOAPI(ret_value)
|
|
} /* end H5T_own_vol_obj() */
|