#include "H5Smodule.h"
#include "H5private.h"
#include "H5Eprivate.h"
#include "H5CXprivate.h"
#include "H5Fprivate.h"
#include "H5FLprivate.h"
#include "H5Iprivate.h"
#include "H5MMprivate.h"
#include "H5Oprivate.h"
#include "H5Spkg.h"
#define H5S_ENCODE_VERSION 0
static htri_t H5S__is_simple(const H5S_t *sdim);
hbool_t H5_PKG_INIT_VAR = FALSE;
const unsigned H5O_sdspace_ver_bounds[] = {
H5O_SDSPACE_VERSION_1,
H5O_SDSPACE_VERSION_2,
H5O_SDSPACE_VERSION_LATEST
};
H5FL_DEFINE(H5S_extent_t);
H5FL_DEFINE(H5S_t);
H5FL_ARR_DEFINE(hsize_t, H5S_MAX_RANK);
static const H5I_class_t H5I_DATASPACE_CLS[1] = {{
H5I_DATASPACE,
0,
2,
(H5I_free_t)H5S_close
}};
static hbool_t H5S_top_package_initialize_s = FALSE;
herr_t
H5S__init_package(void)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
if(H5I_register_type(H5I_DATASPACE_CLS) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize dataspace ID class")
H5S_top_package_initialize_s = TRUE;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
int
H5S_top_term_package(void)
{
int n = 0;
FUNC_ENTER_NOAPI_NOINIT_NOERR
if(H5S_top_package_initialize_s) {
if(H5I_nmembers(H5I_DATASPACE) > 0) {
(void)H5I_clear_type(H5I_DATASPACE, FALSE, FALSE);
n++;
}
if(0 == n)
H5S_top_package_initialize_s = FALSE;
}
FUNC_LEAVE_NOAPI(n)
}
int
H5S_term_package(void)
{
int n = 0;
FUNC_ENTER_NOAPI_NOINIT_NOERR
if(H5_PKG_INIT_VAR) {
HDassert(0 == H5I_nmembers(H5I_DATASPACE));
HDassert(FALSE == H5S_top_package_initialize_s);
n += (H5I_dec_type_ref(H5I_DATASPACE) > 0);
if(0 == n)
H5_PKG_INIT_VAR = FALSE;
}
FUNC_LEAVE_NOAPI(n)
}
herr_t
H5S_get_validated_dataspace(hid_t space_id, const H5S_t **space)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(space);
if(space_id < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid space_id (ID cannot be a negative number)")
if(H5S_ALL == space_id)
*space = NULL;
else {
if(NULL == (*space = (const H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "space_id is not a dataspace ID")
if(H5S_SELECT_VALID(*space) != TRUE)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection + offset not within extent")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5S_t *
H5S_create(H5S_class_t type)
{
H5S_t *new_ds = NULL;
H5S_t *ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
if(NULL == (new_ds = H5FL_CALLOC(H5S_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
new_ds->extent.type = type;
if(type == H5S_NULL)
new_ds->extent.version = H5O_SDSPACE_VERSION_2;
else
new_ds->extent.version = H5O_SDSPACE_VERSION_1;
new_ds->extent.rank = 0;
new_ds->extent.size = new_ds->extent.max = NULL;
switch(type) {
case H5S_SCALAR:
new_ds->extent.nelem = 1;
break;
case H5S_SIMPLE:
case H5S_NULL:
new_ds->extent.nelem = 0;
break;
case H5S_NO_CLASS:
default:
HDassert("unknown dataspace (extent) type" && 0);
break;
}
if(H5S_select_all(new_ds, FALSE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection")
new_ds->select.sel_info.hslab = NULL;
if(H5O_msg_reset_share(H5O_SDSPACE_ID, &(new_ds->extent.sh_loc)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRESET, NULL, "unable to reset shared component info")
ret_value = new_ds;
done:
if(ret_value == NULL)
if(new_ds && H5S_close(new_ds) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, NULL, "unable to release dataspace")
FUNC_LEAVE_NOAPI(ret_value)
}
hid_t
H5Screate(H5S_class_t type)
{
H5S_t *new_ds = NULL;
hid_t ret_value;
FUNC_ENTER_API(FAIL)
H5TRACE1("i", "Sc", type);
if(type <= H5S_NO_CLASS || type > H5S_NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid dataspace type")
if(NULL == (new_ds = H5S_create(type)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace")
if((ret_value = H5I_register(H5I_DATASPACE, new_ds, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom")
done:
if(ret_value < 0)
if(new_ds && H5S_close(new_ds) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace")
FUNC_LEAVE_API(ret_value)
}
herr_t
H5S__extent_release(H5S_extent_t *extent)
{
FUNC_ENTER_PACKAGE_NOERR
HDassert(extent);
if(extent->type == H5S_SIMPLE) {
if(extent->size)
extent->size = H5FL_ARR_FREE(hsize_t, extent->size);
if(extent->max)
extent->max = H5FL_ARR_FREE(hsize_t, extent->max);
}
extent->rank = 0;
extent->nelem = 0;
FUNC_LEAVE_NOAPI(SUCCEED)
}
herr_t
H5S_close(H5S_t *ds)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(ds);
if(H5S_SELECT_RELEASE(ds) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace selection")
if(H5S__extent_release(&ds->extent) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace extent")
done:
H5FL_FREE(H5S_t, ds);
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5Sclose(hid_t space_id)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", space_id);
if(NULL == H5I_object_verify(space_id, H5I_DATASPACE))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
if(H5I_dec_app_ref(space_id) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "problem freeing id")
done:
FUNC_LEAVE_API(ret_value)
}
hid_t
H5Scopy(hid_t space_id)
{
H5S_t *src = NULL;
H5S_t *dst = NULL;
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE1("i", "i", space_id);
if(NULL == (src = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
if(NULL == (dst = H5S_copy(src, FALSE, TRUE)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, H5I_INVALID_HID, "unable to copy dataspace")
if((ret_value = H5I_register (H5I_DATASPACE, dst, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace atom")
done:
if(ret_value < 0)
if(dst && H5S_close(dst) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, H5I_INVALID_HID, "unable to release dataspace")
FUNC_LEAVE_API(ret_value)
}
herr_t
H5Sextent_copy(hid_t dst_id,hid_t src_id)
{
H5S_t *src;
H5S_t *dst;
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "ii", dst_id, src_id);
if(NULL == (src = (H5S_t *)H5I_object_verify(src_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
if(NULL == (dst = (H5S_t *)H5I_object_verify(dst_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
if(H5S_extent_copy(dst, src) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy extent")
done:
FUNC_LEAVE_API(ret_value)
}
herr_t
H5S_extent_copy(H5S_t *dst, const H5S_t *src)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(dst);
HDassert(src);
if(H5S__extent_copy_real(&(dst->extent), &(src->extent), TRUE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy extent")
if(H5S_SEL_ALL == H5S_GET_SELECT_TYPE(dst))
if(H5S_select_all(dst, FALSE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5S__extent_copy_real(H5S_extent_t *dst, const H5S_extent_t *src, hbool_t copy_max)
{
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_PACKAGE
if(H5S__extent_release(dst) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace extent")
dst->type = src->type;
dst->version = src->version;
dst->nelem = src->nelem;
dst->rank = src->rank;
switch (src->type) {
case H5S_NULL:
case H5S_SCALAR:
dst->size = NULL;
dst->max = NULL;
break;
case H5S_SIMPLE:
if(src->size) {
dst->size = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)src->rank);
for(u = 0; u < src->rank; u++)
dst->size[u] = src->size[u];
}
else
dst->size = NULL;
if(copy_max && src->max) {
dst->max = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)src->rank);
for(u = 0; u < src->rank; u++)
dst->max[u] = src->max[u];
}
else
dst->max = NULL;
break;
case H5S_NO_CLASS:
default:
HDassert("unknown dataspace type" && 0);
break;
}
if(H5O_set_shared(&(dst->sh_loc), &(src->sh_loc)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy shared information")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5S_t *
H5S_copy(const H5S_t *src, hbool_t share_selection, hbool_t copy_max)
{
H5S_t *dst = NULL;
H5S_t *ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
if(NULL == (dst = H5FL_CALLOC(H5S_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
if(H5S__extent_copy_real(&(dst->extent), &(src->extent), copy_max) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy extent")
if(H5S_select_copy(dst, src, share_selection) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy select")
ret_value = dst;
done:
if(NULL == ret_value)
if(dst)
dst = H5FL_FREE(H5S_t, dst);
FUNC_LEAVE_NOAPI(ret_value)
}
hssize_t
H5S_get_simple_extent_npoints(const H5S_t *ds)
{
hssize_t ret_value = -1;
FUNC_ENTER_NOAPI(-1)
HDassert(ds);
ret_value = (hssize_t)ds->extent.nelem;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
hssize_t
H5Sget_simple_extent_npoints(hid_t space_id)
{
H5S_t *ds;
hssize_t ret_value;
FUNC_ENTER_API(FAIL)
H5TRACE1("Hs", "i", space_id);
if(NULL == (ds = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
ret_value = (hssize_t)H5S_GET_EXTENT_NPOINTS(ds);
done:
FUNC_LEAVE_API(ret_value)
}
hsize_t
H5S_get_npoints_max(const H5S_t *ds)
{
unsigned u;
hsize_t ret_value = 0;
FUNC_ENTER_NOAPI(0)
HDassert(ds);
switch(H5S_GET_EXTENT_TYPE(ds)) {
case H5S_NULL:
ret_value = 0;
break;
case H5S_SCALAR:
ret_value = 1;
break;
case H5S_SIMPLE:
if(ds->extent.max) {
for(ret_value = 1, u = 0; u < ds->extent.rank; u++) {
if(H5S_UNLIMITED == ds->extent.max[u]) {
ret_value = HSIZET_MAX;
break;
}
else
ret_value *= ds->extent.max[u];
}
}
else
for(ret_value = 1, u = 0; u < ds->extent.rank; u++)
ret_value *= ds->extent.size[u];
break;
case H5S_NO_CLASS:
default:
HDassert("unknown dataspace class" && 0);
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, 0, "internal error (unknown dataspace class)")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
int
H5Sget_simple_extent_ndims(hid_t space_id)
{
H5S_t *ds;
int ret_value = -1;
FUNC_ENTER_API((-1))
H5TRACE1("Is", "i", space_id);
if(NULL == (ds = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not a dataspace")
ret_value = (int)H5S_GET_EXTENT_NDIMS(ds);
done:
FUNC_LEAVE_API(ret_value)
}
int
H5S_get_simple_extent_ndims(const H5S_t *ds)
{
int ret_value = -1;
FUNC_ENTER_NOAPI(FAIL)
HDassert(ds);
switch(H5S_GET_EXTENT_TYPE(ds)) {
case H5S_NULL:
case H5S_SCALAR:
case H5S_SIMPLE:
ret_value = (int)ds->extent.rank;
break;
case H5S_NO_CLASS:
default:
HDassert("unknown dataspace class" && 0);
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "internal error (unknown dataspace class)")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
int
H5Sget_simple_extent_dims(hid_t space_id, hsize_t dims[], hsize_t maxdims[])
{
H5S_t *ds;
int ret_value = -1;
FUNC_ENTER_API((-1))
H5TRACE3("Is", "ixx", space_id, dims, maxdims);
if(NULL == (ds = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not a dataspace")
ret_value = H5S_get_simple_extent_dims(ds, dims, maxdims);
done:
FUNC_LEAVE_API(ret_value)
}
int
H5S_extent_get_dims(const H5S_extent_t *ext, hsize_t dims[], hsize_t max_dims[])
{
int i;
int ret_value = -1;
FUNC_ENTER_NOAPI(FAIL)
HDassert(ext);
switch(ext->type) {
case H5S_NULL:
case H5S_SCALAR:
ret_value = 0;
break;
case H5S_SIMPLE:
ret_value = (int)ext->rank;
for(i = 0; i < ret_value; i++) {
if(dims)
dims[i] = ext->size[i];
if(max_dims) {
if(ext->max)
max_dims[i] = ext->max[i];
else
max_dims[i] = ext->size[i];
}
}
break;
case H5S_NO_CLASS:
default:
HDassert("unknown dataspace class" && 0);
HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "internal error (unknown dataspace class)")
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
int
H5S_get_simple_extent_dims(const H5S_t *ds, hsize_t dims[], hsize_t max_dims[])
{
int ret_value = -1;
FUNC_ENTER_NOAPI(FAIL)
HDassert(ds);
if((ret_value = H5S_extent_get_dims(&ds->extent, dims, max_dims)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't retrieve dataspace extent dims")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5S_write(H5F_t *f, H5O_t *oh, unsigned update_flags, H5S_t *ds)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(oh);
HDassert(ds);
HDassert(H5S_GET_EXTENT_TYPE(ds) >= 0);
if(H5O_msg_write_oh(f, oh, H5O_SDSPACE_ID, 0, update_flags, &(ds->extent)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update simple dataspace message")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5S_append(H5F_t *f, H5O_t *oh, H5S_t *ds)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(oh);
HDassert(ds);
HDassert(H5S_GET_EXTENT_TYPE(ds) >= 0);
if(H5O_msg_append_oh(f, oh, H5O_SDSPACE_ID, 0, 0, &(ds->extent)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't add simple dataspace message")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5S_t *
H5S_read(const H5O_loc_t *loc)
{
H5S_t *ds = NULL;
H5S_t *ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
HDassert(loc);
if(NULL == (ds = H5FL_CALLOC(H5S_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
if(NULL == H5O_msg_read(loc, H5O_SDSPACE_ID, &(ds->extent)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to load dataspace info from dataset header")
if(H5S_select_all(ds, FALSE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection")
ret_value = ds;
done:
if(ret_value == NULL)
if(ds != NULL)
ds = H5FL_FREE(H5S_t, ds);
FUNC_LEAVE_NOAPI(ret_value)
}
static htri_t
H5S__is_simple(const H5S_t *sdim)
{
htri_t ret_value = FAIL;
FUNC_ENTER_STATIC_NOERR
HDassert(sdim);
ret_value = (H5S_GET_EXTENT_TYPE(sdim) == H5S_SIMPLE ||
H5S_GET_EXTENT_TYPE(sdim) == H5S_SCALAR) ? TRUE : FALSE;
FUNC_LEAVE_NOAPI(ret_value)
}
htri_t
H5Sis_simple(hid_t space_id)
{
H5S_t *space;
htri_t ret_value;
FUNC_ENTER_API(FAIL)
H5TRACE1("t", "i", space_id);
if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a dataspace")
ret_value = H5S__is_simple(space);
done:
FUNC_LEAVE_API(ret_value)
}
herr_t
H5Sset_extent_simple(hid_t space_id, int rank, const hsize_t dims[],
const hsize_t max[])
{
H5S_t *space;
int u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
H5TRACE4("e", "iIs*[a1]h*[a1]h", space_id, rank, dims, max);
if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a dataspace")
if(rank > 0 && dims == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no dimensions specified")
if(rank < 0 || rank > H5S_MAX_RANK)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid rank")
if(dims)
for(u = 0; u < rank; u++)
if(H5S_UNLIMITED == dims[u])
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "current dimension must have a specific size, not H5S_UNLIMITED")
if(max != NULL) {
if(dims == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "maximum dimension specified, but no current dimensions specified")
for(u = 0; u < rank; u++)
if(max[u] != H5S_UNLIMITED && max[u] < dims[u])
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid maximum dimension size")
}
if(H5S_set_extent_simple(space, (unsigned)rank, dims, max) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set simple extent")
done:
FUNC_LEAVE_API(ret_value)
}
herr_t
H5S_set_extent_simple(H5S_t *space, unsigned rank, const hsize_t *dims,
const hsize_t *max)
{
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(rank <= H5S_MAX_RANK);
HDassert(0 == rank || dims);
if(H5S__extent_release(&space->extent) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "failed to release previous dataspace extent")
if(rank == 0) {
space->extent.type = H5S_SCALAR;
space->extent.nelem = 1;
space->extent.rank = 0;
}
else {
hsize_t nelem;
space->extent.type = H5S_SIMPLE;
space->extent.rank = rank;
space->extent.size = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)rank);
for(u = 0, nelem = 1; u < space->extent.rank; u++) {
space->extent.size[u] = dims[u];
nelem *= dims[u];
}
space->extent.nelem = nelem;
space->extent.max = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)rank);
if(max != NULL)
H5MM_memcpy(space->extent.max, max, sizeof(hsize_t) * rank);
else
for(u = 0; u < space->extent.rank; u++)
space->extent.max[u] = dims[u];
}
HDmemset(space->select.offset, 0, sizeof(hsize_t) * space->extent.rank);
space->select.offset_changed = FALSE;
if(H5S_GET_SELECT_TYPE(space) == H5S_SEL_ALL)
if(H5S_select_all(space, FALSE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
hid_t
H5Screate_simple(int rank, const hsize_t dims[], const hsize_t maxdims[])
{
H5S_t *space = NULL;
int i;
hid_t ret_value = H5I_INVALID_HID;
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE3("i", "Is*[a0]h*[a0]h", rank, dims, maxdims);
if(rank < 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dimensionality cannot be negative")
if(rank > H5S_MAX_RANK)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dimensionality is too large")
if(!dims && rank != 0)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid dataspace information")
for(i = 0; i < rank; i++) {
if(H5S_UNLIMITED == dims[i])
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "current dimension must have a specific size, not H5S_UNLIMITED")
if(maxdims && H5S_UNLIMITED != maxdims[i] && maxdims[i]<dims[i])
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "maxdims is smaller than dims")
}
if(NULL == (space = H5S_create_simple((unsigned)rank, dims, maxdims)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, H5I_INVALID_HID, "can't create simple dataspace")
if((ret_value = H5I_register (H5I_DATASPACE, space, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace ID")
done:
if(ret_value < 0)
if(space && H5S_close(space) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, H5I_INVALID_HID, "unable to release dataspace")
FUNC_LEAVE_API(ret_value)
}
H5S_t *
H5S_create_simple(unsigned rank, const hsize_t dims[], const hsize_t maxdims[])
{
H5S_t *ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
HDassert(rank <= H5S_MAX_RANK);
if(NULL == (ret_value = H5S_create(H5S_SIMPLE)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, NULL, "can't create simple dataspace")
if(H5S_set_extent_simple(ret_value, rank, dims, maxdims) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "can't set dimensions")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5Sencode(hid_t obj_id, void *buf, size_t *nalloc)
{
H5S_t *dspace;
hid_t temp_fapl_id = H5P_DEFAULT;
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
H5TRACE3("e", "i*x*z", obj_id, buf, nalloc);
if(NULL == (dspace = (H5S_t *)H5I_object_verify(obj_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
if(H5CX_set_apl(&temp_fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, TRUE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
if(H5S_encode(dspace, (unsigned char **)&buf, nalloc) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode dataspace")
done:
FUNC_LEAVE_API(ret_value)
}
herr_t
H5S_encode(H5S_t *obj, unsigned char **p, size_t *nalloc)
{
H5F_t *f = NULL;
size_t extent_size;
hssize_t sselect_size;
size_t select_size;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
if(NULL == (f = H5F_fake_alloc((uint8_t)0)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate fake file struct")
if((extent_size = H5O_msg_raw_size(f, H5O_SDSPACE_ID, TRUE, obj)) == 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADSIZE, FAIL, "can't find dataspace size")
if((sselect_size = H5S_SELECT_SERIAL_SIZE(obj)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADSIZE, FAIL, "can't find dataspace selection size")
H5_CHECKED_ASSIGN(select_size, size_t, sselect_size, hssize_t);
if(!*p || *nalloc < (extent_size + select_size + 1 + 1 + 1 + 4))
*nalloc = extent_size + select_size + 1 + 1 + 1 + 4;
else {
unsigned char *pp = (*p);
*pp++ = H5O_SDSPACE_ID;
*pp++ = H5S_ENCODE_VERSION;
*pp++ = (unsigned char)H5F_SIZEOF_SIZE(f);
UINT32ENCODE(pp, extent_size);
if(H5O_msg_encode(f, H5O_SDSPACE_ID, TRUE, pp, obj) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode extent space")
pp += extent_size;
*p = pp;
if(H5S_SELECT_SERIALIZE(obj, p) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode select space")
}
done:
if(f && H5F_fake_free(f) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release fake file struct")
FUNC_LEAVE_NOAPI(ret_value)
}
hid_t
H5Sdecode(const void *buf)
{
H5S_t *ds;
hid_t ret_value;
FUNC_ENTER_API(H5I_INVALID_HID)
H5TRACE1("i", "*x", buf);
if(buf == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "empty buffer")
if((ds = H5S_decode((const unsigned char **)&buf)) == NULL)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDECODE, H5I_INVALID_HID, "can't decode object")
if((ret_value = H5I_register(H5I_DATASPACE, ds, TRUE)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace")
done:
FUNC_LEAVE_API(ret_value)
}
H5S_t*
H5S_decode(const unsigned char **p)
{
H5F_t *f = NULL;
H5S_t *ds;
H5S_extent_t *extent;
const unsigned char *pp = (*p);
size_t extent_size;
uint8_t sizeof_size;
H5S_t *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT
if(*pp++ != H5O_SDSPACE_ID)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADMESG, NULL, "not an encoded dataspace")
if(*pp++ != H5S_ENCODE_VERSION)
HGOTO_ERROR(H5E_DATASPACE, H5E_VERSION, NULL, "unknown version of encoded dataspace")
sizeof_size = *pp++;
if(NULL == (f = H5F_fake_alloc(sizeof_size)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate fake file struct")
UINT32DECODE(pp, extent_size);
if(NULL == (extent = (H5S_extent_t *)H5O_msg_decode(f, NULL, H5O_SDSPACE_ID, extent_size, pp)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDECODE, NULL, "can't decode object")
pp += extent_size;
if(NULL == (ds = H5FL_CALLOC(H5S_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for dataspace conversion path table")
if(NULL == H5O_msg_copy(H5O_SDSPACE_ID, extent, &(ds->extent)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy object")
if(H5S__extent_release(extent) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTDELETE, NULL, "can't release previous dataspace")
extent = H5FL_FREE(H5S_extent_t, extent);
if(H5S_select_all(ds, FALSE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection")
*p = pp;
if(H5S_SELECT_DESERIALIZE(&ds, p) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDECODE, NULL, "can't decode space selection")
ret_value = ds;
done:
if(f && H5F_fake_free(f) < 0)
HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, NULL, "unable to release fake file struct")
FUNC_LEAVE_NOAPI(ret_value)
}
H5S_class_t
H5S_get_simple_extent_type(const H5S_t *space)
{
H5S_class_t ret_value = H5S_NO_CLASS;
FUNC_ENTER_NOAPI(H5S_NO_CLASS)
HDassert(space);
ret_value = H5S_GET_EXTENT_TYPE(space);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5S_class_t
H5Sget_simple_extent_type(hid_t sid)
{
H5S_t *space;
H5S_class_t ret_value;
FUNC_ENTER_API(H5S_NO_CLASS)
H5TRACE1("Sc", "i", sid);
if(NULL == (space = (H5S_t *)H5I_object_verify(sid, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5S_NO_CLASS, "not a dataspace")
ret_value = H5S_GET_EXTENT_TYPE(space);
done:
FUNC_LEAVE_API(ret_value)
}
herr_t
H5Sset_extent_none(hid_t space_id)
{
H5S_t *space;
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
H5TRACE1("e", "i", space_id);
if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a dataspace")
if(H5S__extent_release(&space->extent) < 0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTDELETE, FAIL, "can't release previous dataspace")
space->extent.type = H5S_NULL;
done:
FUNC_LEAVE_API(ret_value)
}
htri_t
H5S_set_extent(H5S_t *space, const hsize_t *size)
{
unsigned u;
htri_t ret_value = FALSE;
FUNC_ENTER_NOAPI(FAIL)
HDassert(space && H5S_SIMPLE == H5S_GET_EXTENT_TYPE(space));
HDassert(size);
for(u = 0; u < space->extent.rank; u++)
if(space->extent.size[u] != size[u]) {
if(space->extent.max && H5S_UNLIMITED != space->extent.max[u] &&
space->extent.max[u] < size[u])
HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "dimension cannot exceed the existing maximal size (new: %llu max: %llu)", (unsigned long long)size[u], (unsigned long long)space->extent.max[u])
ret_value = TRUE;
}
if(ret_value)
if(H5S_set_extent_real(space, size) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "failed to change dimension size(s)")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5_ATTR_PURE hbool_t
H5S_has_extent(const H5S_t *ds)
{
hbool_t ret_value = FALSE;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(ds);
if(0 == ds->extent.rank && 0 == ds->extent.nelem && H5S_NULL != ds->extent.type)
ret_value = FALSE;
else
ret_value = TRUE;
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5S_set_extent_real(H5S_t *space, const hsize_t *size)
{
hsize_t nelem;
unsigned u;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(space && H5S_SIMPLE == H5S_GET_EXTENT_TYPE(space));
HDassert(size);
for(u = 0, nelem = 1; u < space->extent.rank; u++ ) {
space->extent.size[u] = size[u];
nelem *= size[u];
}
space->extent.nelem = nelem;
if(H5S_SEL_ALL == H5S_GET_SELECT_TYPE(space))
if(H5S_select_all(space, FALSE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
if(H5O_msg_reset_share(H5O_SDSPACE_ID, space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRESET, FAIL, "can't stop sharing dataspace")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
htri_t
H5Sextent_equal(hid_t space1_id, hid_t space2_id)
{
const H5S_t *ds1;
const H5S_t *ds2;
htri_t ret_value;
FUNC_ENTER_API(FAIL)
H5TRACE2("t", "ii", space1_id, space2_id);
if(NULL == (ds1 = (const H5S_t *)H5I_object_verify(space1_id, H5I_DATASPACE)) ||
NULL == (ds2 = (const H5S_t *)H5I_object_verify(space2_id, H5I_DATASPACE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
if((ret_value = H5S_extent_equal(ds1, ds2)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "dataspace comparison failed")
done:
FUNC_LEAVE_API(ret_value)
}
H5_ATTR_PURE htri_t
H5S_extent_equal(const H5S_t *ds1, const H5S_t *ds2)
{
unsigned u;
htri_t ret_value = TRUE;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(ds1);
HDassert(ds2);
if(ds1->extent.type != ds2->extent.type)
HGOTO_DONE(FALSE)
if(ds1->extent.rank != ds2->extent.rank)
HGOTO_DONE(FALSE)
if(ds1->extent.rank > 0) {
HDassert(ds1->extent.size);
HDassert(ds2->extent.size);
for(u = 0; u < ds1->extent.rank; u++)
if(ds1->extent.size[u] != ds2->extent.size[u])
HGOTO_DONE(FALSE)
}
if(ds1->extent.rank > 0) {
if(ds1->extent.max != NULL && ds2->extent.max != NULL) {
for(u = 0; u < ds1->extent.rank; u++)
if(ds1->extent.max[u] != ds2->extent.max[u])
HGOTO_DONE(FALSE)
}
else
if((ds1->extent.max == NULL && ds2->extent.max != NULL) ||
(ds1->extent.max != NULL && ds2->extent.max == NULL))
HGOTO_DONE(FALSE)
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5_ATTR_PURE hsize_t
H5S_extent_nelem(const H5S_extent_t *ext)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(ext);
FUNC_LEAVE_NOAPI(ext->nelem)
}
herr_t
H5S_set_version(H5F_t *f, H5S_t *ds)
{
unsigned version;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
HDassert(f);
HDassert(ds);
version = MAX(ds->extent.version, H5O_sdspace_ver_bounds[H5F_LOW_BOUND(f)]);
if(version > H5O_sdspace_ver_bounds[H5F_HIGH_BOUND(f)])
HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, FAIL, "Dataspace version out of bounds")
ds->extent.version = version;
done:
FUNC_LEAVE_NOAPI(ret_value)
}