summaryrefslogtreecommitdiffstats
path: root/src/H5Aint.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Aint.c')
-rw-r--r--src/H5Aint.c511
1 files changed, 511 insertions, 0 deletions
diff --git a/src/H5Aint.c b/src/H5Aint.c
new file mode 100644
index 0000000..1d6e9ab
--- /dev/null
+++ b/src/H5Aint.c
@@ -0,0 +1,511 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Aint.c
+ * Dec 18 2006
+ * Quincey Koziol <koziol@hdfgroup.org>
+ *
+ * Purpose: Internal routines for managing attributes.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5A_PACKAGE /*suppress error about including H5Apkg */
+#define H5O_PACKAGE /*suppress error about including H5Opkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Apkg.h" /* Attributes */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Opkg.h" /* Object headers */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/* Data exchange structure to use when building table of compact attributes for an object */
+typedef struct {
+ H5F_t *f; /* Pointer to file that fractal heap is in */
+ hid_t dxpl_id; /* DXPL for operation */
+ H5A_attr_table_t *atable; /* Pointer to attribute table to build */
+ size_t curr_attr; /* Current attribute to operate on */
+} H5A_compact_bt_ud_t;
+
+/* Data exchange structure to use when building table of dense attributes for an object */
+typedef struct {
+ H5A_attr_table_t *atable; /* Pointer to attribute table to build */
+ size_t curr_attr; /* Current attribute to operate on */
+} H5A_dense_bt_ud_t;
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static herr_t H5A_compact_build_table_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
+ unsigned sequence, unsigned *oh_flags_ptr, void *_udata/*in,out*/);
+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 herr_t H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type,
+ H5_iter_order_t order);
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_compact_build_table_cb
+ *
+ * Purpose: Object header iterator callback routine to copy attribute
+ * into table.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 18 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_compact_build_table_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/,
+ unsigned UNUSED sequence, unsigned UNUSED *oh_flags_ptr, void *_udata/*in,out*/)
+{
+ H5A_compact_bt_ud_t *udata = (H5A_compact_bt_ud_t *)_udata; /* Operator user data */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_compact_build_table_cb)
+
+ /* check args */
+ HDassert(mesg);
+
+ /* Check for re-allocating table */
+ if(udata->curr_attr == udata->atable->nattrs) {
+ size_t n = MAX(1, 2 * udata->atable->nattrs);
+ H5A_t *table = H5MM_realloc(udata->atable->attrs,
+ n * sizeof(H5A_t));
+
+ if(!table)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "unable to extend attribute table")
+ udata->atable->attrs = table;
+ udata->atable->nattrs = n;
+ } /* end if */
+
+ /* Check for shared message */
+ if(mesg->flags & H5O_MSG_FLAG_SHARED) {
+ /*
+ * If the message is shared then then the native pointer points to an
+ * H5O_MSG_SHARED message. We use that information to look up the real
+ * message in the global heap or some other object header.
+ */
+ if(NULL == H5O_shared_read(udata->f, udata->dxpl_id, mesg->native, H5O_MSG_ATTR, &udata->atable->attrs[udata->curr_attr]))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "unable to read shared attribute")
+ } /* end if */
+ else {
+ if(NULL == H5A_copy(&udata->atable->attrs[udata->curr_attr], mesg->native))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
+ } /* end else */
+
+ /* Increment current attribute */
+ udata->curr_attr++;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_compact_build_table_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_compact_build_table
+ *
+ * Purpose: Builds a table containing a sorted list of attributes for
+ * an object
+ *
+ * Note: Used for building table of attributes in non-native iteration
+ * order for an index
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Dec 18, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_compact_build_table(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
+ H5_index_t UNUSED idx_type, H5_iter_order_t order,
+ H5A_attr_table_t *atable, unsigned *oh_flags)
+{
+ H5A_compact_bt_ud_t udata; /* User data for iteration callback */
+ H5O_mesg_operator_t op; /* Wrapper for operator */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_compact_build_table)
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(oh);
+ HDassert(atable);
+
+ /* Initialize table */
+ atable->attrs = NULL;
+ atable->nattrs = 0;
+
+ /* Set up user data for iteration */
+ udata.f = f;
+ udata.dxpl_id = dxpl_id;
+ udata.atable = atable;
+ udata.curr_attr = 0;
+
+ /* Iterate over existing attributes, checking for attribute with same name */
+ op.lib_op = H5A_compact_build_table_cb;
+ if(H5O_msg_iterate_real(f, oh, H5O_MSG_ATTR, TRUE, op, &udata, dxpl_id, oh_flags) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error building attribute table")
+
+ /* Correct # of attributes in table */
+ atable->nattrs = udata.curr_attr;
+
+ /* Sort attribute table in correct iteration order */
+ if(H5A_attr_sort_table(atable, H5_INDEX_NAME, order) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTSORT, FAIL, "error sorting attribute table")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_compact_build_table() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_build_table_cb
+ *
+ * Purpose: Callback routine for building table of attributes from dense
+ * attribute storage.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 11 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+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; /* 'User data' passed in */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_build_table_cb)
+
+ /* check arguments */
+ HDassert(attr);
+ HDassert(udata);
+ HDassert(udata->curr_attr < udata->atable->nattrs);
+
+ /* Copy attribute information */
+ if(NULL == H5A_copy(&udata->atable->attrs[udata->curr_attr], attr))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
+
+ /* Increment number of attributes stored */
+ udata->curr_attr++;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_build_table_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_dense_build_table
+ *
+ * Purpose: Builds a table containing a sorted list of attributes for
+ * an object
+ *
+ * Note: Used for building table of attributes in non-native iteration
+ * order for an index
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Dec 11, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_dense_build_table(H5F_t *f, hid_t dxpl_id, hsize_t nattrs, haddr_t attr_fheap_addr,
+ haddr_t name_bt2_addr, H5_index_t UNUSED idx_type, H5_iter_order_t order,
+ H5A_attr_table_t *atable)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_dense_build_table)
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(H5F_addr_defined(attr_fheap_addr));
+ HDassert(H5F_addr_defined(name_bt2_addr));
+ HDassert(atable);
+
+ /* Set size of table */
+ H5_CHECK_OVERFLOW(nattrs, /* From: */ hsize_t, /* To: */ size_t);
+ atable->nattrs = (size_t)nattrs;
+
+ /* Allocate space for the table entries */
+ if(atable->nattrs > 0) {
+ H5A_dense_bt_ud_t udata; /* User data for iteration callback */
+ H5A_attr_iter_op_t attr_op; /* Attribute operator */
+
+ /* Allocate the table to store the attributes */
+ if((atable->attrs = H5MM_malloc(sizeof(H5A_t) * atable->nattrs)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Set up user data for iteration */
+ udata.atable = atable;
+ udata.curr_attr = 0;
+
+ /* Build iterator operator */
+ attr_op.op_type = H5A_ATTR_OP_LIB;
+ attr_op.u.lib_op = H5A_dense_build_table_cb;
+
+ /* Iterate over the links in the group, building a table of the link messages */
+ if(H5A_dense_iterate(f, dxpl_id, (hid_t)0, attr_fheap_addr, name_bt2_addr,
+ H5_ITER_NATIVE, (unsigned)0, NULL, &attr_op, &udata) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")
+
+ /* Sort attribute table in correct iteration order */
+ if(H5A_attr_sort_table(atable, H5_INDEX_NAME, order) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTSORT, FAIL, "error sorting attribute table")
+ } /* end if */
+ else
+ atable->attrs = NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_dense_build_table() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_attr_cmp_name_inc
+ *
+ * Purpose: Callback routine for comparing two attribute names, in
+ * increasing alphabetic order
+ *
+ * Return: An integer less than, equal to, or greater than zero if the
+ * first argument is considered to be respectively less than,
+ * equal to, or greater than the second. If two members compare
+ * as equal, their order in the sorted array is undefined.
+ * (i.e. same as strcmp())
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Dec 11 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5A_attr_cmp_name_inc(const void *attr1, const void *attr2)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_cmp_name_inc)
+
+ FUNC_LEAVE_NOAPI(HDstrcmp(((const H5A_t *)attr1)->name, ((const H5A_t *)attr2)->name))
+} /* end H5A_attr_cmp_name_inc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_attr_sort_table
+ *
+ * Purpose: Sort table containing a list of attributes for an object
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Dec 11, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5A_attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type,
+ H5_iter_order_t order)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5A_attr_sort_table)
+
+ /* Sanity check */
+ HDassert(atable);
+
+ /* Pick appropriate comparison routine */
+#ifdef NOT_YET
+ if(idx_type == H5_INDEX_NAME) {
+#else /* NOT_YET */
+HDassert(idx_type == H5_INDEX_NAME);
+#endif /* NOT_YET */
+ if(order == H5_ITER_INC)
+ HDqsort(atable->attrs, atable->nattrs, sizeof(H5A_t), H5A_attr_cmp_name_inc);
+#ifdef NOT_YET
+ else if(order == H5_ITER_DEC)
+ HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_link_cmp_name_dec);
+#endif /* NOT_YET */
+ else
+ HDassert(order == H5_ITER_NATIVE);
+#ifdef NOT_YET
+ } /* end if */
+ else {
+ HDassert(idx_type == H5_INDEX_CRT_ORDER);
+ if(order == H5_ITER_INC)
+ HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_link_cmp_corder_inc);
+ else if(order == H5_ITER_DEC)
+ HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_link_cmp_corder_dec);
+ else
+ HDassert(order == H5_ITER_NATIVE);
+ } /* end else */
+#endif /* NOT_YET */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5A_attr_sort_table() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_attr_iterate_table
+ *
+ * Purpose: Iterate over table containing a list of attributes for an object,
+ * making appropriate callbacks
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Dec 18, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_attr_iterate_table(const H5A_attr_table_t *atable, unsigned skip,
+ unsigned *last_attr, hid_t loc_id, const H5A_attr_iter_op_t *attr_op,
+ void *op_data)
+{
+ size_t u; /* Local index variable */
+ herr_t ret_value = H5_ITER_CONT; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5A_attr_iterate_table, FAIL)
+
+ /* Sanity check */
+ HDassert(atable);
+ HDassert(attr_op);
+
+ /* Skip over attributes, if requested */
+ if(last_attr)
+ *last_attr = skip;
+
+ /* Iterate over attribute messages */
+ H5_ASSIGN_OVERFLOW(/* To: */ u, /* From: */ skip, /* From: */ unsigned, /* To: */ size_t)
+ for(; u < atable->nattrs && !ret_value; u++) {
+ /* Check which type of callback to make */
+ switch(attr_op->op_type) {
+ case H5A_ATTR_OP_APP:
+ /* Make the application callback */
+ ret_value = (attr_op->u.app_op)(loc_id, atable->attrs[u].name, op_data);
+ break;
+
+ case H5A_ATTR_OP_LIB:
+ /* Call the library's callback */
+ ret_value = (attr_op->u.lib_op)(&(atable->attrs[u]), op_data);
+ } /* end switch */
+
+ /* Increment the number of entries passed through */
+ if(last_attr)
+ (*last_attr)++;
+ } /* end for */
+
+ /* Check for callback failure and pass along return value */
+ if(ret_value < 0)
+ HERROR(H5E_ATTR, H5E_CANTNEXT, "iteration operator failed");
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_attr_iterate_table() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_attr_release_table
+ *
+ * Purpose: Release table containing a list of attributes for an object
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Dec 11, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_attr_release_table(H5A_attr_table_t *atable)
+{
+ size_t u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5A_attr_release_table)
+
+ /* Sanity check */
+ HDassert(atable);
+
+ /* Release attribute info, if any */
+ if(atable->nattrs > 0) {
+ /* Free attribute message information */
+ for(u = 0; u < atable->nattrs; u++)
+ if(H5A_free(&(atable->attrs[u])) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute")
+
+ /* Free table of attributes */
+ H5MM_xfree(atable->attrs);
+ } /* end if */
+ else
+ HDassert(atable->attrs == NULL);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_attr_release_table() */
+