#include "H5Amodule.h"
#define H5O_FRIEND
#include "H5private.h"
#include "H5Apkg.h"
#include "H5CXprivate.h"
#include "H5Dprivate.h"
#include "H5Eprivate.h"
#include "H5Iprivate.h"
#include "H5MMprivate.h"
#include "H5Opkg.h"
#include "H5SMprivate.h"
typedef struct {
H5F_t *f;
H5A_attr_table_t *atable;
size_t curr_attr;
hbool_t bogus_crt_idx;
} H5A_compact_bt_ud_t;
typedef struct {
H5A_attr_table_t *atable;
size_t curr_attr;
} H5A_dense_bt_ud_t;
typedef struct {
const H5O_ainfo_t *ainfo;
H5F_t *file;
hbool_t *recompute_size;
H5O_copy_t *cpy_info;
const H5O_loc_t *oloc_src;
H5O_loc_t *oloc_dst;
} H5A_dense_file_cp_ud_t;
static herr_t H5A__open_common(const H5G_loc_t *loc, H5A_t *attr);
static herr_t H5A__compact_build_table_cb(H5O_t *oh, H5O_mesg_t *mesg,
unsigned sequence, unsigned *oh_flags_ptr, void *_udata);
static herr_t H5A__dense_build_table_cb(const H5A_t *attr, void *_udata);
static int H5A__attr_cmp_name_inc(const void *attr1, const void *attr2);
static int H5A__attr_cmp_name_dec(const void *attr1, const void *attr2);
static int H5A__attr_cmp_corder_inc(const void *attr1, const void *attr2);
static int H5A__attr_cmp_corder_dec(const void *attr1, const void *attr2);
static herr_t H5A__attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type,
H5_iter_order_t order);
static herr_t H5A__iterate_common(hid_t loc_id, H5_index_t idx_type,
H5_iter_order_t order, hsize_t *idx, H5A_attr_iter_op_t *attr_op, void *op_data);
const unsigned H5O_attr_ver_bounds[] = {
H5O_ATTR_VERSION_1,
H5O_ATTR_VERSION_3,
H5O_ATTR_VERSION_LATEST
};
typedef H5A_t* H5A_t_ptr;
H5FL_SEQ_DEFINE(H5A_t_ptr);
H5A_t *
H5A__create(const H5G_loc_t *loc, const char *name, const H5T_t *type,
const H5S_t *space, hid_t acpl_id)
{
H5A_t *attr = NULL;
hssize_t snelmts;
size_t nelmts;
htri_t exists;
H5A_t *ret_value = NULL;
FUNC_ENTER_PACKAGE_TAG(loc->oloc->addr)
HDassert(loc);
HDassert(name);
HDassert(type);
HDassert(space);
if((exists = H5O__attr_exists(loc->oloc, name)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "error checking attributes")
else if(exists > 0)
HGOTO_ERROR(H5E_ATTR, H5E_ALREADYEXISTS, NULL, "attribute already exists")
if(!(H5S_has_extent(space)))
HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, NULL, "dataspace extent has not been set")
if(H5T_is_sensible(type) != TRUE)
HGOTO_ERROR(H5E_ATTR, H5E_BADTYPE, NULL, "datatype is not sensible")
if(NULL == (attr = H5FL_CALLOC(H5A_t)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "memory allocation failed for attribute info")
if(NULL == (attr->shared = H5FL_CALLOC(H5A_shared_t)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "can't allocate shared attr structure")
if(acpl_id == H5P_DEFAULT)
attr->shared->encoding = H5F_DEFAULT_CSET;
else {
H5P_genplist_t *ac_plist;
if(NULL == (ac_plist = (H5P_genplist_t *)H5I_object(acpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a property list")
if(H5P_get(ac_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get character encoding flag")
}
attr->shared->name = H5MM_xstrdup(name);
if(NULL == (attr->shared->dt = H5T_copy(type, H5T_COPY_ALL)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "can't get shared datatype info")
if(H5T_convert_committed_datatype(attr->shared->dt, loc->oloc->file) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "can't get shared datatype info")
if(H5T_set_loc(attr->shared->dt, loc->oloc->file, H5T_LOC_DISK) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location")
if(H5T_set_version(loc->oloc->file, attr->shared->dt) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set version of datatype")
attr->shared->ds = H5S_copy(space, FALSE, TRUE);
if(H5S_set_version(loc->oloc->file, attr->shared->ds) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set version of dataspace")
if(H5O_loc_copy_deep(&(attr->oloc), loc->oloc) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to copy entry")
if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy path")
if(H5SM_try_share(attr->oloc.file, NULL, 0, H5O_DTYPE_ID, attr->shared->dt, NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, NULL, "trying to share datatype failed")
if(H5SM_try_share(attr->oloc.file, NULL, 0, H5O_SDSPACE_ID, attr->shared->ds, NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, NULL, "trying to share dataspace failed")
if(H5T_committed(attr->shared->dt))
if(H5T_link(attr->shared->dt, 1) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, NULL, "unable to adjust shared datatype link count")
attr->shared->dt_size = H5O_msg_raw_size(attr->oloc.file, H5O_DTYPE_ID, FALSE, attr->shared->dt);
attr->shared->ds_size = H5O_msg_raw_size(attr->oloc.file, H5O_SDSPACE_ID, FALSE, attr->shared->ds);
if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, NULL, "dataspace is invalid")
H5_CHECKED_ASSIGN(nelmts, size_t, snelmts, hssize_t);
HDassert(attr->shared->dt_size > 0);
HDassert(attr->shared->ds_size > 0);
attr->shared->data_size = nelmts * H5T_GET_SIZE(attr->shared->dt);
if(H5O_open(&(attr->oloc)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to open")
attr->obj_opened = TRUE;
if(H5A__set_version(attr->oloc.file, attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "unable to update attribute version")
if(H5O__attr_create(&(attr->oloc), attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, NULL, "unable to create attribute in object header")
ret_value = attr;
done:
if(NULL == ret_value && attr && H5A__close(attr))
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
H5A_t *
H5A__create_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr_name,
const H5T_t *type, const H5S_t *space, hid_t acpl_id)
{
H5G_loc_t obj_loc;
H5G_name_t obj_path;
H5O_loc_t obj_oloc;
hbool_t loc_found = FALSE;
H5A_t *attr = NULL;
H5A_t *ret_value = NULL;
FUNC_ENTER_PACKAGE
HDassert(loc);
HDassert(obj_name);
HDassert(attr_name);
obj_loc.oloc = &obj_oloc;
obj_loc.path = &obj_path;
H5G_loc_reset(&obj_loc);
if(H5G_loc_find(loc, obj_name, &obj_loc) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "object not found")
loc_found = TRUE;
if(NULL == (attr = H5A__create(&obj_loc, attr_name, type, space, acpl_id)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to create attribute")
ret_value = attr;
done:
if(loc_found && H5G_loc_free(&obj_loc) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't free location")
if(ret_value == NULL)
if(attr && H5A__close(attr) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5A__open_common(const H5G_loc_t *loc, H5A_t *attr)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(loc);
HDassert(attr);
#if defined(H5_USING_MEMCHECKER) || !defined(NDEBUG)
if(H5O_loc_reset(&(attr->oloc)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to reset location")
#endif
if(H5G_name_free(&(attr->path)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path")
if(H5O_loc_copy_deep(&(attr->oloc), loc->oloc) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry")
if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy entry")
if(H5O_open(&(attr->oloc)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open")
attr->obj_opened = TRUE;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5A_t *
H5A__open(const H5G_loc_t *loc, const char *attr_name)
{
H5A_t *attr = NULL;
H5A_t *ret_value = NULL;
FUNC_ENTER_PACKAGE
HDassert(loc);
HDassert(attr_name);
if(NULL == (attr = H5O__attr_open_by_name(loc->oloc, attr_name)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to load attribute info from object header for attribute: '%s'", attr_name)
if(H5A__open_common(loc, attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute")
ret_value = attr;
done:
if(ret_value == NULL)
if(attr && H5A__close(attr) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
FUNC_LEAVE_NOAPI(ret_value)
}
H5A_t *
H5A__open_by_idx(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n)
{
H5G_loc_t obj_loc;
H5G_name_t obj_path;
H5O_loc_t obj_oloc;
hbool_t loc_found = FALSE;
H5A_t *attr = NULL;
H5A_t *ret_value = NULL;
FUNC_ENTER_PACKAGE
HDassert(loc);
HDassert(obj_name);
obj_loc.oloc = &obj_oloc;
obj_loc.path = &obj_path;
H5G_loc_reset(&obj_loc);
if(H5G_loc_find(loc, obj_name, &obj_loc) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "object not found")
loc_found = TRUE;
if(NULL == (attr = H5O__attr_open_by_idx(obj_loc.oloc, idx_type, order, n)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to load attribute info from object header")
if(H5A__open_common(&obj_loc, attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute")
ret_value = attr;
done:
if(loc_found && H5G_loc_free(&obj_loc) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't free location")
if(ret_value == NULL)
if(attr && H5A__close(attr) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
FUNC_LEAVE_NOAPI(ret_value)
}
H5A_t *
H5A__open_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr_name)
{
H5G_loc_t obj_loc;
H5G_name_t obj_path;
H5O_loc_t obj_oloc;
hbool_t loc_found = FALSE;
H5A_t *attr = NULL;
H5A_t *ret_value = NULL;
FUNC_ENTER_PACKAGE
HDassert(loc);
HDassert(obj_name);
HDassert(attr_name);
obj_loc.oloc = &obj_oloc;
obj_loc.path = &obj_path;
H5G_loc_reset(&obj_loc);
if(H5G_loc_find(loc, obj_name, &obj_loc) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "object not found")
loc_found = TRUE;
if(NULL == (attr = H5O__attr_open_by_name(obj_loc.oloc, attr_name)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to load attribute info from object header")
if(H5A__open_common(loc, attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute")
ret_value = attr;
done:
if(loc_found && H5G_loc_free(&obj_loc) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't free location")
if(ret_value == NULL)
if(attr && H5A__close(attr) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5A__read(const H5A_t *attr, const H5T_t *mem_type, void *buf)
{
uint8_t *tconv_buf = NULL;
uint8_t *bkg_buf = NULL;
hssize_t snelmts;
size_t nelmts;
H5T_path_t *tpath = NULL;
hid_t src_id = -1, dst_id = -1;
size_t src_type_size;
size_t dst_type_size;
size_t buf_size;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE_TAG(attr->oloc.addr)
HDassert(attr);
HDassert(mem_type);
HDassert(buf);
if(H5T_patch_vlen_file(attr->shared->dt, attr->oloc.file) < 0 )
HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "can't patch VL datatype file pointer")
if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
H5_CHECKED_ASSIGN(nelmts, size_t, snelmts, hssize_t);
if(nelmts > 0) {
src_type_size = H5T_GET_SIZE(attr->shared->dt);
dst_type_size = H5T_GET_SIZE(mem_type);
if(attr->obj_opened && !attr->shared->data)
HDmemset(buf, 0, (dst_type_size * nelmts));
else {
if(NULL == (tpath = H5T_path_find(attr->shared->dt, mem_type)))
HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes")
if(!H5T_path_noop(tpath)) {
if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->shared->dt, H5T_COPY_ALL), FALSE)) < 0 ||
(dst_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL), FALSE)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion")
buf_size = nelmts * MAX(src_type_size, dst_type_size);
if(NULL == (tconv_buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed")
if(NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size)))
HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed")
H5MM_memcpy(tconv_buf, attr->shared->data, (src_type_size * nelmts));
if(H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "datatype conversion failed")
H5MM_memcpy(buf, tconv_buf, (dst_type_size * nelmts));
}
else {
HDassert(dst_type_size == src_type_size);
H5MM_memcpy(buf, attr->shared->data, (dst_type_size * nelmts));
}
}
}
done:
if(src_id >= 0 && H5I_dec_ref(src_id) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object")
if(dst_id >= 0 && H5I_dec_ref(dst_id) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object")
if(tconv_buf)
tconv_buf = H5FL_BLK_FREE(attr_buf, tconv_buf);
if(bkg_buf)
bkg_buf = H5FL_BLK_FREE(attr_buf, bkg_buf);
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
herr_t
H5A__write(H5A_t *attr, const H5T_t *mem_type, const void *buf)
{
uint8_t *tconv_buf = NULL;
hbool_t tconv_owned = FALSE;
uint8_t *bkg_buf = NULL;
hssize_t snelmts;
size_t nelmts;
H5T_path_t *tpath = NULL;
hid_t src_id = -1, dst_id = -1;
size_t src_type_size;
size_t dst_type_size;
size_t buf_size;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE_TAG(attr->oloc.addr)
HDassert(attr);
HDassert(mem_type);
HDassert(buf);
if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
H5_CHECKED_ASSIGN(nelmts, size_t, snelmts, hssize_t);
if(nelmts > 0) {
src_type_size = H5T_GET_SIZE(mem_type);
dst_type_size = H5T_GET_SIZE(attr->shared->dt);
if(NULL == (tpath = H5T_path_find(mem_type, attr->shared->dt)))
HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes")
if(!H5T_path_noop(tpath)) {
if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL), FALSE)) < 0 ||
(dst_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->shared->dt, H5T_COPY_ALL), FALSE)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion")
buf_size = nelmts * MAX(src_type_size, dst_type_size);
if(NULL == (tconv_buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed")
if(NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed")
H5MM_memcpy(tconv_buf, buf, (src_type_size * nelmts));
if(H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "datatype conversion failed")
if(attr->shared->data)
attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data);
attr->shared->data = tconv_buf;
tconv_owned = TRUE;
}
else {
HDassert(dst_type_size == src_type_size);
if(attr->shared->data == NULL)
if(NULL == (attr->shared->data = H5FL_BLK_MALLOC(attr_buf, dst_type_size * nelmts)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
H5MM_memcpy(attr->shared->data, buf, (dst_type_size * nelmts));
}
if(H5O__attr_write(&(attr->oloc), attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to modify attribute")
}
done:
if(src_id >= 0 && H5I_dec_ref(src_id) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object")
if(dst_id >= 0 && H5I_dec_ref(dst_id) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object")
if(tconv_buf && !tconv_owned)
tconv_buf = H5FL_BLK_FREE(attr_buf, tconv_buf);
if(bkg_buf)
bkg_buf = H5FL_BLK_FREE(attr_buf, bkg_buf);
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
ssize_t
H5A__get_name(H5A_t *attr, size_t buf_size, char *buf)
{
size_t copy_len, nbytes;
ssize_t ret_value = -1;
FUNC_ENTER_PACKAGE_NOERR
nbytes = HDstrlen(attr->shared->name);
HDassert((ssize_t)nbytes >= 0);
copy_len = MIN(buf_size - 1, nbytes);
if(buf && copy_len > 0) {
H5MM_memcpy(buf, attr->shared->name, copy_len);
buf[copy_len]='\0';
}
ret_value = (ssize_t)nbytes;
FUNC_LEAVE_NOAPI(ret_value)
}
hid_t
H5A_get_space(H5A_t *attr)
{
H5S_t *ds = NULL;
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_NOAPI_NOINIT
HDassert(attr);
if (NULL == (ds = H5S_copy(attr->shared->ds, FALSE, TRUE)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5I_INVALID_HID, "unable to copy dataspace")
if ((ret_value = H5I_register(H5I_DATASPACE, ds, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace atom")
done:
if (H5I_INVALID_HID == ret_value && ds && H5S_close(ds) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release dataspace")
FUNC_LEAVE_NOAPI(ret_value)
}
hid_t
H5A__get_type(H5A_t *attr)
{
H5T_t *dt = NULL;
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_PACKAGE
HDassert(attr);
if (H5T_patch_file(attr->shared->dt, attr->oloc.file) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5I_INVALID_HID, "unable to patch datatype's file pointer")
if (NULL == (dt = H5T_copy_reopen(attr->shared->dt)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, H5I_INVALID_HID, "unable to copy datatype")
if (H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, "invalid datatype location")
if (H5T_lock(dt, FALSE) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, "unable to lock transient datatype")
if ((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register datatype")
done:
if(H5I_INVALID_HID == ret_value)
if(dt && H5T_close(dt) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, H5I_INVALID_HID, "unable to release datatype")
FUNC_LEAVE_NOAPI(ret_value)
}
hid_t
H5A__get_create_plist(H5A_t* attr)
{
H5P_genplist_t *plist;
hid_t new_plist_id;
H5P_genplist_t *new_plist;
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_PACKAGE
if(NULL == (plist = (H5P_genplist_t *)H5I_object(H5P_LST_ATTRIBUTE_CREATE_ID_g)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get default ACPL")
if((new_plist_id = H5P_copy_plist(plist, TRUE)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy attribute creation properties")
if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_plist_id)))
HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get property list")
if(H5P_set(new_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set character encoding")
ret_value = new_plist_id;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5A__get_info(const H5A_t *attr, H5A_info_t *ainfo)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(attr);
HDassert(ainfo);
ainfo->cset = attr->shared->encoding;
ainfo->data_size = attr->shared->data_size;
if(attr->shared->crt_idx == H5O_MAX_CRT_ORDER_IDX) {
ainfo->corder_valid = FALSE;
ainfo->corder = 0;
}
else {
ainfo->corder_valid = TRUE;
ainfo->corder = attr->shared->crt_idx;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5A_t *
H5A__copy(H5A_t *_new_attr, const H5A_t *old_attr)
{
H5A_t *new_attr = NULL;
hbool_t allocated_attr = FALSE;
H5A_t *ret_value = NULL;
FUNC_ENTER_PACKAGE
HDassert(old_attr);
if(_new_attr == NULL) {
if(NULL == (new_attr = H5FL_CALLOC(H5A_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
allocated_attr = TRUE;
}
else
new_attr = _new_attr;
new_attr->sh_loc = old_attr->sh_loc;
if(H5G_name_copy(&(new_attr->path), &(old_attr->path), H5_COPY_DEEP) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy path")
new_attr->shared = old_attr->shared;
new_attr->shared->nrefs++;
new_attr->obj_opened = FALSE;
ret_value = new_attr;
done:
if(ret_value == NULL)
if(allocated_attr && new_attr && H5A__close(new_attr) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5A__free(H5A_t *attr)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(attr);
if(attr->shared->name) {
H5MM_xfree(attr->shared->name);
attr->shared->name = NULL;
}
if(attr->shared->dt) {
if(H5T_close_real(attr->shared->dt) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release datatype info")
attr->shared->dt = NULL;
}
if(attr->shared->ds) {
if(H5S_close(attr->shared->ds) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release dataspace info")
attr->shared->ds = NULL;
}
if(attr->shared->data)
attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5A__close_cb(H5A_t *attr)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(attr);
HDassert(attr->shared);
if(H5A__close(attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, FAIL, "problem closing attribute")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5A__close(H5A_t *attr)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(attr);
HDassert(attr->shared);
if(attr->obj_opened && (H5O_close(&(attr->oloc), NULL) < 0))
HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release object header info")
if(attr->shared->nrefs <= 1) {
if(H5A__free(attr) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info")
attr->shared = H5FL_FREE(H5A_shared_t, attr->shared);
}
else {
--attr->shared->nrefs;
}
if(H5G_name_free(&(attr->path)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path")
attr->shared = NULL;
attr = H5FL_FREE(H5A_t, attr);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5O_loc_t *
H5A_oloc(H5A_t *attr)
{
H5O_loc_t *ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
HDassert(attr);
ret_value = &(attr->oloc);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5G_name_t *
H5A_nameof(H5A_t *attr)
{
H5G_name_t *ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
HDassert(attr);
ret_value = &(attr->path);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5T_t *
H5A_type(const H5A_t *attr)
{
H5T_t *ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
HDassert(attr);
ret_value = attr->shared->dt;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
htri_t
H5A__exists_by_name(H5G_loc_t loc, const char *obj_name, const char *attr_name)
{
H5G_loc_t obj_loc;
H5G_name_t obj_path;
H5O_loc_t obj_oloc;
hbool_t loc_found = FALSE;
htri_t ret_value = FAIL;
FUNC_ENTER_PACKAGE
obj_loc.oloc = &obj_oloc;
obj_loc.path = &obj_path;
H5G_loc_reset(&obj_loc);
if(H5G_loc_find(&loc, obj_name, &obj_loc) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found")
loc_found = TRUE;
if((ret_value = H5O__attr_exists(obj_loc.oloc, attr_name)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to determine if attribute exists")
done:
if(loc_found && H5G_loc_free(&obj_loc) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5A__compact_build_table_cb(H5O_t H5_ATTR_UNUSED *oh, H5O_mesg_t *mesg,
unsigned sequence, unsigned H5_ATTR_UNUSED *oh_modified, void *_udata)
{
H5A_compact_bt_ud_t *udata = (H5A_compact_bt_ud_t *)_udata;
herr_t ret_value = H5_ITER_CONT;
FUNC_ENTER_STATIC
HDassert(mesg);
if(udata->curr_attr == udata->atable->nattrs) {
H5A_t **new_table;
size_t new_table_size;
new_table_size = MAX(1, 2 * udata->atable->nattrs);
if(NULL == (new_table = (H5A_t **)H5FL_SEQ_REALLOC(H5A_t_ptr, udata->atable->attrs, new_table_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "unable to extend attribute table")
udata->atable->attrs = new_table;
udata->atable->nattrs = new_table_size;
}
if(NULL == (udata->atable->attrs[udata->curr_attr] = H5A__copy(NULL, (const H5A_t *)mesg->native)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
if(udata->bogus_crt_idx)
((udata->atable->attrs[udata->curr_attr])->shared)->crt_idx = sequence;
udata->curr_attr++;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5A__compact_build_table(H5F_t *f, H5O_t *oh, H5_index_t idx_type,
H5_iter_order_t order, H5A_attr_table_t *atable)
{
H5A_compact_bt_ud_t udata;
H5O_mesg_operator_t op;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(oh);
HDassert(atable);
atable->attrs = NULL;
atable->nattrs = 0;
udata.f = f;
udata.atable = atable;
udata.curr_attr = 0;
udata.bogus_crt_idx = (hbool_t)((oh->version == H5O_VERSION_1 ||
!(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)) ? TRUE : FALSE);
op.op_type = H5O_MESG_OP_LIB;
op.u.lib_op = H5A__compact_build_table_cb;
if(H5O__msg_iterate_real(f, oh, H5O_MSG_ATTR, &op, &udata) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error building attribute table")
atable->nattrs = udata.curr_attr;
if(atable->nattrs > 0) {
if(H5A__attr_sort_table(atable, idx_type, order) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSORT, FAIL, "error sorting attribute table")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5A__dense_build_table_cb(const H5A_t *attr, void *_udata)
{
H5A_dense_bt_ud_t *udata = (H5A_dense_bt_ud_t *)_udata;
herr_t ret_value = H5_ITER_CONT;
FUNC_ENTER_STATIC
HDassert(attr);
HDassert(udata);
HDassert(udata->curr_attr < udata->atable->nattrs);
if(NULL == (udata->atable->attrs[udata->curr_attr] = H5FL_CALLOC(H5A_t)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, H5_ITER_ERROR, "can't allocate attribute")
if(NULL == H5A__copy(udata->atable->attrs[udata->curr_attr], attr))
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
udata->curr_attr++;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5A__dense_build_table(H5F_t *f, const H5O_ainfo_t *ainfo,
H5_index_t idx_type, H5_iter_order_t order, H5A_attr_table_t *atable)
{
H5B2_t *bt2_name = NULL;
hsize_t nrec;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(ainfo);
HDassert(H5F_addr_defined(ainfo->fheap_addr));
HDassert(H5F_addr_defined(ainfo->name_bt2_addr));
HDassert(atable);
if(NULL == (bt2_name = H5B2_open(f, ainfo->name_bt2_addr, NULL)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
if(H5B2_get_nrec(bt2_name, &nrec) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve # of records in index")
H5_CHECK_OVERFLOW(nrec, hsize_t, size_t);
atable->nattrs = (size_t)nrec;
if(atable->nattrs > 0) {
H5A_dense_bt_ud_t udata;
H5A_attr_iter_op_t attr_op;
if((atable->attrs = (H5A_t **)H5FL_SEQ_CALLOC(H5A_t_ptr, atable->nattrs)) == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
udata.atable = atable;
udata.curr_attr = 0;
attr_op.op_type = H5A_ATTR_OP_LIB;
attr_op.u.lib_op = H5A__dense_build_table_cb;
if(H5A__dense_iterate(f, (hid_t)0, ainfo, H5_INDEX_NAME, H5_ITER_NATIVE,
(hsize_t)0, NULL, &attr_op, &udata) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")
if(H5A__attr_sort_table(atable, idx_type, order) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSORT, FAIL, "error sorting attribute table")
}
else
atable->attrs = NULL;
done:
if(bt2_name && H5B2_close(bt2_name) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for name index")
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5A__attr_cmp_name_inc(const void *attr1, const void *attr2)
{
FUNC_ENTER_STATIC_NOERR
FUNC_LEAVE_NOAPI(HDstrcmp((*(const H5A_t * const *)attr1)->shared->name,
(*(const H5A_t * const *)attr2)->shared->name))
}
static int
H5A__attr_cmp_name_dec(const void *attr1, const void *attr2)
{
FUNC_ENTER_STATIC_NOERR
FUNC_LEAVE_NOAPI(HDstrcmp((*(const H5A_t * const *)attr2)->shared->name,
(*(const H5A_t * const *)attr1)->shared->name))
}
static int
H5A__attr_cmp_corder_inc(const void *attr1, const void *attr2)
{
int ret_value = 0;
FUNC_ENTER_STATIC_NOERR
if((*(const H5A_t * const *)attr1)->shared->crt_idx < (*(const H5A_t * const *)attr2)->shared->crt_idx)
ret_value = -1;
else if((*(const H5A_t * const *)attr1)->shared->crt_idx > (*(const H5A_t * const *)attr2)->shared->crt_idx)
ret_value = 1;
else
ret_value = 0;
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5A__attr_cmp_corder_dec(const void *attr1, const void *attr2)
{
int ret_value = 0;
FUNC_ENTER_STATIC_NOERR
if((*(const H5A_t * const *)attr1)->shared->crt_idx < (*(const H5A_t * const *)attr2)->shared->crt_idx)
ret_value = 1;
else if((*(const H5A_t * const *)attr1)->shared->crt_idx > (*(const H5A_t * const *)attr2)->shared->crt_idx)
ret_value = -1;
else
ret_value = 0;
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5A__attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type,
H5_iter_order_t order)
{
FUNC_ENTER_STATIC_NOERR
HDassert(atable);
if(idx_type == H5_INDEX_NAME) {
if(order == H5_ITER_INC)
HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t*), H5A__attr_cmp_name_inc);
else if(order == H5_ITER_DEC)
HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t*), H5A__attr_cmp_name_dec);
else
HDassert(order == H5_ITER_NATIVE);
}
else {
HDassert(idx_type == H5_INDEX_CRT_ORDER);
if(order == H5_ITER_INC)
HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t*), H5A__attr_cmp_corder_inc);
else if(order == H5_ITER_DEC)
HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t*), H5A__attr_cmp_corder_dec);
else
HDassert(order == H5_ITER_NATIVE);
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
herr_t
H5A__attr_iterate_table(const H5A_attr_table_t *atable, hsize_t skip,
hsize_t *last_attr, hid_t loc_id, const H5A_attr_iter_op_t *attr_op,
void *op_data)
{
size_t u;
herr_t ret_value = H5_ITER_CONT;
FUNC_ENTER_PACKAGE
HDassert(atable);
HDassert(attr_op);
if(last_attr)
*last_attr = skip;
H5_CHECKED_ASSIGN(u, size_t, skip, hsize_t)
for(; u < atable->nattrs && !ret_value; u++) {
switch(attr_op->op_type) {
case H5A_ATTR_OP_APP2:
{
H5A_info_t ainfo;
if(H5A__get_info(atable->attrs[u], &ainfo) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, H5_ITER_ERROR, "unable to get attribute info")
ret_value = (attr_op->u.app_op2)(loc_id, ((atable->attrs[u])->shared)->name, &ainfo, op_data);
break;
}
#ifndef H5_NO_DEPRECATED_SYMBOLS
case H5A_ATTR_OP_APP:
ret_value = (attr_op->u.app_op)(loc_id, ((atable->attrs[u])->shared)->name, op_data);
break;
#endif
case H5A_ATTR_OP_LIB:
ret_value = (attr_op->u.lib_op)((atable->attrs[u]), op_data);
break;
default:
HDassert("unknown attribute op type" && 0);
#ifdef NDEBUG
HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unsupported attribute op type")
#endif
}
if(last_attr)
(*last_attr)++;
}
if(ret_value < 0)
HERROR(H5E_ATTR, H5E_CANTNEXT, "iteration operator failed");
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5A__attr_release_table(H5A_attr_table_t *atable)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(atable);
if(atable->nattrs > 0) {
size_t u;
for(u = 0; u < atable->nattrs; u++)
if(atable->attrs[u] && H5A__close(atable->attrs[u]) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute")
}
else
HDassert(atable->attrs == NULL);
atable->attrs = (H5A_t **)H5FL_SEQ_FREE(H5A_t_ptr, atable->attrs);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
htri_t
H5A__get_ainfo(H5F_t *f, H5O_t *oh, H5O_ainfo_t *ainfo)
{
H5B2_t *bt2_name = NULL;
htri_t ret_value = FAIL;
FUNC_ENTER_NOAPI_TAG(oh->cache_info.addr, FAIL)
HDassert(f);
HDassert(oh);
HDassert(ainfo);
if((ret_value = H5O_msg_exists_oh(oh, H5O_AINFO_ID)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "unable to check object header")
if(ret_value > 0) {
if(NULL == H5O_msg_read_oh(f, oh, H5O_AINFO_ID, ainfo))
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't read AINFO message")
if(ainfo->nattrs == HSIZET_MAX) {
if(H5F_addr_defined(ainfo->fheap_addr)) {
if(NULL == (bt2_name = H5B2_open(f, ainfo->name_bt2_addr, NULL)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
if(H5B2_get_nrec(bt2_name, &ainfo->nattrs) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve # of records in index")
}
else
ainfo->nattrs = oh->attr_msgs_seen;
}
}
done:
if(bt2_name && H5B2_close(bt2_name) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for name index")
FUNC_LEAVE_NOAPI_TAG(ret_value)
}
herr_t
H5A__set_version(const H5F_t *f, H5A_t *attr)
{
hbool_t type_shared, space_shared;
uint8_t version;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(f);
HDassert(attr);
if(H5O_msg_is_shared(H5O_DTYPE_ID, attr->shared->dt) > 0)
type_shared = TRUE;
else
type_shared = FALSE;
if(H5O_msg_is_shared(H5O_SDSPACE_ID, attr->shared->ds) > 0)
space_shared = TRUE;
else
space_shared = FALSE;
if(attr->shared->encoding != H5T_CSET_ASCII)
version = H5O_ATTR_VERSION_3;
else if(type_shared || space_shared)
version = H5O_ATTR_VERSION_2;
else
version = H5O_ATTR_VERSION_1;
version = (uint8_t)MAX(version, (uint8_t)H5O_attr_ver_bounds[H5F_LOW_BOUND(f)]);
if(version > H5O_attr_ver_bounds[H5F_HIGH_BOUND(f)])
HGOTO_ERROR(H5E_ATTR, H5E_BADRANGE, FAIL, "attribute version out of bounds")
attr->shared->version = version;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5A_t *
H5A__attr_copy_file(const H5A_t *attr_src, H5F_t *file_dst, hbool_t *recompute_size,
H5O_copy_t H5_ATTR_NDEBUG_UNUSED *cpy_info)
{
H5A_t *attr_dst = NULL;
hid_t tid_src = -1;
hid_t tid_dst = -1;
hid_t tid_mem = -1;
void *buf = NULL;
void *reclaim_buf = NULL;
void *bkg_buf = NULL;
hid_t buf_sid = -1;
hssize_t sdst_nelmts;
size_t dst_nelmts;
size_t dst_dt_size;
H5A_t *ret_value = NULL;
FUNC_ENTER_PACKAGE
HDassert(attr_src);
HDassert(file_dst);
HDassert(cpy_info);
HDassert(!cpy_info->copy_without_attr);
if(NULL == (attr_dst = H5FL_CALLOC(H5A_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
*attr_dst = *attr_src;
if(NULL == (attr_dst->shared = H5FL_CALLOC(H5A_shared_t)))
HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared attr structure")
H5O_loc_reset(&(attr_dst->oloc));
H5G_name_reset(&(attr_dst->path));
attr_dst->obj_opened = FALSE;
attr_dst->shared->nrefs = 1;
attr_dst->shared->name = H5MM_strdup(attr_src->shared->name);
HDassert(attr_dst->shared->name);
attr_dst->shared->encoding = attr_src->shared->encoding;
if(NULL == (attr_dst->shared->dt = H5T_copy(attr_src->shared->dt, H5T_COPY_ALL)))
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "cannot copy datatype")
if(H5T_set_loc(attr_dst->shared->dt, file_dst, H5T_LOC_DISK) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "cannot mark datatype on disk")
if(!H5T_committed(attr_src->shared->dt)) {
if(H5O_msg_reset_share(H5O_DTYPE_ID, attr_dst->shared->dt) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to reset datatype sharing")
}
attr_dst->shared->ds = H5S_copy(attr_src->shared->ds, FALSE, TRUE);
HDassert(attr_dst->shared->ds);
if(H5O_msg_reset_share(H5O_SDSPACE_ID, attr_dst->shared->ds) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to reset dataspace sharing")
if(H5SM_try_share(file_dst, NULL, H5SM_DEFER, H5O_DTYPE_ID, attr_dst->shared->dt, NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "can't share attribute datatype")
if(H5SM_try_share(file_dst, NULL, H5SM_DEFER, H5O_SDSPACE_ID, attr_dst->shared->ds, NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, NULL, "can't share attribute dataspace")
attr_dst->shared->dt_size = H5O_msg_raw_size(file_dst, H5O_DTYPE_ID, FALSE, attr_dst->shared->dt);
HDassert(attr_dst->shared->dt_size > 0);
attr_dst->shared->ds_size = H5O_msg_raw_size(file_dst, H5O_SDSPACE_ID, FALSE, attr_dst->shared->ds);
HDassert(attr_dst->shared->ds_size > 0);
if(attr_dst->shared->dt_size != attr_src->shared->dt_size || attr_dst->shared->ds_size != attr_src->shared->ds_size)
*recompute_size = TRUE;
if((sdst_nelmts = H5S_GET_EXTENT_NPOINTS(attr_dst->shared->ds)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, NULL, "dataspace is invalid")
H5_CHECKED_ASSIGN(dst_nelmts, size_t, sdst_nelmts, hssize_t);
if(0 == (dst_dt_size = H5T_get_size(attr_dst->shared->dt)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size")
attr_dst->shared->data_size = dst_nelmts * dst_dt_size;
if(attr_src->shared->data) {
if(NULL == (attr_dst->shared->data = H5FL_BLK_MALLOC(attr_buf, attr_dst->shared->data_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
if(H5T_detect_class(attr_src->shared->dt, H5T_VLEN, FALSE) > 0) {
H5T_path_t *tpath_src_mem, *tpath_mem_dst;
H5T_t *dt_mem;
size_t src_dt_size;
size_t tmp_dt_size;
size_t max_dt_size;
H5S_t *buf_space;
hsize_t buf_dim;
size_t nelmts;
size_t buf_size;
if((tid_src = H5I_register(H5I_DATATYPE, attr_src->shared->dt, FALSE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register source file datatype")
if(NULL == (dt_mem = H5T_copy(attr_src->shared->dt, H5T_COPY_TRANSIENT)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy")
if((tid_mem = H5I_register(H5I_DATATYPE, dt_mem, FALSE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register memory datatype")
if((tid_dst = H5I_register(H5I_DATATYPE, attr_dst->shared->dt, FALSE)) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, NULL, "unable to register destination file datatype")
if(NULL == (tpath_src_mem = H5T_path_find(attr_src->shared->dt, dt_mem)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to convert between src and mem datatypes")
if(NULL == (tpath_mem_dst = H5T_path_find(dt_mem, attr_dst->shared->dt)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to convert between mem and dst datatypes")
if(0 == (src_dt_size = H5T_get_size(attr_src->shared->dt)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size")
if(0 == (tmp_dt_size = H5T_get_size(dt_mem)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size")
max_dt_size = MAX(src_dt_size, tmp_dt_size);
if(0 == (tmp_dt_size = H5T_get_size(attr_dst->shared->dt)))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to determine datatype size")
max_dt_size = MAX(max_dt_size, tmp_dt_size);
if(0 == (nelmts = attr_src->shared->data_size / src_dt_size))
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "element size too large")
buf_size = nelmts * max_dt_size;
buf_dim = nelmts;
if(NULL == (buf_space = H5S_create_simple((unsigned)1, &buf_dim, NULL)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, NULL, "can't create simple dataspace")
if((buf_sid = H5I_register(H5I_DATASPACE, buf_space, FALSE)) < 0) {
H5S_close(buf_space);
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, NULL, "unable to register dataspace ID")
}
if(NULL == (reclaim_buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation NULLed for raw data chunk")
if(NULL == (buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation NULLed for raw data chunk")
H5MM_memcpy(buf, attr_src->shared->data, attr_src->shared->data_size);
if(H5T_path_bkg(tpath_src_mem) || H5T_path_bkg(tpath_mem_dst))
if(NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "memory allocation failed")
if(H5T_convert(tpath_src_mem, tid_src, tid_mem, nelmts, (size_t)0, (size_t)0, buf, bkg_buf) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "datatype conversion NULLed")
H5MM_memcpy(reclaim_buf, buf, buf_size);
if(bkg_buf)
HDmemset(bkg_buf, 0, buf_size);
if(H5T_convert(tpath_mem_dst, tid_mem, tid_dst, nelmts, (size_t)0, (size_t)0, buf, bkg_buf) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "datatype conversion NULLed")
H5MM_memcpy(attr_dst->shared->data, buf, attr_dst->shared->data_size);
if(H5D_vlen_reclaim(tid_mem, buf_space, reclaim_buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_BADITER, NULL, "unable to reclaim variable-length data")
}
else {
HDassert(attr_dst->shared->data_size == attr_src->shared->data_size);
H5MM_memcpy(attr_dst->shared->data, attr_src->shared->data, attr_src->shared->data_size);
}
}
attr_dst->shared->crt_idx = attr_src->shared->crt_idx;
if(H5A__set_version(file_dst, attr_dst) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "unable to update attribute version")
if(attr_src->shared->version != attr_dst->shared->version)
*recompute_size = TRUE;
ret_value = attr_dst;
done:
if(buf_sid > 0 && H5I_dec_ref(buf_sid) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "Can't decrement temporary dataspace ID")
if(tid_src > 0)
if(NULL == H5I_remove(tid_src))
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "Can't decrement temporary datatype ID")
if(tid_dst > 0)
if(NULL == H5I_remove(tid_dst))
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "Can't decrement temporary datatype ID")
if(tid_mem > 0)
if(H5I_dec_ref(tid_mem) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "Can't decrement temporary datatype ID")
if(buf)
buf = H5FL_BLK_FREE(attr_buf, buf);
if(reclaim_buf)
reclaim_buf = H5FL_BLK_FREE(attr_buf, reclaim_buf);
if(bkg_buf)
bkg_buf = H5FL_BLK_FREE(attr_buf, bkg_buf);
if(!ret_value && attr_dst && H5A__close(attr_dst) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5A__attr_post_copy_file(const H5O_loc_t *src_oloc, const H5A_t *attr_src,
H5O_loc_t *dst_oloc, const H5A_t *attr_dst, H5O_copy_t *cpy_info)
{
H5F_t *file_src, *file_dst;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(src_oloc);
HDassert(dst_oloc);
HDassert(attr_dst);
HDassert(attr_src);
file_src = src_oloc->file;
file_dst = dst_oloc->file;
HDassert(file_src);
HDassert(file_dst);
if(H5T_committed(attr_src->shared->dt)) {
H5O_loc_t *src_oloc_dt;
H5O_loc_t *dst_oloc_dt;
src_oloc_dt = H5T_oloc(attr_src->shared->dt);
HDassert(src_oloc_dt);
dst_oloc_dt = H5T_oloc(attr_dst->shared->dt);
HDassert(dst_oloc_dt);
H5O_loc_reset(dst_oloc_dt);
dst_oloc_dt->file = file_dst;
if(H5O_copy_header_map(src_oloc_dt, dst_oloc_dt, cpy_info, FALSE, NULL, NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
H5T_update_shared(attr_dst->shared->dt);
}
if(H5SM_try_share(file_dst, NULL, H5SM_WAS_DEFERRED, H5O_DTYPE_ID, attr_dst->shared->dt, NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "can't share attribute datatype")
if(H5SM_try_share(file_dst, NULL, H5SM_WAS_DEFERRED, H5O_SDSPACE_ID, attr_dst->shared->ds, NULL) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "can't share attribute dataspace")
if((NULL != attr_dst->shared->data) && (H5T_get_class(attr_dst->shared->dt, FALSE) == H5T_REFERENCE) ) {
if(cpy_info->expand_ref) {
size_t ref_count;
ref_count = attr_dst->shared->data_size / H5T_get_size(attr_dst->shared->dt);
if(H5O_copy_expand_ref(file_src, attr_dst->shared->data, file_dst, attr_dst->shared->data, ref_count, H5T_get_ref_type(attr_dst->shared->dt), cpy_info) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy reference attribute")
}
else
HDmemset(attr_dst->shared->data, 0, attr_dst->shared->data_size);
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5A__dense_post_copy_file_cb(const H5A_t *attr_src, void *_udata)
{
H5A_dense_file_cp_ud_t *udata = (H5A_dense_file_cp_ud_t *)_udata;
H5A_t *attr_dst = NULL;
herr_t ret_value = H5_ITER_CONT;
FUNC_ENTER_STATIC
HDassert(attr_src);
HDassert(udata);
HDassert(udata->ainfo);
HDassert(udata->file);
HDassert(udata->cpy_info);
if(NULL == (attr_dst = H5A__attr_copy_file(attr_src, udata->file, udata->recompute_size, udata->cpy_info)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
if(H5A__attr_post_copy_file(udata->oloc_src, attr_src, udata->oloc_dst, attr_dst, udata->cpy_info) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
if(H5O_msg_reset_share(H5O_ATTR_ID, attr_dst) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to reset attribute sharing")
H5_BEGIN_TAG(H5AC__COPIED_TAG);
if(H5A__dense_insert(udata->file, udata->ainfo, attr_dst) < 0)
HGOTO_ERROR_TAG(H5E_OHDR, H5E_CANTINSERT, H5_ITER_ERROR, "unable to add to dense storage")
H5_END_TAG
done:
if(attr_dst && H5A__close(attr_dst) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close destination attribute")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5A__dense_post_copy_file_all(const H5O_loc_t *src_oloc, const H5O_ainfo_t *ainfo_src,
H5O_loc_t *dst_oloc, H5O_ainfo_t *ainfo_dst, H5O_copy_t *cpy_info)
{
H5A_dense_file_cp_ud_t udata;
H5A_attr_iter_op_t attr_op;
hbool_t recompute_size = FALSE;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
HDassert(ainfo_src);
HDassert(ainfo_dst);
udata.ainfo = ainfo_dst;
udata.file = dst_oloc->file;
udata.recompute_size = &recompute_size;
udata.cpy_info = cpy_info;
udata.oloc_src = src_oloc;
udata.oloc_dst = dst_oloc;
attr_op.op_type = H5A_ATTR_OP_LIB;
attr_op.u.lib_op = H5A__dense_post_copy_file_cb;
if(H5A__dense_iterate(src_oloc->file, (hid_t)0, ainfo_src, H5_INDEX_NAME,
H5_ITER_NATIVE, (hsize_t)0, NULL, &attr_op, &udata) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5A__rename_by_name(H5G_loc_t loc, const char *obj_name, const char *old_attr_name,
const char *new_attr_name)
{
H5G_loc_t obj_loc;
H5G_name_t obj_path;
H5O_loc_t obj_oloc;
hbool_t loc_found = FALSE;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
obj_loc.oloc = &obj_oloc;
obj_loc.path = &obj_path;
H5G_loc_reset(&obj_loc);
if(H5G_loc_find(&loc, obj_name, &obj_loc) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found")
loc_found = TRUE;
if(H5O__attr_rename(obj_loc.oloc, old_attr_name, new_attr_name) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute")
done:
if(loc_found && H5G_loc_free(&obj_loc) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location")
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5A__iterate_common(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t order,
hsize_t *idx, H5A_attr_iter_op_t *attr_op, void *op_data)
{
hsize_t start_idx;
hsize_t last_attr;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC_NOERR
last_attr = start_idx = (idx ? *idx : 0);
if((ret_value = H5O__attr_iterate(loc_id, idx_type, order, start_idx, &last_attr, attr_op, op_data)) < 0)
HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes");
if(idx)
*idx = last_attr;
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5A__iterate(hid_t loc_id, H5_index_t idx_type, H5_iter_order_t order,
hsize_t *idx, H5A_operator2_t op, void *op_data)
{
H5A_attr_iter_op_t attr_op;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
attr_op.op_type = H5A_ATTR_OP_APP2;
attr_op.u.app_op2 = op;
if((ret_value = H5A__iterate_common(loc_id, idx_type, order, idx, &attr_op, op_data)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error iterating over attributes")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
#ifndef H5_NO_DEPRECATED_SYMBOLS
herr_t
H5A__iterate_old(hid_t loc_id, unsigned *attr_num, H5A_operator1_t op,
void *op_data)
{
H5A_attr_iter_op_t attr_op;
hsize_t idx;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
attr_op.op_type = H5A_ATTR_OP_APP;
attr_op.u.app_op = op;
idx = (hsize_t)(attr_num ? *attr_num : 0);
if((ret_value = H5A__iterate_common(loc_id, H5_INDEX_CRT_ORDER, H5_ITER_INC, &idx, &attr_op, op_data)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error iterating over attributes")
if(attr_num)
*attr_num = (unsigned)idx;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
#endif
herr_t
H5A__iterate_by_name(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t *idx, H5A_operator2_t op,
void *op_data)
{
H5G_loc_t obj_loc;
H5G_name_t obj_path;
H5O_loc_t obj_oloc;
hbool_t loc_found = FALSE;
hid_t obj_loc_id = (-1);
H5A_attr_iter_op_t attr_op;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
obj_loc.oloc = &obj_oloc;
obj_loc.path = &obj_path;
H5G_loc_reset(&obj_loc);
if(H5G_loc_find(loc, obj_name, &obj_loc) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found")
loc_found = TRUE;
if((obj_loc_id = H5O__open_by_loc(&obj_loc, TRUE)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open object")
attr_op.op_type = H5A_ATTR_OP_APP2;
attr_op.u.app_op2 = op;
if((ret_value = H5A__iterate_common(obj_loc_id, idx_type, order, idx, &attr_op, op_data)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error iterating over attributes")
done:
if(obj_loc_id > 0) {
if(H5I_dec_app_ref(obj_loc_id) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object")
}
else if(loc_found && H5G_loc_free(&obj_loc) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5A__delete_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr_name)
{
H5G_loc_t obj_loc;
H5G_name_t obj_path;
H5O_loc_t obj_oloc;
hbool_t loc_found = FALSE;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
obj_loc.oloc = &obj_oloc;
obj_loc.path = &obj_path;
H5G_loc_reset(&obj_loc);
if(H5G_loc_find(loc, obj_name, &obj_loc) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found")
loc_found = TRUE;
if(H5O__attr_remove(obj_loc.oloc, attr_name) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute")
done:
if(loc_found && H5G_loc_free(&obj_loc) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location")
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5A__delete_by_idx(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type,
H5_iter_order_t order, hsize_t n)
{
H5G_loc_t obj_loc;
H5G_name_t obj_path;
H5O_loc_t obj_oloc;
hbool_t loc_found = FALSE;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
obj_loc.oloc = &obj_oloc;
obj_loc.path = &obj_path;
H5G_loc_reset(&obj_loc);
if(H5G_loc_find(loc, obj_name, &obj_loc) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found")
loc_found = TRUE;
if(H5O__attr_remove_by_idx(obj_loc.oloc, idx_type, order, n) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute")
done:
if(loc_found && H5G_loc_free(&obj_loc) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location")
FUNC_LEAVE_NOAPI(ret_value)
}