summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>1998-04-23 22:24:38 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>1998-04-23 22:24:38 (GMT)
commitca0a7c164e2e492d5c48d066bacf83a92e675c2e (patch)
tree37c5124c23ceddf677e9e6516e0dde696152655c
parenteba569241e9675494bcc7df4d0005b4a75a1d82d (diff)
downloadhdf5-ca0a7c164e2e492d5c48d066bacf83a92e675c2e.zip
hdf5-ca0a7c164e2e492d5c48d066bacf83a92e675c2e.tar.gz
hdf5-ca0a7c164e2e492d5c48d066bacf83a92e675c2e.tar.bz2
[svn-r361] Added Attribute (H5A) code.
-rw-r--r--src/H5A.c1330
-rw-r--r--src/H5Apkg.h46
-rw-r--r--src/H5Aprivate.h30
-rw-r--r--src/H5Apublic.h47
-rw-r--r--src/H5D.c15
-rw-r--r--src/H5Dpkg.h40
-rw-r--r--src/H5Epublic.h2
-rw-r--r--src/H5Iprivate.h1
-rw-r--r--src/H5Ipublic.h1
-rw-r--r--src/H5O.c4
-rw-r--r--src/H5Oattr.c560
-rw-r--r--src/H5Oprivate.h8
-rw-r--r--src/H5Osdspace.c2
-rw-r--r--src/H5S.c35
-rw-r--r--src/H5Sprivate.h1
-rw-r--r--src/H5T.c4
-rw-r--r--src/H5Tpublic.h2
-rw-r--r--src/H5public.h1
-rw-r--r--src/Makefile.in29
-rw-r--r--src/hdf5.h3
20 files changed, 2124 insertions, 37 deletions
diff --git a/src/H5A.c b/src/H5A.c
new file mode 100644
index 0000000..342dd5f
--- /dev/null
+++ b/src/H5A.c
@@ -0,0 +1,1330 @@
+/****************************************************************************
+* NCSA HDF *
+* Software Development Group *
+* National Center for Supercomputing Applications *
+* University of Illinois at Urbana-Champaign *
+* 605 E. Springfield, Champaign IL 61820 *
+* *
+* For conditions of distribution and use, see the accompanying *
+* hdf/COPYING file. *
+* *
+****************************************************************************/
+
+#ifdef RCSID
+static char RcsId[] = "$Revision$";
+#endif
+
+/* $Id$ */
+
+#define H5A_PACKAGE /*suppress error about including H5Apkg */
+#define H5D_PACKAGE /*suppress error about including H5Dpkg */
+#define H5T_PACKAGE /*suppress error about including H5Tpkg */
+#define H5G_PACKAGE /*suppress error about including H5Gpkg */
+
+/* Private header files */
+#include <H5private.h> /* Generic Functions */
+#include <H5Iprivate.h> /* IDs */
+#include <H5Bprivate.h> /* B-tree subclass names */
+#include <H5Dpkg.h> /* Datasets */
+#include <H5Gpkg.h> /* Groups */
+#include <H5Tpkg.h> /* Datatypes */
+#include <H5Eprivate.h> /* Error handling */
+#include <H5MMprivate.h> /* Memory management */
+#include <H5Pprivate.h> /* Property lists */
+#include <H5Oprivate.h> /* Object Headers */
+#include <H5Apkg.h> /* Attributes */
+
+#define PABLO_MASK H5A_mask
+
+/* Is the interface initialized? */
+static hbool_t interface_initialize_g = FALSE;
+#define INTERFACE_INIT H5A_init_interface
+static herr_t H5A_init_interface(void);
+
+/* PRIVATE PROTOTYPES */
+static void H5A_term_interface(void);
+static hid_t H5A_create(const H5G_entry_t *ent, const char *name, const H5T_t *type, const H5S_t *space);
+static hid_t H5A_open(H5G_entry_t *ent, unsigned idx);
+static herr_t H5A_write(H5A_t *attr, const H5T_t *mem_type, void *buf);
+static herr_t H5A_read(H5A_t *attr, const H5T_t *mem_type, void *buf);
+static int H5A_get_index(H5G_entry_t *ent, const char *name);
+
+
+/*--------------------------------------------------------------------------
+NAME
+ H5A_init_interface -- Initialize interface-specific information
+USAGE
+ herr_t H5A_init_interface()
+
+RETURNS
+ SUCCEED/FAIL
+DESCRIPTION
+ Initializes any interface-specific data or routines.
+
+--------------------------------------------------------------------------*/
+static herr_t
+H5A_init_interface(void)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5A_init_interface, FAIL);
+
+ /*
+ * Register cleanup function.
+ */
+ if ((ret_value = H5I_init_group(H5_ATTR, H5I_ATTRID_HASHSIZE,
+ H5A_RESERVED_ATOMS,
+ (herr_t (*)(void *)) H5A_close)) == FAIL) {
+ HRETURN_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL,
+ "unable to initialize attribute group");
+ }
+
+ if (H5_add_exit(H5A_term_interface) < 0) {
+ HRETURN_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL,
+ "unable to install atexit function");
+ }
+
+ FUNC_LEAVE(ret_value);
+}
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5A_term_interface
+ PURPOSE
+ Terminate various H5A objects
+ USAGE
+ void H5A_term_interface()
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ Release any other resources allocated.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Can't report errors...
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static void
+H5A_term_interface(void)
+{
+}
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Acreate
+ PURPOSE
+ Creates a dataset as an attribute of another dataset or group
+ USAGE
+ hid_t H5Acreate (loc_id, name, datatype, dataspace, create_plist)
+ hid_t loc_id; IN: Object (dataset or group) to be attached to
+ const char *name; IN: Name of attribute to create
+ hid_t datatype; IN: ID of datatype for attribute
+ hid_t dataspace; IN: ID of dataspace for attribute
+ hid_t create_plist; IN: ID of creation property list (currently not used)
+ RETURNS
+ SUCCEED/FAIL
+
+ ERRORS
+
+ DESCRIPTION
+ This function creates an attribute which is attached to the object
+ specified with 'location_id'. The name specified with 'name' for each
+ attribute for an object must be unique for that object. The 'type_id'
+ and 'space_id' are created with the H5T and H5S interfaces respectively.
+ Currently only simple dataspaces are allowed for attribute dataspaces.
+ The 'create_plist_id' property list is currently un-used, but will be
+ used int the future for optional properties of attributes. The attribute
+ ID returned from this function must be released with H5Aclose or resource
+ leaks will develop.
+ The link created (see H5G API documentation for more information on
+ link types) is a hard link, so the attribute may be shared among datasets
+ and will not be removed from the file until the reference count for the
+ attribute is reduced to zero.
+ The location object may be either a group or a dataset, both of
+ which may have any sort of attribute.
+--------------------------------------------------------------------------*/
+hid_t
+H5Acreate(hid_t loc_id, const char *name, hid_t datatype, hid_t dataspace,
+ hid_t create_plist)
+{
+ void *obj = NULL;
+ H5G_entry_t *ent = NULL;
+ H5T_t *type = NULL;
+ H5S_t *space = NULL;
+ const H5D_create_t *create_parms = NULL;
+ hid_t ret_value = FAIL;
+
+ FUNC_ENTER(H5Acreate, FAIL);
+
+ /* check arguments */
+ if (!(H5_DATASET != H5I_group(loc_id) || H5_GROUP != H5I_group(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "attribute target not a dataset or group");
+ }
+ if (!name || !*name) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name");
+ }
+ if (H5_DATATYPE != H5I_group(datatype) ||
+ NULL == (type = H5I_object(datatype))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a type");
+ }
+ if (H5_DATASPACE != H5I_group(dataspace) ||
+ NULL == (space = H5I_object(dataspace))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space");
+ }
+ if (create_plist >= 0) {
+ if (H5P_DATASET_CREATE != H5Pget_class(create_plist) ||
+ NULL == (create_parms = H5I_object(create_plist))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL,
+ "not a dataset creation property list");
+ }
+ } else {
+ create_parms = &H5D_create_dflt;
+ }
+
+ /* Get the dataset or group's pointer */
+ if(NULL == (obj = H5I_object(loc_id)))
+ HRETURN_ERROR(H5E_ARGS, H5E_BADATOM, FAIL, "illegal object atom");
+ if (H5_DATASET == H5I_group(loc_id))
+ ent=&(((H5D_t *)obj)->ent);
+ else
+ ent=&(((H5G_t *)obj)->ent);
+
+ /* Go do the real work for attaching the attribute to the dataset */
+ ret_value=H5A_create(ent,name,type,space);
+
+ FUNC_LEAVE(ret_value);
+} /* H5Acreate() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_create
+ *
+ * Purpose:
+ * This is the guts of the H5Acreate function.
+ * Usage:
+ * hid_t H5A_create (ent, name, type, space)
+ * const H5G_entry_t *ent; IN: Pointer to symbol table entry for object to attribute
+ * const char *name; IN: Name of attribute
+ * H5T_t *type; IN: Datatype of attribute
+ * H5S_t *space; IN: Dataspace of attribute
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * April 2, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static hid_t
+H5A_create(const H5G_entry_t *ent, const char *name, const H5T_t *type, const H5S_t *space)
+{
+ H5A_t *attr = NULL;
+ H5A_t *found_attr = NULL;
+ intn seq=0;
+ hid_t ret_value = FAIL;
+
+ FUNC_ENTER(H5A_create, FAIL);
+
+ /* check args */
+ assert(ent);
+ assert(name);
+ assert(type);
+ assert(space);
+
+ /* Build the attribute information */
+ if((attr = H5MM_xcalloc(1, sizeof(H5A_t)))==NULL)
+ HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "unable to allocate space for attribute info");
+ attr->name=HDstrdup(name);
+ attr->dt=H5T_copy(type);
+ attr->ds=H5S_copy(space);
+
+ /* Copy the symbol table entry */
+ attr->ent=*ent;
+
+ /* Compute the internal sizes */
+ attr->dt_size=(H5O_DTYPE[0].raw_size)(attr->ent.file,type);
+ attr->ds_size=(H5O_SDSPACE[0].raw_size)(attr->ent.file,&(space->u.simple));
+ attr->data_size=H5S_get_npoints(space)*H5T_get_size(type);
+
+ /* Hold the symbol table entry (and file) open */
+ if (H5O_open(&(attr->ent)) < 0) {
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to open");
+ }
+ attr->ent_opened=1;
+
+ /* Read in the existing attributes to check for duplicates */
+ seq=0;
+ while((found_attr=H5O_read(&(attr->ent), H5O_ATTR, seq, NULL))!=NULL)
+ {
+ /* Compare found attribute name to new attribute name reject creation if names are the same */
+ if(HDstrcmp(found_attr->name,attr->name)==0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCREATE, FAIL,
+ "attribute already exists");
+ seq++;
+ } /* end while */
+
+ /* Create the attribute message and save the attribute index */
+ if (H5O_modify(&(attr->ent), H5O_ATTR, H5O_NEW_MESG, 0, attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL,
+ "can't update attribute header messages");
+
+ /* Register the new attribute and get an ID for it */
+ if ((ret_value = H5I_register(H5_ATTR, attr)) < 0) {
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL,
+ "unable to register attribute for ID");
+ }
+
+done:
+ if (ret_value < 0) {
+ if(attr)
+ H5A_close(attr);
+ }
+
+ FUNC_LEAVE(ret_value);
+} /* H5A_create() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5A_get_index
+ PURPOSE
+ Determine the index of an attribute in an object header
+ USAGE
+ int H5A_get_index (ent, name)
+ H5G_entry_t *ent; IN: Symbol table entry of object
+ const char *name; IN: Name of dataset to find
+ RETURNS
+ non-negative on success, negative on failure
+
+ ERRORS
+
+ DESCRIPTION
+ This function determines the index of the attribute within an object
+ header. This is not stored in the attribute structure because it is only
+ a subjective measure and can change if attributes are deleted from the
+ object header.
+--------------------------------------------------------------------------*/
+static int
+H5A_get_index(H5G_entry_t *ent, const char *name)
+{
+ H5A_t *found_attr = NULL;
+ int ret_value = FAIL;
+
+ FUNC_ENTER(H5A_get_index, FAIL);
+
+ assert(ent);
+ assert(name);
+
+ /* Look up the attribute for the object */
+ ret_value=0;
+ while((found_attr=H5O_read(ent, H5O_ATTR, ret_value, NULL))!=NULL)
+ {
+ /* Compare found attribute name to new attribute name reject creation if names are the same */
+ if(HDstrcmp(found_attr->name,name)==0)
+ break;
+ ret_value++;
+ } /* end while */
+ if(found_attr==NULL) {
+ HRETURN_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL,
+ "attribute not found");
+ }
+
+ FUNC_LEAVE(ret_value);
+} /* H5A_get_index() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Aopen_name
+ PURPOSE
+ Opens an attribute for an object by looking up the attribute name
+ USAGE
+ hid_t H5Aopen_name (loc_id, name)
+ hid_t loc_id; IN: Object (dataset or group) to be attached to
+ const char *name; IN: Name of attribute to locate and open
+ RETURNS
+ ID of attribute on success, negative on failure
+
+ ERRORS
+
+ DESCRIPTION
+ This function opens an existing attribute for access. The attribute
+ name specified is used to look up the corresponding attribute for the
+ object. The attribute ID returned from this function must be released with
+ H5Aclose or resource leaks will develop.
+ The location object may be either a group or a dataset, both of
+ which may have any sort of attribute.
+--------------------------------------------------------------------------*/
+hid_t
+H5Aopen_name(hid_t loc_id, const char *name)
+{
+ H5G_entry_t *ent = NULL; /* Symbol table entry of object to attribute */
+ void *obj = NULL;
+ intn idx=0;
+ hid_t ret_value = FAIL;
+
+ FUNC_ENTER(H5Aopen_name, FAIL);
+
+ /* check arguments */
+ if (!(H5_DATASET != H5I_group(loc_id) || H5_GROUP != H5I_group(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "attribute target not a dataset or group");
+ }
+ if (!name || !*name) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name");
+ }
+
+ /* Get the dataset or group's pointer */
+ if(NULL == (obj = H5I_object(loc_id)))
+ HRETURN_ERROR(H5E_ARGS, H5E_BADATOM, FAIL, "illegal object atom");
+
+ /* Copy the object header entry for the object */
+ if (H5_DATASET == H5I_group(loc_id))
+ ent=&(((H5D_t *)obj)->ent);
+ else
+ ent=&(((H5G_t *)obj)->ent);
+
+ /* Look up the attribute for the object */
+ if((idx=H5A_get_index(ent,name))<0)
+ HRETURN_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "attribute not found");
+
+ /* Go do the real work for opening the attribute */
+ ret_value=H5A_open(ent, (unsigned)idx);
+
+ FUNC_LEAVE(ret_value);
+} /* H5Aopen_name() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Aopen_idx
+ PURPOSE
+ Opens the n'th attribute for an object
+ USAGE
+ hid_t H5Aopen_idx (loc_id, idx)
+ hid_t loc_id; IN: Object (dataset or group) to be attached to
+ unsigned idx; IN: Index (0-based) attribute to open
+ RETURNS
+ ID of attribute on success, negative on failure
+
+ ERRORS
+
+ DESCRIPTION
+ This function opens an existing attribute for access. The attribute
+ index specified is used to look up the corresponding attribute for the
+ object. The attribute ID returned from this function must be released with
+ H5Aclose or resource leaks will develop.
+ The location object may be either a group or a dataset, both of
+ which may have any sort of attribute.
+--------------------------------------------------------------------------*/
+hid_t
+H5Aopen_idx(hid_t loc_id, unsigned idx)
+{
+ H5G_entry_t *ent = NULL; /* Symbol table entry of object to attribute */
+ void *obj = NULL;
+ hid_t ret_value = FAIL;
+
+ FUNC_ENTER(H5Aopen_idx, FAIL);
+
+ /* check arguments */
+ if (!(H5_DATASET != H5I_group(loc_id) || H5_GROUP != H5I_group(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "attribute target not a dataset or group");
+ }
+
+ /* Get the dataset or group's pointer */
+ if(NULL == (obj = H5I_object(loc_id)))
+ HRETURN_ERROR(H5E_ARGS, H5E_BADATOM, FAIL, "illegal object atom");
+
+ /* Copy the object header entry for the object */
+ if (H5_DATASET == H5I_group(loc_id))
+ ent=&(((H5D_t *)obj)->ent);
+ else
+ ent=&(((H5G_t *)obj)->ent);
+
+ /* Go do the real work for opening the attribute */
+ ret_value=H5A_open(ent, idx);
+
+ FUNC_LEAVE(ret_value);
+} /* H5Aopen_idx() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_open
+ *
+ * Purpose:
+ * This is the guts of the H5Aopen_xxx functions
+ * Usage:
+ * herr_t H5A_open (ent, idx)
+ * const H5G_entry_t *ent; IN: Pointer to symbol table entry for object to attribute
+ * unsigned idx; IN: index of attribute to open (0-based)
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * April 2, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static hid_t
+H5A_open(H5G_entry_t *ent, unsigned idx)
+{
+ H5A_t *attr = NULL;
+ hid_t ret_value = FAIL;
+
+ FUNC_ENTER(H5A_open, FAIL);
+
+ /* check args */
+ assert(ent);
+
+ /* Build the attribute information */
+ if((attr = H5MM_xcalloc(1, sizeof(H5A_t)))==NULL)
+ HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
+ "unable to allocate space for attribute info");
+
+ /* Read in attribute with H5O_read() */
+ if (NULL==(H5O_read(ent, H5O_ATTR, idx, attr))) {
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL,
+ "unable to load attribute info from dataset header");
+ }
+
+ /* Copy the symbol table entry */
+ attr->ent=*ent;
+
+ /* Hold the symbol table entry (and file) open */
+ if (H5O_open(&(attr->ent)) < 0) {
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open");
+ }
+ attr->ent_opened=1;
+
+ /* Register the new attribute and get an ID for it */
+ if ((ret_value = H5I_register(H5_ATTR, attr)) < 0) {
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL,
+ "unable to register attribute for ID");
+ }
+
+done:
+ if (ret_value < 0) {
+ if(attr)
+ H5A_close(attr);
+ }
+
+ FUNC_LEAVE(ret_value);
+} /* H5A_open() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Awrite
+ PURPOSE
+ Write out data to an attribute
+ USAGE
+ herr_t H5Awrite (attr_id, mem_dt, buf)
+ hid_t attr_id; IN: Attribute to write
+ hid_t mem_dt; IN: Memory datatype of buffer
+ void *buf; IN: Buffer of data to write
+ RETURNS
+ SUCCEED/FAIL
+
+ ERRORS
+
+ DESCRIPTION
+ This function writes a complete attribute to disk.
+--------------------------------------------------------------------------*/
+herr_t
+H5Awrite(hid_t attr_id, hid_t mem_dt, void *buf)
+{
+ H5A_t *attr = NULL;
+ const H5T_t *mem_type = NULL;
+ herr_t ret_value = FAIL;
+
+ FUNC_ENTER(H5Awrite, FAIL);
+
+ /* check arguments */
+ if (H5_ATTR != H5I_group(attr_id) ||
+ (NULL == (attr = H5I_object(attr_id)))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute");
+ }
+ if (H5_DATATYPE != H5I_group(mem_dt) ||
+ NULL == (mem_type = H5I_object(mem_dt))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ }
+ if (NULL == buf) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null attribute buffer");
+ }
+
+ /* Go write the actual data to the attribute */
+ if ((ret_value=H5A_write(attr,mem_type,buf))<0) {
+ HRETURN_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL,
+ "can't write attribute");
+ }
+
+ FUNC_LEAVE(ret_value);
+} /* H5Awrite() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5A_write
+ PURPOSE
+ Actually write out data to an attribute
+ USAGE
+ herr_t H5A_write (attr, mem_type, buf)
+ H5A_t *attr; IN: Attribute to write
+ const H5T_t *mem_type; IN: Memory datatype of buffer
+ void *buf; IN: Buffer of data to write
+ RETURNS
+ SUCCEED/FAIL
+
+ ERRORS
+
+ DESCRIPTION
+ This function writes a complete attribute to disk.
+--------------------------------------------------------------------------*/
+static herr_t
+H5A_write(H5A_t *attr, const H5T_t *mem_type, void *buf)
+{
+ uint8 *tconv_buf = NULL; /* data type conv buffer */
+ size_t nelmts; /* elements in attribute */
+ H5T_conv_t tconv_func = NULL; /* conversion function */
+ H5T_cdata_t *cdata = NULL; /* type conversion data */
+ hid_t src_id = -1, dst_id = -1;/* temporary type atoms */
+ size_t src_type_size; /* size of source type */
+ size_t dst_type_size; /* size of destination type*/
+ size_t buf_size; /* desired buffer size */
+ int idx; /* index of attribute in object header */
+ herr_t ret_value = FAIL;
+
+ FUNC_ENTER(H5A_write, FAIL);
+
+ assert(attr);
+ assert(mem_type);
+ assert(buf);
+
+
+ /* Create buffer for data to store on disk */
+ nelmts=H5S_get_npoints (attr->ds);
+
+ /* Get the memory and file datatype sizes */
+ src_type_size = H5T_get_size(mem_type);
+ dst_type_size = H5T_get_size(attr->dt);
+
+ /* Get the maximum buffer size needed and allocate it */
+ buf_size = nelmts*MAX(src_type_size,dst_type_size);
+ tconv_buf = H5MM_xmalloc (buf_size);
+
+ /* Copy the user's data into the buffer for conversion */
+ HDmemcpy(tconv_buf,buf,src_type_size*nelmts);
+
+/* Convert memory buffer into disk buffer */
+ /* Set up type conversion function */
+ if (NULL == (tconv_func = H5T_find(mem_type, attr->dt,
+ H5T_BKG_NO, &cdata))) {
+ HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL,
+ "unable to convert between src and dest data types");
+ } else if (H5T_conv_noop!=tconv_func) {
+ if ((src_id = H5I_register(H5_DATATYPE, H5T_copy(mem_type)))<0 ||
+ (dst_id = H5I_register(H5_DATATYPE, H5T_copy(attr->dt)))<0) {
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL,
+ "unable to register types for conversion");
+ }
+ }
+
+ /* Perform data type conversion. */
+ cdata->command = H5T_CONV_CONV;
+ cdata->stats->ncalls++;
+ if ((tconv_func) (src_id, dst_id, cdata, nelmts, tconv_buf, NULL)<0) {
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL,
+ "data type conversion failed");
+ }
+
+ /* Free the previous attribute data buffer, if there is one */
+ if(attr->data)
+ H5MM_xfree(attr->data);
+
+ /* Look up the attribute for the object */
+ if((idx=H5A_get_index(&(attr->ent),attr->name))<0)
+ HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "attribute not found");
+
+ /* Modify the attribute data */
+ attr->data=tconv_buf; /* Set the data pointer temporarily */
+ if (H5O_modify(&(attr->ent), H5O_ATTR, idx, 0, attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL,
+ "can't update attribute header messages");
+ attr->data=NULL; /* un-do the data pointer */
+
+ /* Indicate the the attribute doesn't need fill-values */
+ attr->initialized=TRUE;
+
+ ret_value=SUCCEED;
+
+done:
+ /* Release resources */
+ if (src_id >= 0)
+ H5I_dec_ref(src_id);
+ if (dst_id >= 0)
+ H5I_dec_ref(dst_id);
+ if (tconv_buf)
+ H5MM_xfree(tconv_buf);
+
+ FUNC_LEAVE(ret_value);
+} /* H5A_write() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Aread
+ PURPOSE
+ Read in data from an attribute
+ USAGE
+ herr_t H5Aread (attr_id, mem_dt, buf)
+ hid_t attr_id; IN: Attribute to read
+ hid_t mem_dt; IN: Memory datatype of buffer
+ void *buf; IN: Buffer for data to read
+ RETURNS
+ SUCCEED/FAIL
+
+ ERRORS
+
+ DESCRIPTION
+ This function reads a complete attribute from disk.
+--------------------------------------------------------------------------*/
+herr_t
+H5Aread(hid_t attr_id, hid_t mem_dt, void *buf)
+{
+ H5A_t *attr = NULL;
+ const H5T_t *mem_type = NULL;
+ herr_t ret_value = FAIL;
+
+ FUNC_ENTER(H5Aread, FAIL);
+
+ /* check arguments */
+ if (H5_ATTR != H5I_group(attr_id) ||
+ (NULL == (attr = H5I_object(attr_id)))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute");
+ }
+ if (H5_DATATYPE != H5I_group(mem_dt) ||
+ NULL == (mem_type = H5I_object(mem_dt))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
+ }
+ if (NULL == buf) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null attribute buffer");
+ }
+
+ /* Go write the actual data to the attribute */
+ if ((ret_value=H5A_read(attr,mem_type,buf))<0) {
+ HRETURN_ERROR(H5E_ATTR, H5E_READERROR, FAIL,
+ "can't read attribute");
+ }
+
+ FUNC_LEAVE(ret_value);
+} /* H5Aread() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5A_read
+ PURPOSE
+ Actually read in data from an attribute
+ USAGE
+ herr_t H5A_read (attr, mem_type, buf)
+ H5A_t *attr; IN: Attribute to read
+ const H5T_t *mem_type; IN: Memory datatype of buffer
+ void *buf; IN: Buffer for data to read
+ RETURNS
+ SUCCEED/FAIL
+
+ ERRORS
+
+ DESCRIPTION
+ This function read a complete attribute to disk.
+--------------------------------------------------------------------------*/
+static herr_t
+H5A_read(H5A_t *attr, const H5T_t *mem_type, void *buf)
+{
+ uint8 *tconv_buf = NULL; /* data type conv buffer */
+ size_t nelmts; /* elements in attribute */
+ H5T_conv_t tconv_func = NULL; /* conversion function */
+ H5T_cdata_t *cdata = NULL; /* type conversion data */
+ hid_t src_id = -1, dst_id = -1;/* temporary type atoms */
+ size_t src_type_size; /* size of source type */
+ size_t dst_type_size; /* size of destination type*/
+ size_t buf_size; /* desired buffer size */
+ herr_t ret_value = FAIL;
+
+ FUNC_ENTER(H5A_read, FAIL);
+
+ assert(attr);
+ assert(mem_type);
+ assert(buf);
+
+
+ /* Create buffer for data to store on disk */
+ nelmts=H5S_get_npoints (attr->ds);
+
+ /* Get the memory and file datatype sizes */
+ src_type_size = H5T_get_size(attr->dt);
+ dst_type_size = H5T_get_size(mem_type);
+
+ /* Get the maximum buffer size needed and allocate it */
+ buf_size = nelmts*MAX(src_type_size,dst_type_size);
+ tconv_buf = H5MM_xmalloc (buf_size);
+
+ /* Copy the attribute data into the buffer for conversion */
+ HDmemcpy(tconv_buf,attr->data,src_type_size*nelmts);
+
+/* Convert memory buffer into disk buffer */
+ /* Set up type conversion function */
+ if (NULL == (tconv_func = H5T_find(attr->dt, mem_type,
+ H5T_BKG_NO, &cdata))) {
+ HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL,
+ "unable to convert between src and dest data types");
+ } else if (H5T_conv_noop!=tconv_func) {
+ if ((src_id = H5I_register(H5_DATATYPE, H5T_copy(attr->dt)))<0 ||
+ (dst_id = H5I_register(H5_DATATYPE, H5T_copy(mem_type)))<0) {
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL,
+ "unable to register types for conversion");
+ }
+ }
+
+ /* Perform data type conversion. */
+ cdata->command = H5T_CONV_CONV;
+ cdata->stats->ncalls++;
+ if ((tconv_func) (src_id, dst_id, cdata, nelmts, tconv_buf, NULL)<0) {
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL,
+ "data type conversion failed");
+ }
+
+ /* Copy the converted data into the user's buffer */
+ HDmemcpy(buf,tconv_buf,dst_type_size*nelmts);
+
+
+ ret_value=SUCCEED;
+
+done:
+ /* Release resources */
+ if (src_id >= 0)
+ H5I_dec_ref(src_id);
+ if (dst_id >= 0)
+ H5I_dec_ref(dst_id);
+ if (tconv_buf)
+ H5MM_xfree(tconv_buf);
+
+ FUNC_LEAVE(ret_value);
+} /* H5A_read() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Aget_space
+ PURPOSE
+ Gets a copy of the dataspace for an attribute
+ USAGE
+ hid_t H5Aget_space (attr_id)
+ hid_t attr_id; IN: Attribute to get dataspace of
+ RETURNS
+ A dataspace ID on success, negative on failure
+
+ ERRORS
+
+ DESCRIPTION
+ This function retrieves a copy of the dataspace for an attribute.
+ The dataspace ID returned from this function must be released with H5Sclose
+ or resource leaks will develop.
+--------------------------------------------------------------------------*/
+hid_t
+H5Aget_space(hid_t attr_id)
+{
+ H5A_t *attr = NULL;
+ H5S_t *dst = NULL;
+ hid_t ret_value = FAIL;
+
+ FUNC_ENTER(H5Aget_space, FAIL);
+
+ /* check arguments */
+ if (H5_ATTR != H5I_group(attr_id) ||
+ (NULL == (attr = H5I_object(attr_id)))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute");
+ }
+
+ /* Copy the attribute's dataspace */
+ if (NULL==(dst=H5S_copy (attr->ds))) {
+ HRETURN_ERROR (H5E_ATTR, H5E_CANTINIT, FAIL,
+ "unable to copy dataspace");
+ }
+
+ /* Atomize */
+ if ((ret_value=H5I_register (H5_DATASPACE, dst))<0) {
+ HRETURN_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL,
+ "unable to register dataspace atom");
+ }
+
+ FUNC_LEAVE(ret_value);
+} /* H5Aget_space() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Aget_type
+ PURPOSE
+ Gets a copy of the datatype for an attribute
+ USAGE
+ hid_t H5Aget_type (attr_id)
+ hid_t attr_id; IN: Attribute to get datatype of
+ RETURNS
+ A datatype ID on success, negative on failure
+
+ ERRORS
+
+ DESCRIPTION
+ This function retrieves a copy of the datatype for an attribute.
+ The datatype ID returned from this function must be released with H5Tclose
+ or resource leaks will develop.
+--------------------------------------------------------------------------*/
+hid_t
+H5Aget_type(hid_t attr_id)
+{
+ H5A_t *attr = NULL;
+ H5T_t *dst = NULL;
+ hid_t ret_value = FAIL;
+
+ FUNC_ENTER(H5Aget_type, FAIL);
+
+ /* check arguments */
+ if (H5_ATTR != H5I_group(attr_id) ||
+ (NULL == (attr = H5I_object(attr_id)))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute");
+ }
+
+ /* Copy the attribute's dataspace */
+ if (NULL==(dst=H5T_copy (attr->dt))) {
+ HRETURN_ERROR (H5E_ATTR, H5E_CANTINIT, FAIL,
+ "unable to copy datatype");
+ }
+
+ /* Atomize */
+ if ((ret_value=H5I_register (H5_DATATYPE, dst))<0) {
+ HRETURN_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL,
+ "unable to register datatype atom");
+ }
+
+ FUNC_LEAVE(ret_value);
+} /* H5Aget_type() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Aget_name
+ PURPOSE
+ Gets a copy of the name for an attribute
+ USAGE
+ size_t H5Aget_name (attr_id, buf, buf_size)
+ hid_t attr_id; IN: Attribute to get name of
+ char *buf; IN: Buffer to store name in
+ size_t buf_size; IN: The size of the buffer to store the string in.
+ RETURNS
+ This function returns the length of the attribute's name (which may be
+ longer than 'buf_size') on success or negative for failure.
+
+ ERRORS
+
+ DESCRIPTION
+ This function retrieves the name of an attribute for an attribute ID.
+ Up to 'buf_size' characters are stored in 'buf' followed by a '\0' string
+ terminator. If the name of the attribute is longer than 'buf_size'-1,
+ the string terminator is stored in the last position of the buffer to
+ properly terminate the string.
+--------------------------------------------------------------------------*/
+size_t
+H5Aget_name(hid_t attr_id, char *buf, size_t buf_size)
+{
+ H5A_t *attr = NULL;
+ size_t copy_len=0;
+ size_t ret_value = FAIL;
+
+ FUNC_ENTER(H5Aget_name, FAIL);
+
+ /* check arguments */
+ if (H5_ATTR != H5I_group(attr_id) ||
+ (NULL == (attr = H5I_object(attr_id)))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute");
+ }
+ if (!buf || buf_size==0) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid buffer");
+ }
+
+ /* get the real attribute length */
+ ret_value=HDstrlen(attr->name);
+
+ /* compute the string length which will fit into the user's buffer */
+ copy_len=MIN(buf_size-1,ret_value);
+
+ /* Copy all/some of the name */
+ HDmemcpy(buf,attr->name,copy_len);
+
+ /* Terminate the string */
+ buf[copy_len]='\0';
+
+ FUNC_LEAVE(ret_value);
+} /* H5Aget_type() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Anum_attrs
+ PURPOSE
+ Determines the number of attributes attached to an object
+ USAGE
+ int H5Anum_attrs (loc_id)
+ hid_t loc_id; IN: Object (dataset or group) to be queried
+ RETURNS
+ Number of attributes on success, negative on failure
+
+ ERRORS
+
+ DESCRIPTION
+ This function returns the number of attributes attached to a dataset or
+ group, 'location_id'.
+--------------------------------------------------------------------------*/
+int
+H5Anum_attrs(hid_t loc_id)
+{
+ H5G_entry_t *ent = NULL; /* Symbol table entry of object to attribute */
+ void *obj = NULL;
+ int ret_value = 0;
+
+ FUNC_ENTER(H5Anum_attrs, FAIL);
+
+ /* check arguments */
+ if (!(H5_DATASET != H5I_group(loc_id) || H5_GROUP != H5I_group(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "attribute target not a dataset or group");
+ }
+
+ /* Get the dataset or group's pointer */
+ if(NULL == (obj = H5I_object(loc_id)))
+ HRETURN_ERROR(H5E_ARGS, H5E_BADATOM, FAIL, "illegal object atom");
+
+ /* Copy the object header entry for the object */
+ if (H5_DATASET == H5I_group(loc_id))
+ ent=&(((H5D_t *)obj)->ent);
+ else
+ ent=&(((H5G_t *)obj)->ent);
+
+ /* Look up the attribute for the object */
+ ret_value=H5O_count(ent, H5O_ATTR);
+
+ FUNC_LEAVE(ret_value);
+} /* H5Anum_attrs() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Aiterate
+ PURPOSE
+ Calls a user's function for each attribute on an object
+ USAGE
+ herr_t H5Aiterate (loc_id, attr_num, op, data)
+ hid_t loc_id; IN: Object (dataset or group) to be iterated over
+ unsigned *attr_num; IN/OUT: Starting (IN) & Ending (OUT) attribute number
+ H5A_operator_t op; IN: User's function to pass each attribute to
+ void *op_data; IN/OUT: User's data to pass through to iterator operator function
+ RETURNS
+ Returns a negative value if something is wrong, the return value of the
+ last operator if it was non-zero, or zero if all attributes were processed.
+
+ ERRORS
+
+ DESCRIPTION
+ This function interates over the attributes of dataset or group
+ specified with 'loc_id'. For each attribute of the object, the
+ 'op_data' and some additional information (specified below) are passed
+ to the 'op' function. The iteration begins with the '*attr_number'
+ object in the group and the next attribute to be processed by the operator
+ is returned in '*attr_number'.
+ The operation receives the ID for the group or dataset being iterated
+ over ('loc_id'), the name of the current attribute about the object
+ ('attr_name') and the pointer to the operator data passed in to H5Aiterate
+ ('op_data'). The return values from an operator are:
+ A. Zero causes the iterator to continue, returning zero when all
+ attributes have been processed.
+ B. Positive causes the iterator to immediately return that positive
+ value, indicating short-circuit success. The iterator can be
+ restarted at the next attribute.
+ C. Negative causes the iterator to immediately return that value,
+ indicating failure. The iterator can be restarted at the next
+ attribute.
+--------------------------------------------------------------------------*/
+int
+H5Aiterate(hid_t loc_id, unsigned *attr_num, H5A_operator_t op, void *op_data)
+{
+ H5G_entry_t *ent = NULL; /* Symbol table entry of object to attribute */
+ void *obj = NULL;
+ H5A_t *found_attr = NULL;
+ int ret_value = 0;
+
+ FUNC_ENTER(H5Anum_attrs, FAIL);
+
+ /* check arguments */
+ if (!(H5_DATASET != H5I_group(loc_id) || H5_GROUP != H5I_group(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "attribute target not a dataset or group");
+ }
+ if (!attr_num) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index");
+ }
+ if (!op) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid operator");
+ }
+
+ /* Get the dataset or group's pointer */
+ if(NULL == (obj = H5I_object(loc_id)))
+ HRETURN_ERROR(H5E_ARGS, H5E_BADATOM, FAIL, "illegal object atom");
+
+ /* Copy the object header entry for the object */
+ if (H5_DATASET == H5I_group(loc_id))
+ ent=&(((H5D_t *)obj)->ent);
+ else
+ ent=&(((H5G_t *)obj)->ent);
+
+ /* Look up the attribute for the object */
+ if((int)*attr_num<H5O_count(ent, H5O_ATTR)) /* Make certain the start point is reasonable */
+ while((found_attr=H5O_read(ent, H5O_ATTR, *attr_num, NULL))!=NULL)
+ {
+ /* Compare found attribute name to new attribute name reject creation if names are the same */
+ (*attr_num)++;
+ if((ret_value=op(loc_id,found_attr->name,op_data))!=0)
+ break;
+ } /* end while */
+
+ FUNC_LEAVE(ret_value);
+} /* H5Aiterate() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Adelete
+ PURPOSE
+ Deletes an attribute from a location
+ USAGE
+ herr_t H5Adelete (loc_id, name)
+ hid_t loc_id; IN: Object (dataset or group) to have attribute deleted from
+ const char *name; IN: Name of attribute to delete
+ RETURNS
+ 0 on success, negative on failure
+
+ ERRORS
+
+ DESCRIPTION
+ This function removes the named attribute from a dataset or group.
+ This function should not be used when attribute IDs are open on 'loc_id'
+ as it may cause the internal indexes of the attributes to change and future
+ writes to the open attributes to produce incorrect results.
+--------------------------------------------------------------------------*/
+herr_t
+H5Adelete(hid_t loc_id, const char *name)
+{
+ H5A_t *found_attr = NULL;
+ H5G_entry_t *ent = NULL; /* Symbol table entry of object to attribute */
+ void *obj = NULL;
+ intn idx=0;
+ hid_t ret_value = FAIL;
+
+ FUNC_ENTER(H5Aopen_name, FAIL);
+
+ /* check arguments */
+ if (!(H5_DATASET != H5I_group(loc_id) || H5_GROUP != H5I_group(loc_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "attribute target not a dataset or group");
+ }
+ if (!name || !*name) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name");
+ }
+
+ /* Get the dataset or group's pointer */
+ if(NULL == (obj = H5I_object(loc_id)))
+ HRETURN_ERROR(H5E_ARGS, H5E_BADATOM, FAIL, "illegal object atom");
+
+ /* Copy the object header entry for the object */
+ if (H5_DATASET == H5I_group(loc_id))
+ ent=&(((H5D_t *)obj)->ent);
+ else
+ ent=&(((H5G_t *)obj)->ent);
+
+ /* Look up the attribute for the object */
+ idx=0;
+ while((found_attr=H5O_read(ent, H5O_ATTR, idx, NULL))!=NULL)
+ {
+ /* Compare found attribute name to new attribute name reject creation if names are the same */
+ if(HDstrcmp(found_attr->name,name)==0)
+ break;
+ idx++;
+ } /* end while */
+ if(found_attr==NULL) {
+ HRETURN_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL,
+ "attribute not found");
+ }
+
+ /* Delete the attribute from the location */
+ if ((ret_value=H5O_remove(ent, H5O_ATTR, idx)) < 0)
+ HRETURN_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL,
+ "can't delete attribute header message");
+
+ FUNC_LEAVE(ret_value);
+} /* H5Adelete() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Aclose
+ PURPOSE
+ Close an attribute ID
+ USAGE
+ herr_t H5Aclose (attr_id)
+ hid_t attr_id; IN: Attribute to release access to
+ RETURNS
+ SUCCEED/FAIL
+
+ ERRORS
+
+ DESCRIPTION
+ This function releases an attribute from use. Further use of the
+ attribute ID will result in undefined behavior.
+--------------------------------------------------------------------------*/
+herr_t
+H5Aclose(hid_t attr_id)
+{
+ H5A_t *attr = NULL;
+ herr_t ret_value = FAIL;
+
+ FUNC_ENTER(H5Aclose, FAIL);
+
+ /* check arguments */
+ if (H5_ATTR != H5I_group(attr_id) ||
+ (NULL == (attr = H5I_object(attr_id)))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute");
+ }
+
+ /* Check if the attribute has any data yet, if not, fill with zeroes */
+ if(!attr->initialized) {
+ uint8 *tmp_buf=H5MM_xcalloc(1,attr->data_size);
+
+ if (NULL == tmp_buf) {
+ HRETURN_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL,
+ "can't allocate attribute fill-value");
+ }
+
+ /* Go write the fill data to the attribute */
+ if ((ret_value=H5A_write(attr,attr->dt,tmp_buf))<0) {
+ HRETURN_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL,
+ "can't write attribute");
+ }
+
+ /* Free temporary buffer */
+ H5MM_xfree(tmp_buf);
+ } /* end if */
+
+ /* Free the memory used for the attribute */
+ H5A_close(attr);
+ ret_value=SUCCEED;
+
+ FUNC_LEAVE(ret_value);
+} /* H5Aclose() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_copy
+ *
+ * Purpose: Copies attribute OLD_ATTR.
+ *
+ * Return: Success: Pointer to a new copy of the OLD_ATTR argument.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, December 4, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5A_t *
+H5A_copy(const H5A_t *old_attr)
+{
+ H5A_t *new_attr=NULL;
+
+ FUNC_ENTER(H5A_copy, NULL);
+
+ /* check args */
+ assert(old_attr);
+
+ /* get space */
+ new_attr = H5MM_xcalloc(1, sizeof(H5A_t));
+
+ /* Copy the top level of the attribute */
+ *new_attr = *old_attr;
+
+ /* Don't open the object header for a copy */
+ new_attr->ent_opened=0;
+
+ /* Copy the guts of the attribute */
+ new_attr->name=HDstrdup(old_attr->name);
+ new_attr->dt=H5T_copy(old_attr->dt);
+ new_attr->ds=H5S_copy(old_attr->ds);
+ if(old_attr->data) {
+ new_attr->data=H5MM_xmalloc(old_attr->data_size);
+ HDmemcpy(new_attr->data,old_attr->data,old_attr->data_size);
+ } /* end if */
+
+ /* Copy the share info? */
+
+ FUNC_LEAVE(new_attr);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_close
+ *
+ * Purpose: Frees a attribute and all associated memory.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Monday, December 8, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_close(H5A_t *attr)
+{
+ FUNC_ENTER(H5A_close, FAIL);
+
+ assert(attr);
+
+ /* Free dynamicly allocated items */
+ if(attr->name)
+ H5MM_xfree(attr->name);
+ if(attr->dt)
+ H5T_close(attr->dt);
+ if(attr->ds)
+ H5S_close(attr->ds);
+ if(attr->data)
+ H5MM_xfree(attr->data);
+
+ /* Close the object's symbol-table entry */
+ if(attr->ent_opened)
+ H5O_close(&(attr->ent));
+
+/* Do something with the shared information? */
+
+ H5MM_xfree(attr);
+
+ FUNC_LEAVE(SUCCEED);
+}
+
diff --git a/src/H5Apkg.h b/src/H5Apkg.h
new file mode 100644
index 0000000..b6f1a24
--- /dev/null
+++ b/src/H5Apkg.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 1997 NCSA
+ * All rights reserved.
+ *
+ * Programmer: Robb Matzke <matzke@llnl.gov>
+ * Monday, December 8, 1997
+ *
+ * Purpose: This file contains declarations which are visible only within
+ * the H5A package. Source files outside the H5A package should
+ * include H5Aprivate.h instead.
+ */
+#ifndef H5A_PACKAGE
+#error "Do not include this file outside the H5A package!"
+#endif
+
+#ifndef _H5Apkg_H
+#define _H5Apkg_H
+
+/*
+ * Define this to enable debugging.
+ */
+#ifdef NDEBUG
+# undef H5A_DEBUG
+#endif
+
+#include <H5HGprivate.h>
+#include <H5Aprivate.h>
+
+struct H5A_t {
+ uintn initialized;/* Indicate whether the attribute has been modified */
+ uintn ent_opened; /* Object header entry opened? */
+ H5G_entry_t ent; /* Object Header entry (for both datasets & groups) */
+ char *name; /* Attribute's name */
+ H5T_t *dt; /* Attribute's datatype */
+ size_t dt_size; /* Size of datatype on disk */
+ H5S_t *ds; /* Attribute's dataspace */
+ size_t ds_size; /* Size of dataspace on disk */
+ void *data; /* Attribute data (on a temporary basis) */
+ size_t data_size; /* Size of data on disk */
+ H5HG_t sh_heap; /*if defined, attribute is in global heap */
+ H5F_t *sh_file; /*file pointer if this is a shared attribute */
+};
+
+/* Function prototypes for H5T package scope */
+
+#endif
diff --git a/src/H5Aprivate.h b/src/H5Aprivate.h
new file mode 100644
index 0000000..9557ddd
--- /dev/null
+++ b/src/H5Aprivate.h
@@ -0,0 +1,30 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/*
+ * This file contains private information about the H5D module
+ */
+#ifndef _H5Aprivate_H
+#define _H5Aprivate_H
+
+#include <H5Apublic.h>
+
+#define H5A_RESERVED_ATOMS 0
+typedef struct H5A_t H5A_t;
+
+/* Private headers needed by this file */
+
+/* Functions defined in H5A.c */
+H5A_t * H5A_copy(const H5A_t *old_attr);
+herr_t H5A_close(H5A_t *attr);
+
+#endif
diff --git a/src/H5Apublic.h b/src/H5Apublic.h
new file mode 100644
index 0000000..71322dc
--- /dev/null
+++ b/src/H5Apublic.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+ * NCSA HDF *
+ * Software Development Group *
+ * National Center for Supercomputing Applications *
+ * University of Illinois at Urbana-Champaign *
+ * 605 E. Springfield, Champaign IL 61820 *
+ * *
+ * For conditions of distribution and use, see the accompanying *
+ * hdf/COPYING file. *
+ * *
+ ****************************************************************************/
+
+/*
+ * This file contains public declarations for the H5A module.
+ */
+#ifndef _H5Apublic_H
+#define _H5Apublic_H
+
+/* Public headers needed by this file */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int (*H5A_operator_t)(hid_t location_id/*in*/,
+ const char *attr_name/*in*/, void *operator_data/*in,out*/);
+
+/* Public function prototypes */
+hid_t H5Acreate(hid_t loc_id, const char *name, hid_t datatype, hid_t dataspace, hid_t create_plist);
+hid_t H5Aopen_name(hid_t loc_id, const char *name);
+hid_t H5Aopen_idx(hid_t loc_id, unsigned idx);
+herr_t H5Awrite(hid_t attr_id, hid_t mem_dt, void *buf);
+herr_t H5Aread(hid_t attr_id, hid_t mem_dt, void *buf);
+herr_t H5Aclose(hid_t attr_id);
+hid_t H5Aget_space(hid_t attr);
+hid_t H5Aget_type(hid_t attr);
+size_t H5Aget_name(hid_t attr, char *buf, size_t buf_size);
+int H5Anum_attrs(hid_t loc_id);
+int H5Aiterate(hid_t loc_id, unsigned *attr_num, H5A_operator_t op, void *op_data);
+herr_t H5Adelete(hid_t loc_id, const char *name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _H5Apublic_H */
diff --git a/src/H5D.c b/src/H5D.c
index 45ed334..17a5c7d 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -14,12 +14,12 @@
static char RcsId[] = "@(#)$Revision$";
#endif
-/* $Id$ */
+#define H5D_PACKAGE /*suppress error about including H5Tpkg */
#include <H5private.h> /* Generic Functions */
#include <H5Iprivate.h> /* IDs */
#include <H5ACprivate.h> /* Cache */
-#include <H5Dprivate.h> /* Dataset functions */
+#include <H5Dpkg.h> /* Dataset functions */
#include <H5Eprivate.h> /* Error handling */
#include <H5Gprivate.h> /* Group headers */
#include <H5HLprivate.h> /* Name heap */
@@ -37,17 +37,6 @@ static char RcsId[] = "@(#)$Revision$";
*/
#define H5D_OPTIMIZE_PIPE 1
-/*
- * A dataset is the following struct.
- */
-struct H5D_t {
- H5G_entry_t ent; /*cached object header stuff */
- H5T_t *type; /*datatype of this dataset */
- H5S_t *space; /*dataspace of this dataset */
- H5D_create_t *create_parms; /*creation parameters */
- H5O_layout_t layout; /*data layout */
-};
-
/* Default dataset creation property list */
const H5D_create_t H5D_create_dflt = {
H5D_CONTIGUOUS, /* Layout */
diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h
new file mode 100644
index 0000000..e57f6ab
--- /dev/null
+++ b/src/H5Dpkg.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 1997 NCSA
+ * All rights reserved.
+ *
+ * Programmer: Robb Matzke <matzke@llnl.gov>
+ * Monday, December 8, 1997
+ *
+ * Purpose: This file contains declarations which are visible only within
+ * the H5D package. Source files outside the H5D package should
+ * include H5Dprivate.h instead.
+ */
+#ifndef H5D_PACKAGE
+#error "Do not include this file outside the H5D package!"
+#endif
+
+#ifndef _H5Dpkg_H
+#define _H5Dpkg_H
+
+/*
+ * Define this to enable debugging.
+ */
+#ifdef NDEBUG
+# undef H5D_DEBUG
+#endif
+
+#include <H5Dprivate.h>
+
+/*
+ * A dataset is the following struct.
+ */
+struct H5D_t {
+ H5G_entry_t ent; /*cached object header stuff */
+ H5T_t *type; /*datatype of this dataset */
+ H5S_t *space; /*dataspace of this dataset */
+ H5D_create_t *create_parms; /*creation parameters */
+ H5O_layout_t layout; /*data layout */
+};
+
+
+#endif
diff --git a/src/H5Epublic.h b/src/H5Epublic.h
index 284b310..9a07ad5 100644
--- a/src/H5Epublic.h
+++ b/src/H5Epublic.h
@@ -46,6 +46,7 @@ typedef enum H5E_major_t {
H5E_DATASET, /*Dataset */
H5E_STORAGE, /*data storage */
H5E_TEMPLATE, /*Property lists */
+ H5E_ATTR, /*Attribute */
H5E_COMP, /*Data compression */
H5E_EFL /*External file list */
} H5E_major_t;
@@ -108,6 +109,7 @@ typedef enum H5E_minor_t {
H5E_VERSION, /*wrong version number */
H5E_ALIGNMENT, /*alignment error */
H5E_BADMESG, /*unrecognized message */
+ H5E_CANTDELETE, /* Can't delete message */
/* Group related errors */
H5E_CANTOPENOBJ, /*Can't open object */
diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h
index 25fe0c7..895128b 100644
--- a/src/H5Iprivate.h
+++ b/src/H5Iprivate.h
@@ -67,6 +67,7 @@
#define H5I_DATASETID_HASHSIZE 64
#define H5I_OID_HASHSIZE 64
#define H5I_GROUPID_HASHSIZE 64
+#define H5I_ATTRID_HASHSIZE 64
/* Atom information structure used */
typedef struct H5I_id_info_t {
diff --git a/src/H5Ipublic.h b/src/H5Ipublic.h
index bb1dfc4..eb8b804 100644
--- a/src/H5Ipublic.h
+++ b/src/H5Ipublic.h
@@ -40,6 +40,7 @@ typedef enum {
H5_DATASPACE, /*group ID for Dataspace objects */
H5_DATASET, /*group ID for Dataset objects */
H5_DIRECTORY, /*group ID for Directory objects */
+ H5_ATTR, /*group ID for Attribute objects */
MAXGROUP /*highest group in group_t (Invalid as true group)*/
} H5I_group_t;
diff --git a/src/H5O.c b/src/H5O.c
index a027bf0..9bf528c 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -62,7 +62,7 @@ static const H5O_class_t *const message_type_g[] = {
NULL, /*0x0009 Not assigned */
NULL, /*0x000A Not assigned */
H5O_COMPRESS, /*0x000B Data storage -- compressed object */
- NULL, /*0x000C Attribute list */
+ H5O_ATTR, /*0x000C Attribute list */
H5O_NAME, /*0x000D Object name */
NULL, /*0x000E Object modification date and time */
NULL, /*0x000F Shared header message */
@@ -975,7 +975,7 @@ H5O_find_in_ohdr(H5F_t *f, const haddr_t *addr, const H5O_class_t **type_p,
*
* The OVERWRITE argument is either a sequence number of a
* message to overwrite (usually zero) or the constant
- * H5O_NEW_MESSAGE (-1) to indicate that a new message is to
+ * H5O_NEW_MESG (-1) to indicate that a new message is to
* be created. If the message to overwrite doesn't exist then
* it is created (but only if it can be inserted so its sequence
* number is OVERWRITE; that is, you can create a message with
diff --git a/src/H5Oattr.c b/src/H5Oattr.c
new file mode 100644
index 0000000..2671b38
--- /dev/null
+++ b/src/H5Oattr.c
@@ -0,0 +1,560 @@
+/****************************************************************************
+* NCSA HDF *
+* Software Development Group *
+* National Center for Supercomputing Applications *
+* University of Illinois at Urbana-Champaign *
+* 605 E. Springfield, Champaign IL 61820 *
+* *
+* For conditions of distribution and use, see the accompanying *
+* hdf/COPYING file. *
+* *
+****************************************************************************/
+
+#ifdef RCSID
+static char RcsId[] = "@(#)$Revision$";
+#endif
+
+/* $Id$ */
+
+#define H5A_PACKAGE /*prevent warning from including H5Tpkg.h */
+
+#include <H5private.h>
+#include <H5Eprivate.h>
+#include <H5Gprivate.h>
+#include <H5MMprivate.h>
+#include <H5Oprivate.h>
+#include <H5Apkg.h>
+
+#define PABLO_MASK H5O_attr_mask
+
+/* PRIVATE PROTOTYPES */
+static herr_t H5O_attr_encode (H5F_t *f, uint8 *p, const void *mesg);
+static void *H5O_attr_decode (H5F_t *f, const uint8 *p, H5HG_t *hobj);
+static void *H5O_attr_copy (const void *_mesg, void *_dest);
+static size_t H5O_attr_size (H5F_t *f, const void *_mesg);
+static herr_t H5O_attr_reset (void *_mesg);
+static herr_t H5O_attr_debug (H5F_t *f, const void *_mesg,
+ FILE * stream, intn indent, intn fwidth);
+
+/* This message derives from H5O */
+const H5O_class_t H5O_ATTR[1] = {{
+ H5O_ATTR_ID, /* message id number */
+ "attribute", /* message name for debugging */
+ sizeof(H5A_t), /* native message size */
+ H5O_attr_decode, /* decode message */
+ H5O_attr_encode, /* encode message */
+ H5O_attr_copy, /* copy the native value */
+ H5O_attr_size, /* size of raw message */
+ H5O_attr_reset, /* reset method */
+ NULL, /* no share method (currently) */
+ H5O_attr_debug, /* debug the message */
+}};
+
+/* Interface initialization */
+static hbool_t interface_initialize_g = FALSE;
+#define INTERFACE_INIT NULL
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5O_attr_decode
+ PURPOSE
+ Decode a attribute message and return a pointer to a memory struct
+ with the decoded information
+ USAGE
+ void *H5O_attr_decode(f, raw_size, p)
+ H5F_t *f; IN: pointer to the HDF5 file struct
+ size_t raw_size; IN: size of the raw information buffer
+ const uint8 *p; IN: the raw information buffer
+ RETURNS
+ Pointer to the new message in native order on success, NULL on failure
+ DESCRIPTION
+ This function decodes the "raw" disk form of a attribute message
+ into a struct in memory native format. The struct is allocated within this
+ function using malloc() and is returned to the caller.
+--------------------------------------------------------------------------*/
+static void *
+H5O_attr_decode(H5F_t *f, const uint8 *p, H5HG_t __unused__ *hobj)
+{
+ H5A_t *attr = NULL;
+ H5S_simple_t *simple; /*simple dimensionality information */
+ size_t name_len; /* Attribute name length */
+
+ FUNC_ENTER(H5O_attr_decode, NULL);
+
+ /* check args */
+ assert(f);
+ assert(p);
+
+ attr = H5MM_xcalloc(1, sizeof(H5A_t));
+
+ /* Decode and store the name */
+ UINT16DECODE(p, name_len);
+ attr->name=H5MM_xmalloc(name_len+1);
+ HDmemcpy(attr->name,p,name_len);
+ attr->name[name_len]='\0';
+ p+=name_len; /* advance the memory pointer */
+
+ /* decode the attribute datatype */
+ if((attr->dt=(H5O_DTYPE[0].decode)(f,p,NULL))==NULL) {
+ HRETURN_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL,
+ "can't decode attribute datatype");
+ }
+ attr->dt_size=(H5O_DTYPE[0].raw_size)(f,attr->dt);
+ p+=attr->dt_size;
+
+ /* decode the attribute dataspace */
+ attr->ds = H5MM_xcalloc(1, sizeof(H5S_t));
+ if((simple=(H5O_SDSPACE[0].decode)(f,p,NULL))!=NULL) {
+ attr->ds->type = H5S_SIMPLE;
+ HDmemcpy(&(attr->ds->u.simple),simple, sizeof(H5S_simple_t));
+ H5MM_xfree(simple);
+ } else {
+ attr->ds->type = H5S_SCALAR;
+ } /* end else */
+ attr->ds_size=(H5O_SDSPACE[0].raw_size)(f,&(attr->ds->u.simple));
+ p+=attr->ds_size;
+
+ /* Compute the size of the data */
+ attr->data_size=H5S_get_npoints(attr->ds)*H5T_get_size(attr->dt);
+
+ /* Go get the data */
+ attr->data = H5MM_xmalloc(attr->data_size);
+ HDmemcpy(attr->data,p,attr->data_size);
+
+ /* Indicate that the fill values aren't to be written out */
+ attr->initialized=1;
+
+#ifdef LOTSLATER
+ if (hobj) {
+ attr->sh_heap = *hobj;
+ attr->sh_file = f;
+ }
+#endif
+
+ FUNC_LEAVE(attr);
+}
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5O_attr_encode
+ PURPOSE
+ Encode a simple attribute message
+ USAGE
+ herr_t H5O_attr_encode(f, raw_size, p, mesg)
+ H5F_t *f; IN: pointer to the HDF5 file struct
+ const uint8 *p; IN: the raw information buffer
+ const void *mesg; IN: Pointer to the simple datatype struct
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ This function encodes the native memory form of the attribute
+ message in the "raw" disk form.
+--------------------------------------------------------------------------*/
+static herr_t
+H5O_attr_encode(H5F_t *f, uint8 *p, const void *mesg)
+{
+ const H5A_t *attr = (const H5A_t *) mesg;
+ size_t name_len; /* Attribute name length */
+
+ FUNC_ENTER(H5O_attr_encode, FAIL);
+
+ /* check args */
+ assert(f);
+ assert(p);
+ assert(attr);
+
+ /* encode the attribute name */
+ name_len=HDstrlen(attr->name);
+ UINT16ENCODE(p, name_len);
+ HDmemcpy(p,attr->name,name_len);
+ p+=name_len;
+
+ /* encode the attribute datatype */
+ if((H5O_DTYPE[0].encode)(f,p,attr->dt)<0) {
+ HRETURN_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL,
+ "can't encode attribute datatype");
+ }
+ p+=attr->dt_size;
+
+ /* encode the attribute dataspace */
+ if((H5O_SDSPACE[0].encode)(f,p,&(attr->ds->u.simple))<0) {
+ HRETURN_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL,
+ "can't encode attribute dataspace");
+ }
+ p+=attr->ds_size;
+
+ /* Store attribute data */
+ HDmemcpy(p,attr->data,attr->data_size);
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5O_attr_copy
+ PURPOSE
+ Copies a message from MESG to DEST, allocating DEST if necessary.
+ USAGE
+ void *H5O_attr_copy(mesg, dest)
+ const void *mesg; IN: Pointer to the source attribute struct
+ const void *dest; IN: Pointer to the destination attribute struct
+ RETURNS
+ Pointer to DEST on success, NULL on failure
+ DESCRIPTION
+ This function copies a native (memory) attribute message,
+ allocating the destination structure if necessary.
+--------------------------------------------------------------------------*/
+static void *
+H5O_attr_copy(const void *_src, void *_dst)
+{
+ const H5A_t *src = (const H5A_t *) _src;
+ H5A_t *dst = NULL;
+
+ FUNC_ENTER(H5O_attr_copy, NULL);
+
+ /* check args */
+ assert(src);
+
+ /* copy */
+ if (NULL == (dst = H5A_copy(src))) {
+ HRETURN_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "can't copy attribute");
+ }
+ /* was result already allocated? */
+ if (_dst) {
+ *((H5A_t *) _dst) = *dst;
+ H5MM_xfree(dst);
+ dst = (H5A_t *) _dst;
+ }
+ FUNC_LEAVE((void *) dst);
+}
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5O_attr_size
+ PURPOSE
+ Return the raw message size in bytes
+ USAGE
+ size_t H5O_attr_size(f, mesg)
+ H5F_t *f; IN: pointer to the HDF5 file struct
+ const void *mesg; IN: Pointer to the source attribute struct
+ RETURNS
+ Size of message on success, 0 on failure
+ DESCRIPTION
+ This function returns the size of the raw attribute message on
+ success. (Not counting the message type or size fields, only the data
+ portion of the message). It doesn't take into account alignment.
+--------------------------------------------------------------------------*/
+static size_t
+H5O_attr_size(H5F_t __unused__ *f, const void *mesg)
+{
+ size_t ret_value = 0;
+ const H5A_t *attr = (const H5A_t *) mesg;
+
+ FUNC_ENTER(H5O_attr_size, 0);
+
+ assert(attr);
+
+ /* Get size of name */
+ ret_value=2; /* Size to store length of name */
+ ret_value+=HDstrlen(attr->name); /* Add length of name (non-zero terminated) */
+
+ /* Get size of datatype information */
+ ret_value+=attr->dt_size;
+
+ /* Get size of [simple] dataspace information */
+ ret_value+=attr->ds_size;
+
+ /* Get size of attribute data */
+ ret_value+=attr->data_size;
+
+ FUNC_LEAVE(ret_value);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5O_attr_reset
+ *
+ * Purpose: Frees resources within a attribute message, but doesn't free
+ * the message itself.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, December 9, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5O_attr_reset(void *_mesg)
+{
+ H5A_t *attr = (H5A_t *) _mesg;
+ H5A_t *tmp = NULL;
+
+ FUNC_ENTER(H5O_attr_reset, FAIL);
+
+ if (attr) {
+ tmp = H5MM_xmalloc(sizeof(H5A_t));
+ *tmp = *attr;
+ H5A_close(tmp);
+ HDmemset(attr, 0, sizeof(H5A_t));
+ }
+ FUNC_LEAVE(SUCCEED);
+}
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5O_attr_debug
+ PURPOSE
+ Prints debugging information for an attribute message
+ USAGE
+ void *H5O_attr_debug(f, mesg, stream, indent, fwidth)
+ H5F_t *f; IN: pointer to the HDF5 file struct
+ const void *mesg; IN: Pointer to the source attribute struct
+ FILE *stream; IN: Pointer to the stream for output data
+ intn indent; IN: Amount to indent information by
+ intn fwidth; IN: Field width (?)
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ This function prints debugging output to the stream passed as a
+ parameter.
+--------------------------------------------------------------------------*/
+static herr_t
+H5O_attr_debug(H5F_t __unused__ *f, const void __unused__ *mesg, FILE __unused__ * stream,
+ intn __unused__ indent, intn __unused__ fwidth)
+{
+ const H5A_t *attr = (const H5A_t *) mesg;
+#ifdef LATER
+ const char *s;
+ char buf[256];
+ intn i, j;
+#endif /* LATER */
+
+ FUNC_ENTER(H5O_attr_debug, FAIL);
+
+ /* check args */
+ assert(f);
+ assert(attr);
+ assert(stream);
+ assert(indent >= 0);
+ assert(fwidth >= 0);
+
+#ifdef LATER
+ switch (dt->type) {
+ case H5T_INTEGER:
+ s = "integer";
+ break;
+ case H5T_FLOAT:
+ s = "floating-point";
+ break;
+ case H5T_TIME:
+ s = "date and time";
+ break;
+ case H5T_STRING:
+ s = "text string";
+ break;
+ case H5T_BITFIELD:
+ s = "bit field";
+ break;
+ case H5T_OPAQUE:
+ s = "opaque";
+ break;
+ case H5T_COMPOUND:
+ s = "compound";
+ break;
+ default:
+ sprintf(buf, "H5T_CLASS_%d", (int) (dt->type));
+ s = buf;
+ break;
+ }
+ fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Type class:",
+ s);
+
+ fprintf(stream, "%*s%-*s %lu byte%s\n", indent, "", fwidth,
+ "Size:",
+ (unsigned long) (dt->size), 1 == dt->size ? "" : "s");
+
+ if (H5T_COMPOUND == dt->type) {
+ fprintf(stream, "%*s%-*s %d\n", indent, "", fwidth,
+ "Number of members:",
+ dt->u.compnd.nmembs);
+ for (i = 0; i < dt->u.compnd.nmembs; i++) {
+ sprintf(buf, "Member %d:", i);
+ fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ buf,
+ dt->u.compnd.memb[i].name);
+ fprintf(stream, "%*s%-*s %lu\n", indent + 3, "", MAX(0, fwidth-3),
+ "Byte offset:",
+ (unsigned long) (dt->u.compnd.memb[i].offset));
+ fprintf(stream, "%*s%-*s %d%s\n", indent + 3, "", MAX(0, fwidth-3),
+ "Dimensionality:",
+ dt->u.compnd.memb[i].ndims,
+ 0 == dt->u.compnd.memb[i].ndims ? " (scalar)" : "");
+ if (dt->u.compnd.memb[i].ndims > 0) {
+ fprintf(stream, "%*s%-*s {", indent + 3, "", MAX(0, fwidth-3),
+ "Size:");
+ for (j = 0; j < dt->u.compnd.memb[i].ndims; j++) {
+ fprintf(stream, "%s%lu", j ? ", " : "",
+ (unsigned long) (dt->u.compnd.memb[i].dim[j]));
+ }
+ fprintf(stream, "}\n");
+ fprintf(stream, "%*s%-*s {", indent + 3, "", MAX(0, fwidth-3),
+ "Permutation:");
+ for (j = 0; j < dt->u.compnd.memb[i].ndims; j++) {
+ fprintf(stream, "%s%lu", j ? ", " : "",
+ (unsigned long) (dt->u.compnd.memb[i].perm[j]));
+ }
+ fprintf(stream, "}\n");
+ }
+ H5O_dtype_debug(f, dt->u.compnd.memb[i].type, stream,
+ indent + 3, MAX(0, fwidth - 3));
+ }
+ } else {
+ switch (dt->u.atomic.order) {
+ case H5T_ORDER_LE:
+ s = "little endian";
+ break;
+ case H5T_ORDER_BE:
+ s = "big endian";
+ break;
+ case H5T_ORDER_VAX:
+ s = "VAX";
+ break;
+ case H5T_ORDER_NONE:
+ s = "none";
+ break;
+ default:
+ sprintf(buf, "H5T_ORDER_%d", dt->u.atomic.order);
+ s = buf;
+ break;
+ }
+ fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Byte order:",
+ s);
+
+ fprintf(stream, "%*s%-*s %lu bit%s\n", indent, "", fwidth,
+ "Precision:",
+ (unsigned long) (dt->u.atomic.prec),
+ 1 == dt->u.atomic.prec ? "" : "s");
+
+ fprintf(stream, "%*s%-*s %lu bit%s\n", indent, "", fwidth,
+ "Offset:",
+ (unsigned long) (dt->u.atomic.offset),
+ 1 == dt->u.atomic.offset ? "" : "s");
+
+ switch (dt->u.atomic.lsb_pad) {
+ case H5T_PAD_ZERO:
+ s = "zero";
+ break;
+ case H5T_PAD_ONE:
+ s = "one";
+ break;
+ default:
+ s = "pad?";
+ break;
+ }
+ fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Low pad type:", s);
+
+ switch (dt->u.atomic.msb_pad) {
+ case H5T_PAD_ZERO:
+ s = "zero";
+ break;
+ case H5T_PAD_ONE:
+ s = "one";
+ break;
+ default:
+ s = "pad?";
+ break;
+ }
+ fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "High pad type:", s);
+
+ if (H5T_FLOAT == dt->type) {
+ switch (dt->u.atomic.u.f.pad) {
+ case H5T_PAD_ZERO:
+ s = "zero";
+ break;
+ case H5T_PAD_ONE:
+ s = "one";
+ break;
+ default:
+ if (dt->u.atomic.u.f.pad < 0) {
+ sprintf(buf, "H5T_PAD_%d", -(dt->u.atomic.u.f.pad));
+ } else {
+ sprintf(buf, "bit-%d", dt->u.atomic.u.f.pad);
+ }
+ s = buf;
+ break;
+ }
+ fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Internal pad type:", s);
+
+ switch (dt->u.atomic.u.f.norm) {
+ case H5T_NORM_IMPLIED:
+ s = "implied";
+ break;
+ case H5T_NORM_MSBSET:
+ s = "msb set";
+ break;
+ case H5T_NORM_NONE:
+ s = "none";
+ break;
+ default:
+ sprintf(buf, "H5T_NORM_%d", (int) (dt->u.atomic.u.f.norm));
+ s = buf;
+ }
+ fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Normalization:", s);
+
+ fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth,
+ "Sign bit location:",
+ (unsigned long) (dt->u.atomic.u.f.sign));
+
+ fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth,
+ "Exponent location:",
+ (unsigned long) (dt->u.atomic.u.f.epos));
+
+ fprintf(stream, "%*s%-*s 0x%08lx\n", indent, "", fwidth,
+ "Exponent bias:",
+ (unsigned long) (dt->u.atomic.u.f.ebias));
+
+ fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth,
+ "Exponent size:",
+ (unsigned long) (dt->u.atomic.u.f.esize));
+
+ fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth,
+ "Mantissa location:",
+ (unsigned long) (dt->u.atomic.u.f.mpos));
+
+ fprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth,
+ "Mantissa size:",
+ (unsigned long) (dt->u.atomic.u.f.msize));
+
+ } else if (H5T_INTEGER == dt->type) {
+ switch (dt->u.atomic.u.i.sign) {
+ case H5T_SGN_NONE:
+ s = "none";
+ break;
+ case H5T_SGN_2:
+ s = "2's comp";
+ break;
+ default:
+ sprintf(buf, "H5T_SGN_%d", (int) (dt->u.atomic.u.i.sign));
+ s = buf;
+ break;
+ }
+ fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
+ "Sign scheme:", s);
+
+ }
+ }
+#endif /* LATER */
+
+ FUNC_LEAVE(SUCCEED);
+}
+
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index bd4503e..b6e340b 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -180,6 +180,14 @@ typedef struct H5O_compress_t {
} H5O_compress_t;
/*
+ * Attribute Message.
+ */
+#define H5O_ATTR_ID 0x000C
+extern const H5O_class_t H5O_ATTR[1];
+
+/* operates on an H5A_t struct */
+
+/*
* Object name message.
*/
#define H5O_NAME_ID 0x000d
diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c
index 12ae765..0073c9b 100644
--- a/src/H5Osdspace.c
+++ b/src/H5Osdspace.c
@@ -258,7 +258,7 @@ H5O_sdspace_size(H5F_t *f, const void *mesg)
*/
size_t ret_value = 8;
- FUNC_ENTER(H5O_sim_dtype_size, 0);
+ FUNC_ENTER(H5O_sdspace_size, 0);
/* add in the dimension sizes */
ret_value += sdim->rank * H5F_SIZEOF_SIZE (f);
diff --git a/src/H5S.c b/src/H5S.c
index 177b5dc..47a1ac4 100644
--- a/src/H5S.c
+++ b/src/H5S.c
@@ -238,9 +238,7 @@ H5S_close(H5S_t *ds)
break;
case H5S_SIMPLE:
- H5MM_xfree(ds->u.simple.size);
- H5MM_xfree(ds->u.simple.max);
- H5MM_xfree(ds->u.simple.perm);
+ H5S_close_simple(&(ds->u.simple));
break;
case H5S_COMPLEX:
@@ -262,6 +260,37 @@ H5S_close(H5S_t *ds)
}
/*-------------------------------------------------------------------------
+ * Function: H5S_close_simple
+ *
+ * Purpose: Releases all memory associated with a simple data space.
+ * (but doesn't free the simple space itself)
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Friday, April 17, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5S_close_simple(H5S_simple_t *simple)
+{
+ FUNC_ENTER(H5S_close_simple, FAIL);
+
+ assert(simple);
+
+ H5MM_xfree(simple->size);
+ H5MM_xfree(simple->max);
+ H5MM_xfree(simple->perm);
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+/*-------------------------------------------------------------------------
* Function: H5Scopy
*
* Purpose: Copies a dataspace.
diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h
index 07f4108..a023f5d 100644
--- a/src/H5Sprivate.h
+++ b/src/H5Sprivate.h
@@ -108,6 +108,7 @@ typedef struct H5S_tconv_t {
} H5S_conv_t;
H5S_t *H5S_copy (const H5S_t *src);
+herr_t H5S_close_simple (H5S_simple_t *simple);
herr_t H5S_close (H5S_t *ds);
hsize_t H5S_get_npoints (const H5S_t *ds);
hsize_t H5S_get_npoints_max(const H5S_t *ds);
diff --git a/src/H5T.c b/src/H5T.c
index 3ffbdcc..1a7f911 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -3006,9 +3006,9 @@ H5T_insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member)
/* Does the new member overlap any existing member ? */
for (i = 0; i < parent->u.compnd.nmembs; i++) {
- if ((offset < parent->u.compnd.memb[i].offset &&
+ if ((offset <= parent->u.compnd.memb[i].offset &&
offset + member->size > parent->u.compnd.memb[i].offset) ||
- (parent->u.compnd.memb[i].offset < offset &&
+ (parent->u.compnd.memb[i].offset <= offset &&
parent->u.compnd.memb[i].offset +
parent->u.compnd.memb[i].type->size > offset)) {
HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL,
diff --git a/src/H5Tpublic.h b/src/H5Tpublic.h
index 4c1a680..1fc4477 100644
--- a/src/H5Tpublic.h
+++ b/src/H5Tpublic.h
@@ -20,7 +20,7 @@
#include <H5public.h>
#include <H5Ipublic.h>
-#define HOFFSET(S,M) ((size_t)((const char*)&S.M-(const char*)&S))
+#define HOFFSET(S,M) (offsetof(S,M))
#define HPOFFSET(P,M) ((size_t)((const char*)&(P->M)-(const char*)P))
/* These are the various classes of data types */
diff --git a/src/H5public.h b/src/H5public.h
index 81bbe17..0f2aebf 100644
--- a/src/H5public.h
+++ b/src/H5public.h
@@ -18,6 +18,7 @@
#include <H5config.h> /*from configure */
#include <sys/types.h>
+#include <stddef.h>
#ifdef HAVE_PARALLEL
# include <mpi.h>
# include <mpio.h>
diff --git a/src/Makefile.in b/src/Makefile.in
index ca59511..cd18e59 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -16,12 +16,12 @@ PROGS=debug h5ls
# Source and object files for the library (lexicographically)...
PARALLEL_SRC=H5Fmpio.c
-LIB_SRC=H5.c H5AC.c H5B.c H5D.c H5E.c H5F.c H5Farray.c H5Fcore.c H5Ffamily.c \
- H5Fistore.c H5Flow.c H5Fsec2.c H5Fsplit.c H5Fstdio.c H5G.c H5Gent.c \
- H5Gnode.c H5Gstab.c H5HG.c H5HL.c H5I.c H5MF.c H5MM.c H5O.c H5Ocomp.c \
- H5Ocont.c H5Odtype.c H5Oefl.c H5Olayout.c H5Oname.c H5Onull.c \
- H5Osdspace.c H5Oshared.c H5Ostab.c H5P.c H5S.c H5Ssimp.c H5T.c \
- H5Tconv.c H5Tinit.c H5V.c H5Z.c @PARALLEL_SRC@
+LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5D.c H5E.c H5F.c H5Farray.c H5Fcore.c \
+ H5Ffamily.c H5Fistore.c H5Flow.c H5Fsec2.c H5Fsplit.c H5Fstdio.c H5G.c \
+ H5Gent.c H5Gnode.c H5Gstab.c H5HG.c H5HL.c H5I.c H5MF.c H5MM.c \
+ H5O.c H5Oattr.c H5Ocomp.c H5Ocont.c H5Odtype.c H5Oefl.c H5Olayout.c \
+ H5Oname.c H5Onull.c H5Osdspace.c H5Oshared.c H5Ostab.c H5P.c H5S.c \
+ H5Ssimp.c H5T.c H5Tconv.c H5Tinit.c H5V.c H5Z.c @PARALLEL_SRC@
LIB_OBJ=$(LIB_SRC:.c=.o)
@@ -33,16 +33,17 @@ PROG_SRC=debug.c h5ls.c
PROG_OBJ=$(PROG_SRC:.c=.o)
# Public header files (to be installed)...
-PUB_HDR=H5public.h H5ACpublic.h H5Bpublic.h H5Ppublic.h H5Dpublic.h \
- H5Epublic.h H5Fpublic.h H5Gpublic.h H5HGpublic.h H5HLpublic.h \
- H5Ipublic.h H5MFpublic.h H5MMpublic.h H5Opublic.h H5Spublic.h \
- H5Tpublic.h H5Zpublic.h H5config.h hdf5.h
+PUB_HDR=H5public.h H5Apublic.h H5ACpublic.h H5Bpublic.h H5Ppublic.h \
+ H5Dpublic.h H5Epublic.h H5Fpublic.h H5Gpublic.h H5HGpublic.h H5HLpublic.h \
+ H5Ipublic.h H5MFpublic.h H5MMpublic.h H5Opublic.h H5Spublic.h \
+ H5Tpublic.h H5config.h hdf5.h
# Other header files (not to be installed)...
-PRIVATE_HDR=H5private.h H5ACprivate.h H5Bprivate.h H5Pprivate.h H5Dprivate.h \
- H5Eprivate.h H5Fprivate.h H5Gprivate.h H5Gpkg.h H5HGprivate.h \
- H5HLprivate.h H5Iprivate.h H5MFprivate.h H5MMprivate.h H5Oprivate.h \
- H5Sprivate.h H5Tprivate.h H5Tpkg.h H5Vprivate.h H5Zprivate.h
+PRIVATE_HDR=H5private.h H5Aprivate.h H5Apkg.h H5ACprivate.h H5Bprivate.h \
+ H5Pprivate.h H5Dprivate.h H5Dpkg.h H5Eprivate.h H5Fprivate.h H5Gprivate.h \
+ H5Gpkg.h H5HGprivate.h H5HLprivate.h H5Iprivate.h H5MFprivate.h \
+ H5MMprivate.h H5Oprivate.h H5Sprivate.h H5Tprivate.h H5Tpkg.h H5Vprivate.h \
+ H5Zprivate.h
# Number format detection
H5Tinit.c: H5detect
diff --git a/src/hdf5.h b/src/hdf5.h
index ce4ed62..a80945b 100644
--- a/src/hdf5.h
+++ b/src/hdf5.h
@@ -19,6 +19,8 @@
#define _HDF5_H
#include <H5public.h>
+#include <H5Ipublic.h> /* IDs (this has to come near the top, to define hid_t) */
+#include <H5Apublic.h> /* Attributes */
#include <H5ACpublic.h> /* Metadata cache */
#include <H5Bpublic.h> /* B-trees */
#include <H5Dpublic.h> /* Datasets */
@@ -27,7 +29,6 @@
#include <H5Gpublic.h> /* Groups */
#include <H5HGpublic.h> /* Global heaps */
#include <H5HLpublic.h> /* Local heaps */
-#include <H5Ipublic.h> /* IDs */
#include <H5MFpublic.h> /* File memory management */
#include <H5MMpublic.h> /* Core memory management */
#include <H5Opublic.h> /* Object headers */