summaryrefslogtreecommitdiffstats
path: root/src/H5S.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5S.c')
-rw-r--r--src/H5S.c1294
1 files changed, 1294 insertions, 0 deletions
diff --git a/src/H5S.c b/src/H5S.c
new file mode 100644
index 0000000..c6f03b2
--- /dev/null
+++ b/src/H5S.c
@@ -0,0 +1,1294 @@
+/****************************************************************************
+* 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$ */
+
+#include <H5private.h> /* Generic Functions */
+#include <H5Aprivate.h> /* Atom Functions */
+#include <H5Eprivate.h> /* Error handling */
+#include <H5MMprivate.h> /* Memory Management functions */
+#include <H5Oprivate.h> /*object headers */
+#include <H5Sprivate.h> /* Data-space functions */
+
+/* Interface initialization */
+#define PABLO_MASK H5S_mask
+#define INTERFACE_INIT H5S_init_interface
+static intn interface_initialize_g = FALSE;
+static herr_t H5S_init_interface(void);
+static void H5S_term_interface(void);
+
+
+/*--------------------------------------------------------------------------
+NAME
+ H5S_init_interface -- Initialize interface-specific information
+USAGE
+ herr_t H5S_init_interface()
+
+RETURNS
+ SUCCEED/FAIL
+DESCRIPTION
+ Initializes any interface-specific data or routines.
+
+--------------------------------------------------------------------------*/
+static herr_t
+H5S_init_interface(void)
+{
+ herr_t ret_value = SUCCEED;
+ FUNC_ENTER(H5S_init_interface, FAIL);
+
+ /* Initialize the atom group for the file IDs */
+ if ((ret_value = H5A_init_group(H5_DATASPACE, H5A_DATASPACEID_HASHSIZE,
+ H5S_RESERVED_ATOMS,
+ (herr_t (*)(void *)) H5S_close)) != FAIL) {
+ ret_value = H5_add_exit(&H5S_term_interface);
+ }
+ FUNC_LEAVE(ret_value);
+}
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_term_interface
+ PURPOSE
+ Terminate various H5S objects
+ USAGE
+ void H5S_term_interface()
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ Release the atom group and any other resources allocated.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Can't report errors...
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static void
+H5S_term_interface(void)
+{
+ H5A_destroy_group(H5_DATASPACE);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Screate_simple
+ *
+ * Purpose: Creates a new simple data space object and opens it for
+ * access. The DIMS argument is the size of the simple dataset
+ * and the MAXDIMS argument is the upper limit on the size of
+ * the dataset. MAXDIMS may be the null pointer in which case
+ * the upper limit is the same as DIMS. If an element of
+ * MAXDIMS is zero then the corresponding dimension is unlimited,
+ * otherwise no element of MAXDIMS should be smaller than the
+ * corresponding element of DIMS.
+ *
+ * Return: Success: The ID for the new simple data space object.
+ *
+ * Failure: FAIL
+ *
+ * Errors:
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, January 27, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5Screate_simple(int rank, const size_t *dims, const size_t *maxdims)
+{
+ H5S_t *ds = NULL;
+ hid_t ret_value = FAIL;
+ int i;
+
+ FUNC_ENTER(H5Screate, FAIL);
+
+ /* Check arguments */
+ if (rank<0) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL,
+ "dimensionality cannot be negative");
+ }
+ if (!dims) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL,
+ "no dimensions specified");
+ }
+ if (maxdims) {
+ for (i=0; i<rank; i++) {
+ if (maxdims[i] && maxdims[i]<dims[i]) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL,
+ "maxdims is smaller than dims");
+ }
+ }
+ }
+
+ /* Create a new data space */
+ ds = H5MM_xcalloc(1, sizeof(H5S_t));
+#ifdef LATER /* QAK */
+ if(rank>0) /* for creating simple dataspace */
+ {
+#endif /* LATER */
+ ds->type = H5S_SIMPLE;
+ ds->hslab_def = FALSE; /* no hyperslab defined currently */
+
+ /* Initialize rank and dimensions */
+ ds->u.simple.rank = rank;
+
+ ds->u.simple.size = H5MM_xcalloc(1, rank*sizeof(size_t));
+ HDmemcpy(ds->u.simple.size, dims, rank*sizeof(size_t));
+
+ if (maxdims) {
+ ds->u.simple.max = H5MM_xcalloc(1, rank*sizeof(size_t));
+ HDmemcpy (ds->u.simple.max, maxdims, rank*sizeof(size_t));
+ }
+#ifdef LATER /* QAK */
+ } /* end if */
+ else /* rank==0, for scalar data space */
+ {
+ ds->type = H5S_SCALAR;
+ } /* end else */
+#endif /* LATER */
+
+ /* Register the new data space and get an ID for it */
+ if ((ret_value = H5A_register(H5_DATASPACE, ds)) < 0) {
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL,
+ "unable to register data space for ID");
+ }
+
+ done:
+ if (ret_value < 0) {
+ H5MM_xfree(ds);
+ }
+ FUNC_LEAVE(ret_value);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Sclose
+ *
+ * Purpose: Release access to a data space object.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Errors:
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, December 9, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Sclose(hid_t space_id)
+{
+ FUNC_ENTER(H5Sclose, FAIL);
+
+ /* Check args */
+ if (H5_DATASPACE != H5A_group(space_id) ||
+ NULL == H5A_object(space_id)) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space");
+ }
+ /* When the reference count reaches zero the resources are freed */
+ if (H5A_dec_ref(space_id) < 0) {
+ HRETURN_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "problem freeing id");
+ }
+ FUNC_LEAVE(SUCCEED);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_close
+ *
+ * Purpose: Releases all memory associated with a data space.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, December 9, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5S_close(H5S_t *ds)
+{
+ FUNC_ENTER(H5S_close, FAIL);
+
+ assert(ds);
+
+ switch (ds->type) {
+ case H5S_SCALAR:
+ /*void */
+ break;
+
+ case H5S_SIMPLE:
+ H5MM_xfree(ds->u.simple.size);
+ H5MM_xfree(ds->u.simple.max);
+ H5MM_xfree(ds->u.simple.perm);
+ break;
+
+ case H5S_COMPLEX:
+ /* nothing */
+ break;
+
+ default:
+ assert("unknown data space type" && 0);
+ break;
+ }
+ if(ds->hslab_def==TRUE) {
+ H5MM_xfree(ds->h.start);
+ H5MM_xfree(ds->h.count);
+ H5MM_xfree(ds->h.stride);
+ } /* end if */
+ H5MM_xfree(ds);
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Scopy
+ *
+ * Purpose: Copies a dataspace.
+ *
+ * Return: Success: ID of the new dataspace
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Friday, January 30, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5Scopy (hid_t space_id)
+{
+ H5S_t *src = NULL;
+ H5S_t *dst = NULL;
+ hid_t ret_value = FAIL;
+
+ FUNC_ENTER (H5Scopy, FAIL);
+
+ /* Check args */
+ if (H5_DATASPACE!=H5A_group (space_id) ||
+ NULL==(src=H5A_object (space_id))) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space");
+ }
+
+ /* Copy */
+ if (NULL==(dst=H5S_copy (src))) {
+ HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL,
+ "unable to copy data space");
+ }
+
+ /* Atomize */
+ if ((ret_value=H5A_register (H5_DATASPACE, dst))<0) {
+ HRETURN_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL,
+ "unable to register data space atom");
+ }
+
+ FUNC_LEAVE (ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_copy
+ *
+ * Purpose: Copies a data space.
+ *
+ * Return: Success: A pointer to a new copy of SRC
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, December 4, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5S_t *
+H5S_copy(const H5S_t *src)
+{
+ H5S_t *dst = NULL;
+ int i;
+
+ FUNC_ENTER(H5S_copy, NULL);
+
+ dst = H5MM_xmalloc(sizeof(H5S_t));
+ *dst = *src;
+
+ switch (dst->type) {
+ case H5S_SCALAR:
+ /*void */
+ break;
+
+ case H5S_SIMPLE:
+ if (dst->u.simple.size) {
+ dst->u.simple.size = H5MM_xmalloc(dst->u.simple.rank *
+ sizeof(dst->u.simple.size[0]));
+ for (i = 0; i < dst->u.simple.rank; i++) {
+ dst->u.simple.size[i] = src->u.simple.size[i];
+ }
+ }
+ if (dst->u.simple.max) {
+ dst->u.simple.max = H5MM_xmalloc(dst->u.simple.rank *
+ sizeof(dst->u.simple.max[0]));
+ for (i = 0; i < dst->u.simple.rank; i++) {
+ dst->u.simple.max[i] = src->u.simple.max[i];
+ }
+ }
+ if (dst->u.simple.perm) {
+ dst->u.simple.perm = H5MM_xmalloc(dst->u.simple.rank *
+ sizeof(dst->u.simple.perm[0]));
+ for (i = 0; i < dst->u.simple.rank; i++) {
+ dst->u.simple.perm[i] = src->u.simple.perm[i];
+ }
+ }
+ break;
+
+ case H5S_COMPLEX:
+ /*void */
+ break;
+
+ default:
+ assert("unknown data space type" && 0);
+ break;
+ }
+
+ FUNC_LEAVE(dst);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Sget_npoints
+ *
+ * Purpose: Determines how many data points a data set has.
+ *
+ * Return: Success: Number of data points in the data set.
+ *
+ * Failure: 0
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, December 9, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+size_t
+H5Sget_npoints(hid_t space_id)
+{
+ H5S_t *ds = NULL;
+ size_t ret_value = 0;
+
+ FUNC_ENTER(H5Sget_npoints, 0);
+
+ /* Check args */
+ if (H5_DATASPACE != H5A_group(space_id) ||
+ NULL == (ds = H5A_object(space_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a data space");
+ }
+ ret_value = H5S_get_npoints(ds);
+
+ FUNC_LEAVE(ret_value);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_get_npoints
+ *
+ * Purpose: Determines how many data points a data set has.
+ *
+ * Return: Success: Number of data points in the data set.
+ *
+ * Failure: 0
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, December 9, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+size_t
+H5S_get_npoints(const H5S_t *ds)
+{
+ size_t ret_value = 0;
+ intn i;
+
+ FUNC_ENTER(H5S_get_npoints, 0);
+
+ /* check args */
+ assert(ds);
+
+ switch (ds->type) {
+ case H5S_SCALAR:
+ ret_value = 1;
+ break;
+
+ case H5S_SIMPLE:
+ /*
+ * Count the elements selected by the hypeslab if there is one,
+ * otherwise count all the elements.
+ */
+ if (ds->hslab_def) {
+ for (ret_value=1, i=0; i<ds->u.simple.rank; i++) {
+ ret_value *= ds->h.count[i];
+ }
+ } else {
+ for (ret_value=1, i=0; i<ds->u.simple.rank; i++) {
+ ret_value *= ds->u.simple.size[i];
+ }
+ }
+ break;
+
+ case H5S_COMPLEX:
+ HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, 0,
+ "complex data spaces are not supported yet");
+
+ default:
+ assert("unknown data space class" && 0);
+ HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, 0,
+ "internal error (unknown data space class)");
+ }
+
+ FUNC_LEAVE(ret_value);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Sget_ndims
+ *
+ * Purpose: Determines the dimensionality of a data space.
+ *
+ * Return: Success: The number of dimensions in a data space.
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, December 11, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5Sget_ndims(hid_t space_id)
+{
+ H5S_t *ds = NULL;
+ intn ret_value = 0;
+
+ FUNC_ENTER(H5Sget_ndims, FAIL);
+
+ /* Check args */
+ if (H5_DATASPACE != H5A_group(space_id) ||
+ NULL == (ds = H5A_object(space_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space");
+ }
+ ret_value = H5S_get_ndims(ds);
+
+ FUNC_LEAVE(ret_value);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_get_ndims
+ *
+ * Purpose: Returns the number of dimensions in a data space.
+ *
+ * Return: Success: Non-negative number of dimensions. Zero
+ * implies a scalar.
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, December 11, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+intn
+H5S_get_ndims(const H5S_t *ds)
+{
+ intn ret_value = FAIL;
+
+ FUNC_ENTER(H5S_get_ndims, FAIL);
+
+ /* check args */
+ assert(ds);
+
+ switch (ds->type) {
+ case H5S_SCALAR:
+ ret_value = 0;
+ break;
+
+ case H5S_SIMPLE:
+ ret_value = ds->u.simple.rank;
+ break;
+
+ case H5S_COMPLEX:
+ HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL,
+ "complex data spaces are not supported yet");
+
+ default:
+ assert("unknown data space class" && 0);
+ HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL,
+ "internal error (unknown data space class)");
+ }
+
+ FUNC_LEAVE(ret_value);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Sget_dims
+ *
+ * Purpose: Returns the size in each dimension of a data space DS through
+ * the DIMS argument.
+ *
+ * Return: Success: Number of dimensions, the same value as
+ * returned by H5Sget_ndims().
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, December 11, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5Sget_dims(hid_t space_id, size_t dims[]/*out*/)
+{
+
+ H5S_t *ds = NULL;
+ intn ret_value = 0;
+
+ FUNC_ENTER(H5Sget_dims, FAIL);
+
+ /* Check args */
+ if (H5_DATASPACE != H5A_group(space_id) ||
+ NULL == (ds = H5A_object(space_id))) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space");
+ }
+ if (!dims) {
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer");
+ }
+ ret_value = H5S_get_dims(ds, dims);
+
+ FUNC_LEAVE(ret_value);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_get_dims
+ *
+ * Purpose: Returns the size in each dimension of a data space. This
+ * function may not be meaningful for all types of data spaces.
+ *
+ * Return: Success: Number of dimensions. Zero implies scalar.
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, December 11, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+intn
+H5S_get_dims(const H5S_t *ds, size_t dims[])
+{
+ intn ret_value = FAIL;
+ intn i;
+
+ FUNC_ENTER(H5S_get_dims, FAIL);
+
+ /* check args */
+ assert(ds);
+ assert(dims);
+
+ switch (ds->type) {
+ case H5S_SCALAR:
+ ret_value = 0;
+ break;
+
+ case H5S_SIMPLE:
+ ret_value = ds->u.simple.rank;
+ for (i = 0; i < ret_value; i++) {
+ dims[i] = ds->u.simple.size[i];
+ }
+ break;
+
+ case H5S_COMPLEX:
+ HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL,
+ "complex data spaces are not supported yet");
+
+ default:
+ assert("unknown data space class" && 0);
+ HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL,
+ "internal error (unknown data space class)");
+ }
+
+ FUNC_LEAVE(ret_value);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_modify
+ *
+ * Purpose: Updates a data space by writing a message to an object
+ * header.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, December 9, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5S_modify(H5G_entry_t *ent, const H5S_t *ds)
+{
+ FUNC_ENTER(H5S_modify, FAIL);
+
+ assert(ent);
+ assert(ds);
+
+ switch (ds->type) {
+ case H5S_SCALAR:
+ HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL,
+ "scalar data spaces are not implemented yet");
+
+ case H5S_SIMPLE:
+ if (H5O_modify(ent, H5O_SDSPACE, 0, 0, &(ds->u.simple)) < 0) {
+ HRETURN_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL,
+ "can't update simple data space message");
+ }
+ break;
+
+ case H5S_COMPLEX:
+ HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL,
+ "complex data spaces are not implemented yet");
+
+ default:
+ assert("unknown data space class" && 0);
+ break;
+ }
+
+ FUNC_LEAVE(SUCCEED);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_read
+ *
+ * Purpose: Reads the data space from an object header.
+ *
+ * Return: Success: Pointer to a new data space.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, December 9, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+H5S_t *
+H5S_read(H5F_t *f, H5G_entry_t *ent)
+{
+ H5S_t *ds = NULL;
+
+ FUNC_ENTER(H5S_read, NULL);
+
+ /* check args */
+ assert(f);
+ assert(ent);
+
+ ds = H5MM_xcalloc(1, sizeof(H5S_t));
+
+ if (H5O_read(ent, H5O_SDSPACE, 0, &(ds->u.simple))) {
+ ds->type = H5S_SIMPLE;
+
+ } else {
+ ds->type = H5S_SCALAR;
+ }
+
+ FUNC_LEAVE(ds);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_cmp
+ *
+ * Purpose: Compares two data spaces.
+ *
+ * Return: Success: 0 if DS1 and DS2 are the same.
+ * <0 if DS1 is less than DS2.
+ * >0 if DS1 is greater than DS2.
+ *
+ * Failure: 0, never fails
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, December 10, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+intn
+H5S_cmp(const H5S_t *ds1, const H5S_t *ds2)
+{
+ intn i;
+
+ FUNC_ENTER(H5S_cmp, 0);
+
+ /* check args */
+ assert(ds1);
+ assert(ds2);
+
+ /* compare */
+ if (ds1->type < ds2->type)
+ HRETURN(-1);
+ if (ds1->type > ds2->type)
+ HRETURN(1);
+
+ switch (ds1->type) {
+ case H5S_SIMPLE:
+ if (ds1->u.simple.rank < ds2->u.simple.rank)
+ HRETURN(-1);
+ if (ds1->u.simple.rank > ds2->u.simple.rank)
+ HRETURN(1);
+
+ for (i = 0; i < ds1->u.simple.rank; i++) {
+ if (ds1->u.simple.size[i] < ds2->u.simple.size[i])
+ HRETURN(-1);
+ if (ds1->u.simple.size[i] > ds2->u.simple.size[i])
+ HRETURN(1);
+ }
+
+ /* don't compare max dimensions */
+
+ for (i = 0; i < ds1->u.simple.rank; i++) {
+ if ((ds1->u.simple.perm ? ds1->u.simple.perm[i] : i) <
+ (ds2->u.simple.perm ? ds2->u.simple.perm[i] : i))
+ HRETURN(-1);
+ if ((ds1->u.simple.perm ? ds2->u.simple.perm[i] : i) >
+ (ds2->u.simple.perm ? ds2->u.simple.perm[i] : i))
+ HRETURN(1);
+ }
+
+ /* Check if we should compare hyperslab definitions */
+ if(ds1->hslab_def==TRUE && ds2->hslab_def==TRUE) {
+ for (i = 0; i < ds1->u.simple.rank; i++) {
+ if (ds1->h.start[i] < ds2->h.start[i])
+ HRETURN(-1);
+ if (ds1->h.start[i] > ds2->h.start[i])
+ HRETURN(1);
+ if (ds1->h.count[i] < ds2->h.count[i])
+ HRETURN(-1);
+ if (ds1->h.count[i] > ds2->h.count[i])
+ HRETURN(1);
+ if (ds1->h.stride[i] < ds2->h.stride[i])
+ HRETURN(-1);
+ if (ds1->h.stride[i] > ds2->h.stride[i])
+ HRETURN(1);
+ }
+ } else {
+ if(ds1->hslab_def!=ds2->hslab_def)
+ HRETURN(ds1->hslab_def==TRUE ? 1 : -1);
+ }
+
+ break;
+
+ default:
+ assert("not implemented yet" && 0);
+ }
+
+ FUNC_LEAVE(0);
+}
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_is_simple
+ PURPOSE
+ Check if a dataspace is simple (internal)
+ USAGE
+ hbool_t H5S_is_simple(sdim)
+ H5S_t *sdim; IN: Pointer to dataspace object to query
+ RETURNS
+ TRUE/FALSE/FAIL
+ DESCRIPTION
+ This function determines the if a dataspace is "simple". ie. if it
+ has orthogonal, evenly spaced dimensions.
+--------------------------------------------------------------------------*/
+hbool_t
+H5S_is_simple(const H5S_t *sdim)
+{
+ hbool_t ret_value = FAIL;
+
+ FUNC_ENTER(H5S_is_simple, FAIL);
+
+ /* Check args and all the boring stuff. */
+ assert(sdim);
+ ret_value = sdim->type == H5S_SIMPLE ? TRUE : FALSE; /* Currently all dataspaces are simple, but check anyway */
+
+ FUNC_LEAVE(ret_value);
+}
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Sis_simple
+ PURPOSE
+ Check if a dataspace is simple
+ USAGE
+ hbool_t H5Sis_simple(sid)
+ hid_t sid; IN: ID of dataspace object to query
+ RETURNS
+ TRUE/FALSE/FAIL
+ DESCRIPTION
+ This function determines the if a dataspace is "simple". ie. if it
+ has orthogonal, evenly spaced dimensions.
+--------------------------------------------------------------------------*/
+hbool_t
+H5Sis_simple(hid_t sid)
+{
+ H5S_t *space = NULL; /* dataspace to modify */
+ hbool_t ret_value = FAIL;
+
+ FUNC_ENTER(H5Sis_simple, FAIL);
+
+ /* Check args and all the boring stuff. */
+ if ((space = H5A_object(sid)) == NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a data space");
+
+ ret_value = H5S_is_simple(space);
+
+ done:
+ if (ret_value == FAIL) { /* Error condition cleanup */
+
+ } /* end if */
+ /* Normal function cleanup */
+ FUNC_LEAVE(ret_value);
+}
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Sset_space
+ PURPOSE
+ Determine the size of a dataspace
+ USAGE
+ herr_t H5Sset_space(sid, rank, dims)
+ hid_t sid; IN: Dataspace object to query
+ intn rank; IN: # of dimensions for the dataspace
+ const size_t *dims; IN: Size of each dimension for the dataspace
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ This function sets the number and size of each dimension in the
+ dataspace. Setting RANK to a value of zero allows scalar objects to be
+ created. Dimensions are specified from slowest to fastest changing in the
+ DIMS array (i.e. 'C' order). Setting the size of a dimension to zero
+ indicates that the dimension is of unlimited size and should be allowed to
+ expand. Currently, only the first dimension in the array (the slowest) may
+ be unlimited in size.
+--------------------------------------------------------------------------*/
+herr_t
+H5Sset_space(hid_t sid, int rank, const size_t *dims)
+{
+ H5S_t *space = NULL; /* dataspace to modify */
+ intn u; /* local counting variable */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5Sset_space, FAIL);
+
+ /* Check args */
+ if ((space = H5A_object(sid)) == NULL)
+ HRETURN_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a data space");
+ if (rank > 0 && dims == NULL)
+ HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no dimensions specified");
+ if (rank<0)
+ HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid rank");
+ if (dims) {
+ for (u=0; u<rank; u++) {
+ if (dims[u]<=0) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL,
+ "invalid dimension size");
+ }
+ }
+ }
+
+ /* shift out of the previous state to a "simple" dataspace */
+ switch (space->type) {
+ case H5S_SCALAR:
+ case H5S_SIMPLE:
+ /* do nothing */
+ break;
+
+ case H5S_COMPLEX:
+ /*
+ * eventually this will destroy whatever "complex" dataspace info
+ * is retained, right now it's an error
+ */
+ /* Fall through to report error */
+
+ default:
+ HRETURN_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL,
+ "unknown data space class");
+ }
+ space->type = H5S_SIMPLE;
+
+ /* Reset hyperslab definition, if one is defined */
+ if(space->hslab_def==TRUE) {
+ H5MM_xfree(space->h.start);
+ H5MM_xfree(space->h.count);
+ H5MM_xfree(space->h.stride);
+ space->hslab_def=FALSE;
+ }
+
+ if (rank == 0) { /* scalar variable */
+ space->type = H5S_SCALAR;
+ space->u.simple.rank = 0; /* set to scalar rank */
+ if (space->u.simple.size != NULL)
+ space->u.simple.size = H5MM_xfree(space->u.simple.size);
+ if (space->u.simple.max != NULL)
+ space->u.simple.max = H5MM_xfree(space->u.simple.max);
+ if (space->u.simple.perm != NULL)
+ space->u.simple.max = H5MM_xfree(space->u.simple.perm);
+ } else {
+ /* Free the old space for now */
+ if (space->u.simple.size != NULL)
+ space->u.simple.size = H5MM_xfree(space->u.simple.size);
+ if (space->u.simple.max != NULL)
+ space->u.simple.max = H5MM_xfree(space->u.simple.max);
+ if (space->u.simple.perm != NULL)
+ space->u.simple.perm = H5MM_xfree(space->u.simple.perm);
+
+ /* Set the rank and copy the dims */
+ space->u.simple.rank = rank;
+ space->u.simple.size = H5MM_xcalloc(rank, sizeof(size_t));
+ HDmemcpy(space->u.simple.size, dims, sizeof(size_t) * rank);
+
+ }
+ FUNC_LEAVE(ret_value);
+}
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Sset_hyperslab
+ PURPOSE
+ Select a hyperslab from a simple dataspace
+ USAGE
+ herr_t H5Sset_hyperslab(sid, start, count, stride)
+ hid_t sid; IN: Dataspace object to select hyperslab from
+ const int *start; IN: Starting location for hyperslab to select
+ const size_t *count; IN: Number of elements in hyperslab
+ const size_t *stride; IN: Packing of elements in hyperslab
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ This function selects a hyperslab from a simple dataspace. The stride
+ array may be used to sub-sample the hyperslab chosen, a value of 1 in each
+ position of the stride array selects contiguous elements in the array,
+ a value of 2 selects every other element, etc. If the stride parameter is
+ set to NULL, a contiguous hyperslab is chosen. The values in the start and
+ count arrays may be negative, to allow for selecting hyperslabs in chunked
+ datasets which extend in arbitrary directions.
+--------------------------------------------------------------------------*/
+herr_t
+H5Sset_hyperslab(hid_t sid, const int *start, const size_t *count, const size_t *stride)
+{
+ H5S_t *space = NULL; /* dataspace to modify */
+ size_t *tmp_stride=NULL; /* temp. copy of stride */
+ intn u; /* local counting variable */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER(H5Sset_hyperslab, FAIL);
+
+ /* Get the object */
+ if (H5_DATASPACE != H5A_group(sid) || (space = H5A_object(sid)) == NULL)
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a data space");
+ if (start == NULL || count==NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
+ "invalid hyperslab selected");
+
+ /* We can't modify other types of dataspaces currently, so error out */
+ if (space->type!=H5S_SIMPLE)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL,
+ "unknown dataspace type");
+
+ /* Set up stride values for later use */
+ tmp_stride= H5MM_xmalloc(space->u.simple.rank*sizeof(tmp_stride[0]));
+ for (u=0; u<space->u.simple.rank; u++) {
+ tmp_stride[u] = stride ? stride[u] : 1;
+ }
+
+ /* Range check arguments */
+ for (u=0; u<space->u.simple.rank; u++) {
+ if (start[u]<0 || start[u]>=space->u.simple.size[u]) {
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL,
+ "hyperslab bounds out of range");
+ }
+ if (start[u]<0 ||
+ start[u]+(count[u]*tmp_stride[u])>space->u.simple.size[u]) {
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL,
+ "hyperslab bounds out of range");
+ }
+ }
+
+ /* Allocate space for the hyperslab information */
+ if (NULL==space->h.start) {
+ space->h.start= H5MM_xcalloc(space->u.simple.rank,sizeof(intn));
+ space->h.count= H5MM_xcalloc(space->u.simple.rank,sizeof(size_t));
+ space->h.stride= H5MM_xcalloc(space->u.simple.rank,sizeof(size_t));
+ }
+
+ /* Build hyperslab */
+ for(u=0; u<space->u.simple.rank; u++) {
+ space->h.start[u] = start[u];
+ space->h.count[u] = count[u];
+ space->h.stride[u] = tmp_stride[u];
+ }
+ space->hslab_def=TRUE;
+
+done:
+ if (ret_value == FAIL) { /* Error condition cleanup */
+
+ } /* end if */
+
+ /* Normal function cleanup */
+ H5MM_xfree(tmp_stride);
+ FUNC_LEAVE(ret_value);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Sget_hyperslab
+ *
+ * Purpose: Retrieves information about the hyperslab from a simple data
+ * space. If no hyperslab has been defined then the hyperslab
+ * is the same as the entire array.
+ *
+ * Return: Success: Hyperslab dimensionality.
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, January 28, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5Sget_hyperslab (hid_t sid, int offset[]/*out*/, size_t size[]/*out*/,
+ size_t stride[]/*out*/)
+{
+ const H5S_t *ds = NULL;
+ intn ret_value = FAIL;
+
+ FUNC_ENTER (H5Sget_hyperslab, FAIL);
+
+ /* Check args */
+ if (H5_DATASPACE!=H5A_group (sid) || NULL==(ds=H5A_object (sid))) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space");
+ }
+
+ /* Get hyperslab info */
+ if ((ret_value=H5S_get_hyperslab (ds, offset, size, stride))<0) {
+ HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL,
+ "unable to retrieve hyperslab information");
+ }
+
+ FUNC_LEAVE (ret_value);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_get_hyperslab
+ *
+ * Purpose: Retrieves information about the hyperslab from a simple data
+ * space. If no hyperslab has been defined then the hyperslab
+ * is the same as the entire array.
+ *
+ * Return: Success: Hyperslab dimensionality.
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, January 28, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+intn
+H5S_get_hyperslab (const H5S_t *ds, int offset[]/*out*/,
+ size_t size[]/*out*/, size_t stride[]/*out*/)
+{
+ intn i;
+ intn ret_value = FAIL;
+
+ FUNC_ENTER (H5S_get_hyperslab, FAIL);
+
+ /* Check args */
+ assert (ds);
+ switch (ds->type) {
+ case H5S_SCALAR:
+ break;
+
+ case H5S_SIMPLE:
+ if (ds->hslab_def) {
+ for (i=0; i<ds->u.simple.rank; i++) {
+ if (offset) offset[i] = ds->h.start[i];
+ if (size) size[i] = ds->h.count[i];
+ if (stride) stride[i] = ds->h.stride[i];
+ }
+ } else {
+ for (i=0; i<ds->u.simple.rank; i++) {
+ if (offset) offset[i] = 0;
+ if (size) size[i] = ds->u.simple.size[i];
+ if (stride) stride[i] = 1;
+ }
+ }
+ ret_value = ds->u.simple.rank;
+ break;
+
+ case H5S_COMPLEX: /*fall through*/
+ default:
+ HRETURN_ERROR (H5E_DATASPACE, H5E_UNSUPPORTED, FAIL,
+ "hyperslabs not supported for this type of space");
+ }
+
+ FUNC_LEAVE (ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_find
+ *
+ * Purpose: Given two data spaces (MEM_SPACE and FILE_SPACE) this
+ * function locates the data space conversion functions and
+ * initializes CONV to point to them. The CONV contains
+ * function pointers for converting in either direction.
+ *
+ * Return: Success: Pointer to a data space conversion callback
+ * list.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, January 21, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+const H5S_conv_t *
+H5S_find (const H5S_t *mem_space, const H5S_t *file_space)
+{
+ static H5S_conv_t _conv;
+ static const H5S_conv_t *conv = NULL;
+
+ FUNC_ENTER (H5S_find, NULL);
+
+ /* Check args */
+ assert (mem_space && H5S_SIMPLE==mem_space->type);
+ assert (file_space && H5S_SIMPLE==file_space->type);
+
+ /*
+ * We can't do conversion if the source and destination select a
+ * different number of data points.
+ */
+ if (H5S_get_npoints (mem_space) != H5S_get_npoints (file_space)) {
+ HRETURN_ERROR (H5E_DATASPACE, H5E_BADRANGE, NULL,
+ "memory and file data spaces are different sizes");
+ }
+
+ /*
+ * Initialize pointers. This will eventually be a table lookup based
+ * on the source and destination data spaces, similar to H5T_find(), but
+ * for now we only support simple data spaces.
+ */
+ if (!conv) {
+ _conv.init = H5S_simp_init;
+ _conv.fgath = H5S_simp_fgath;
+ _conv.mscat = H5S_simp_mscat;
+ _conv.mgath = H5S_simp_mgath;
+ _conv.fscat = H5S_simp_fscat;
+ conv = &_conv;
+ }
+
+ FUNC_LEAVE (conv);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_extend
+ *
+ * Purpose: Extend the dimensions of a data space.
+ *
+ * Return: Success: Number of dimensions whose size increased.
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Friday, January 30, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+intn
+H5S_extend (H5S_t *space, const size_t *size)
+{
+ intn i, ret_value=0;
+
+ FUNC_ENTER (H5S_extend, FAIL);
+
+ /* Check args */
+ assert (space && H5S_SIMPLE==space->type);
+ assert (size);
+
+ for (i=0; i<space->u.simple.rank; i++) {
+ if (space->u.simple.size[i]<size[i]) {
+ if (space->u.simple.max &&
+ H5S_UNLIMITED!=space->u.simple.max[i] &&
+ space->u.simple.max[i]<size[i]) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL,
+ "dimension cannot be increased");
+ }
+ ret_value++;
+ }
+ }
+
+ /* Update */
+ if (ret_value) {
+ for (i=0; i<space->u.simple.rank; i++) {
+ if (space->u.simple.size[i]<size[i]) {
+ space->u.simple.size[i] = size[i];
+ }
+ }
+ }
+
+ FUNC_LEAVE (ret_value);
+}
+