Coverage Report

Created: 2024-06-18 06:29

/src/hdf5/src/H5S.c
Line
Count
Source (jump to first uncovered line)
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
 * Copyright by The HDF Group.                                               *
3
 * All rights reserved.                                                      *
4
 *                                                                           *
5
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
6
 * terms governing use, modification, and redistribution, is contained in    *
7
 * the COPYING file, which can be found at the root of the source code       *
8
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9
 * If you do not have access to either file, you may request a copy from     *
10
 * help@hdfgroup.org.                                                        *
11
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13
/****************/
14
/* Module Setup */
15
/****************/
16
17
#include "H5Smodule.h" /* This source code file is part of the H5S module */
18
19
/***********/
20
/* Headers */
21
/***********/
22
#include "H5private.h"   /* Generic Functions            */
23
#include "H5Eprivate.h"  /* Error handling              */
24
#include "H5CXprivate.h" /* API Contexts         */
25
#include "H5Fprivate.h"  /* Files                */
26
#include "H5FLprivate.h" /* Free lists                           */
27
#include "H5Iprivate.h"  /* IDs                      */
28
#include "H5MMprivate.h" /* Memory management            */
29
#include "H5Oprivate.h"  /* Object headers              */
30
#include "H5Spkg.h"      /* Dataspaces                 */
31
32
/****************/
33
/* Local Macros */
34
/****************/
35
36
/* Version of dataspace encoding */
37
0
#define H5S_ENCODE_VERSION 0
38
39
/******************/
40
/* Local Typedefs */
41
/******************/
42
43
/********************/
44
/* Local Prototypes */
45
/********************/
46
static herr_t H5S__close_cb(void *space, void **request);
47
static htri_t H5S__is_simple(const H5S_t *sdim);
48
49
/*****************************/
50
/* Library Private Variables */
51
/*****************************/
52
53
/*********************/
54
/* Package Variables */
55
/*********************/
56
57
/* Format version bounds for dataspace */
58
const unsigned H5O_sdspace_ver_bounds[] = {
59
    H5O_SDSPACE_VERSION_1,     /* H5F_LIBVER_EARLIEST */
60
    H5O_SDSPACE_VERSION_2,     /* H5F_LIBVER_V18 */
61
    H5O_SDSPACE_VERSION_2,     /* H5F_LIBVER_V110 */
62
    H5O_SDSPACE_VERSION_2,     /* H5F_LIBVER_V112 */
63
    H5O_SDSPACE_VERSION_LATEST /* H5F_LIBVER_LATEST */
64
};
65
66
/* Declare a free list to manage the H5S_extent_t struct */
67
H5FL_DEFINE(H5S_extent_t);
68
69
/* Declare a free list to manage the H5S_t struct */
70
H5FL_DEFINE(H5S_t);
71
72
/* Declare a free list to manage the array's of hsize_t's */
73
H5FL_ARR_DEFINE(hsize_t, H5S_MAX_RANK);
74
75
/*******************/
76
/* Local Variables */
77
/*******************/
78
79
/* Dataspace ID class */
80
static const H5I_class_t H5I_DATASPACE_CLS[1] = {{
81
    H5I_DATASPACE,            /* ID class value */
82
    0,                        /* Class flags */
83
    3,                        /* # of reserved IDs for class */
84
    (H5I_free_t)H5S__close_cb /* Callback routine for closing objects of this class */
85
}};
86
87
/* Dataspace selection iterator ID class */
88
static const H5I_class_t H5I_SPACE_SEL_ITER_CLS[1] = {{
89
    H5I_SPACE_SEL_ITER,                /* ID class value */
90
    0,                                 /* Class flags */
91
    0,                                 /* # of reserved IDs for class */
92
    (H5I_free_t)H5S__sel_iter_close_cb /* Callback routine for closing objects of this class */
93
}};
94
95
/*-------------------------------------------------------------------------
96
 * Function: H5S_init
97
 *
98
 * Purpose:  Initialize the interface from some other layer.
99
 *
100
 * Return:   Success:    non-negative
101
 *           Failure:    negative
102
 *-------------------------------------------------------------------------
103
 */
104
herr_t
105
H5S_init(void)
106
1
{
107
1
    herr_t ret_value = SUCCEED; /* Return value */
108
109
1
    FUNC_ENTER_NOAPI(FAIL)
110
111
    /* Initialize the ID group for the dataspace IDs */
112
1
    if (H5I_register_type(H5I_DATASPACE_CLS) < 0)
113
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize dataspace ID class");
114
115
    /* Initialize the ID group for the dataspace selection iterator IDs */
116
1
    if (H5I_register_type(H5I_SPACE_SEL_ITER_CLS) < 0)
117
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL,
118
1
                    "unable to initialize dataspace selection iterator ID class");
119
120
1
done:
121
1
    FUNC_LEAVE_NOAPI(ret_value)
122
1
} /* end H5S_init() */
123
124
/*--------------------------------------------------------------------------
125
 NAME
126
    H5S_top_term_package
127
 PURPOSE
128
    Terminate various H5S objects
129
 USAGE
130
    void H5S_top_term_package()
131
 RETURNS
132
    Non-negative on success/Negative on failure
133
 DESCRIPTION
134
    Release IDs for the ID group, deferring full interface shutdown
135
    until later (in H5S_term_package).
136
 GLOBAL VARIABLES
137
 COMMENTS, BUGS, ASSUMPTIONS
138
     Can't report errors...
139
 EXAMPLES
140
 REVISION LOG
141
--------------------------------------------------------------------------*/
142
int
143
H5S_top_term_package(void)
144
1
{
145
1
    int n = 0;
146
147
1
    FUNC_ENTER_NOAPI_NOINIT_NOERR
148
149
1
    if (H5I_nmembers(H5I_DATASPACE) > 0) {
150
0
        (void)H5I_clear_type(H5I_DATASPACE, false, false);
151
0
        n++;
152
0
    }
153
1
    if (H5I_nmembers(H5I_SPACE_SEL_ITER) > 0) {
154
0
        (void)H5I_clear_type(H5I_SPACE_SEL_ITER, false, false);
155
0
        n++;
156
0
    }
157
158
1
    FUNC_LEAVE_NOAPI(n)
159
1
} /* end H5S_top_term_package() */
160
161
/*--------------------------------------------------------------------------
162
 NAME
163
    H5S_term_package
164
 PURPOSE
165
    Terminate various H5S objects
166
 USAGE
167
    void H5S_term_package()
168
 RETURNS
169
    Non-negative on success/Negative on failure
170
 DESCRIPTION
171
    Release the ID group and any other resources allocated.
172
 GLOBAL VARIABLES
173
 COMMENTS, BUGS, ASSUMPTIONS
174
     Can't report errors...
175
176
     Finishes shutting down the interface, after H5S_top_term_package()
177
     is called
178
 EXAMPLES
179
 REVISION LOG
180
--------------------------------------------------------------------------*/
181
int
182
H5S_term_package(void)
183
1
{
184
1
    int n = 0;
185
186
1
    FUNC_ENTER_NOAPI_NOINIT_NOERR
187
188
    /* Sanity checks */
189
1
    assert(0 == H5I_nmembers(H5I_DATASPACE));
190
1
    assert(0 == H5I_nmembers(H5I_SPACE_SEL_ITER));
191
192
    /* Destroy the dataspace object id group */
193
1
    n += (H5I_dec_type_ref(H5I_DATASPACE) > 0);
194
195
    /* Destroy the dataspace selection iterator object id group */
196
1
    n += (H5I_dec_type_ref(H5I_SPACE_SEL_ITER) > 0);
197
198
1
    FUNC_LEAVE_NOAPI(n)
199
1
} /* end H5S_term_package() */
200
201
/*-------------------------------------------------------------------------
202
 * Function:    H5S__close_cb
203
 *
204
 * Purpose:     Called when the ref count reaches zero on a dataspace's ID
205
 *
206
 * Return:      SUCCEED / FAIL
207
 *
208
 *-------------------------------------------------------------------------
209
 */
210
static herr_t
211
H5S__close_cb(void *_space, void H5_ATTR_UNUSED **request)
212
43
{
213
43
    H5S_t *space     = (H5S_t *)_space; /* The dataspace to close */
214
43
    herr_t ret_value = SUCCEED;         /* Return value */
215
216
43
    FUNC_ENTER_PACKAGE
217
218
    /* Sanity check */
219
43
    assert(space);
220
221
    /* Close the dataspace object */
222
43
    if (H5S_close(space) < 0)
223
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CLOSEERROR, FAIL, "unable to close dataspace");
224
225
43
done:
226
43
    FUNC_LEAVE_NOAPI(ret_value)
227
43
} /* end H5S__close_cb() */
228
229
/*--------------------------------------------------------------------------
230
 NAME
231
    H5S_create
232
 PURPOSE
233
    Create empty, typed dataspace
234
 USAGE
235
   H5S_t *H5S_create(type)
236
    H5S_type_t  type;           IN: Dataspace type to create
237
 RETURNS
238
    Pointer to dataspace on success, NULL on failure
239
 DESCRIPTION
240
    Creates a new dataspace of a given type.  The extent is undefined and the
241
    selection is set to the "all" selection.
242
 GLOBAL VARIABLES
243
 COMMENTS, BUGS, ASSUMPTIONS
244
 EXAMPLES
245
 REVISION LOG
246
--------------------------------------------------------------------------*/
247
H5S_t *
248
H5S_create(H5S_class_t type)
249
0
{
250
0
    H5S_t *new_ds    = NULL; /* New dataspace created */
251
0
    H5S_t *ret_value = NULL; /* Return value */
252
253
0
    FUNC_ENTER_NOAPI(NULL)
254
255
    /* Create a new dataspace */
256
0
    if (NULL == (new_ds = H5FL_CALLOC(H5S_t)))
257
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
258
259
    /* Initialize default dataspace state */
260
0
    new_ds->extent.type = type;
261
0
    if (type == H5S_NULL)
262
0
        new_ds->extent.version = H5O_SDSPACE_VERSION_2;
263
0
    else
264
0
        new_ds->extent.version = H5O_SDSPACE_VERSION_1;
265
0
    new_ds->extent.rank = 0;
266
0
    new_ds->extent.size = new_ds->extent.max = NULL;
267
268
0
    switch (type) {
269
0
        case H5S_SCALAR:
270
0
            new_ds->extent.nelem = 1;
271
0
            break;
272
273
0
        case H5S_SIMPLE:
274
0
        case H5S_NULL:
275
0
            new_ds->extent.nelem = 0;
276
0
            break;
277
278
0
        case H5S_NO_CLASS:
279
0
        default:
280
0
            assert("unknown dataspace (extent) type" && 0);
281
0
            break;
282
0
    } /* end switch */
283
284
    /* Start with "all" selection */
285
0
    if (H5S_select_all(new_ds, false) < 0)
286
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection");
287
288
    /* Reset common selection info pointer */
289
0
    new_ds->select.sel_info.hslab = NULL;
290
291
    /* Reset "shared" info on extent */
292
0
    if (H5O_msg_reset_share(H5O_SDSPACE_ID, &(new_ds->extent.sh_loc)) < 0)
293
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRESET, NULL, "unable to reset shared component info");
294
295
    /* Set return value */
296
0
    ret_value = new_ds;
297
298
0
done:
299
0
    if (ret_value == NULL)
300
0
        if (new_ds && H5S_close(new_ds) < 0)
301
0
            HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, NULL, "unable to release dataspace");
302
303
0
    FUNC_LEAVE_NOAPI(ret_value)
304
0
} /* end H5S_create() */
305
306
/*--------------------------------------------------------------------------
307
 NAME
308
    H5Screate
309
 PURPOSE
310
    Create empty, typed dataspace
311
 USAGE
312
   hid_t  H5Screate(type)
313
    H5S_type_t  type;           IN: Dataspace type to create
314
 RETURNS
315
    Valid dataspace ID on success, negative on failure
316
 DESCRIPTION
317
    Creates a new dataspace of a given type.  The extent & selection are
318
    undefined
319
 GLOBAL VARIABLES
320
 COMMENTS, BUGS, ASSUMPTIONS
321
 EXAMPLES
322
 REVISION LOG
323
--------------------------------------------------------------------------*/
324
hid_t
325
H5Screate(H5S_class_t type)
326
0
{
327
0
    H5S_t *new_ds = NULL; /* New dataspace structure */
328
0
    hid_t  ret_value;     /* Return value */
329
330
0
    FUNC_ENTER_API(FAIL)
331
332
    /* Check args */
333
0
    if (type <= H5S_NO_CLASS || type > H5S_NULL) /* don't allow complex dataspace yet */
334
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid dataspace type");
335
336
0
    if (NULL == (new_ds = H5S_create(type)))
337
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace");
338
339
    /* Register */
340
0
    if ((ret_value = H5I_register(H5I_DATASPACE, new_ds, true)) < 0)
341
0
        HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID");
342
343
0
done:
344
0
    if (ret_value < 0)
345
0
        if (new_ds && H5S_close(new_ds) < 0)
346
0
            HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace");
347
348
0
    FUNC_LEAVE_API(ret_value)
349
0
} /* end H5Screate() */
350
351
/*-------------------------------------------------------------------------
352
 * Function:    H5S__extent_release
353
 *
354
 * Purpose:     Releases all memory associated with a dataspace extent.
355
 *
356
 * Return:      Non-negative on success/Negative on failure
357
 *
358
 *-------------------------------------------------------------------------
359
 */
360
herr_t
361
H5S__extent_release(H5S_extent_t *extent)
362
280
{
363
280
    FUNC_ENTER_PACKAGE_NOERR
364
365
280
    assert(extent);
366
367
    /* Release extent */
368
280
    if (extent->type == H5S_SIMPLE) {
369
136
        if (extent->size)
370
136
            extent->size = H5FL_ARR_FREE(hsize_t, extent->size);
371
136
        if (extent->max)
372
136
            extent->max = H5FL_ARR_FREE(hsize_t, extent->max);
373
136
    } /* end if */
374
375
280
    extent->rank  = 0;
376
280
    extent->nelem = 0;
377
378
280
    FUNC_LEAVE_NOAPI(SUCCEED)
379
280
} /* end H5S__extent_release() */
380
381
/*-------------------------------------------------------------------------
382
 * Function:    H5S_close
383
 *
384
 * Purpose:     Releases all memory associated with a dataspace.
385
 *
386
 * Return:      Non-negative on success/Negative on failure
387
 *
388
 *-------------------------------------------------------------------------
389
 */
390
herr_t
391
H5S_close(H5S_t *ds)
392
147
{
393
147
    herr_t ret_value = SUCCEED; /* Return value */
394
395
147
    FUNC_ENTER_NOAPI(FAIL)
396
397
147
    assert(ds);
398
399
    /* Release selection (this should come before the extent release) */
400
147
    if (H5S_SELECT_RELEASE(ds) < 0)
401
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace selection");
402
403
    /* Release extent */
404
147
    if (H5S__extent_release(&ds->extent) < 0)
405
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace extent");
406
407
147
done:
408
    /* Release the main structure.
409
     * Always do this to ensure that we don't leak memory when calling this
410
     * function on partially constructed dataspaces (which will fail one or
411
     * both of the above calls)
412
     */
413
147
    H5FL_FREE(H5S_t, ds);
414
415
147
    FUNC_LEAVE_NOAPI(ret_value)
416
147
} /* end H5S_close() */
417
418
/*-------------------------------------------------------------------------
419
 * Function:    H5Sclose
420
 *
421
 * Purpose:     Release access to a dataspace object.
422
 *
423
 * Return:      Non-negative on success/Negative on failure
424
 *
425
 *-------------------------------------------------------------------------
426
 */
427
herr_t
428
H5Sclose(hid_t space_id)
429
46
{
430
46
    herr_t ret_value = SUCCEED; /* Return value */
431
432
92
    FUNC_ENTER_API(FAIL)
433
434
    /* Check args */
435
92
    if (NULL == H5I_object_verify(space_id, H5I_DATASPACE))
436
3
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace");
437
438
    /* When the reference count reaches zero the resources are freed */
439
43
    if (H5I_dec_app_ref(space_id) < 0)
440
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "problem freeing id");
441
442
46
done:
443
46
    FUNC_LEAVE_API(ret_value)
444
43
} /* end H5Sclose() */
445
446
/*-------------------------------------------------------------------------
447
 * Function:    H5Scopy
448
 *
449
 * Purpose:     Copies a dataspace.
450
 *
451
 * Return:      Success:    ID of the new dataspace
452
 *
453
 *              Failure:    H5I_INVALID_HID
454
 *
455
 *-------------------------------------------------------------------------
456
 */
457
hid_t
458
H5Scopy(hid_t space_id)
459
0
{
460
0
    H5S_t *src       = NULL;
461
0
    H5S_t *dst       = NULL;
462
0
    hid_t  ret_value = H5I_INVALID_HID;
463
464
0
    FUNC_ENTER_API(H5I_INVALID_HID)
465
466
    /* Check args */
467
0
    if (NULL == (src = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
468
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace");
469
470
    /* Copy */
471
0
    if (NULL == (dst = H5S_copy(src, false, true)))
472
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, H5I_INVALID_HID, "unable to copy dataspace");
473
474
    /* Register */
475
0
    if ((ret_value = H5I_register(H5I_DATASPACE, dst, true)) < 0)
476
0
        HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace ID");
477
478
0
done:
479
0
    if (ret_value < 0)
480
0
        if (dst && H5S_close(dst) < 0)
481
0
            HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, H5I_INVALID_HID, "unable to release dataspace");
482
483
0
    FUNC_LEAVE_API(ret_value)
484
0
} /* end H5Scopy() */
485
486
/*-------------------------------------------------------------------------
487
 * Function:    H5Sextent_copy
488
 *
489
 * Purpose:     Copies a dataspace extent.
490
 *
491
 * Return:      Non-negative on success/Negative on failure
492
 *
493
 *-------------------------------------------------------------------------
494
 */
495
herr_t
496
H5Sextent_copy(hid_t dst_id, hid_t src_id)
497
0
{
498
0
    H5S_t *src;
499
0
    H5S_t *dst;
500
0
    herr_t ret_value = SUCCEED;
501
502
0
    FUNC_ENTER_API(FAIL)
503
504
    /* Check args */
505
0
    if (NULL == (src = (H5S_t *)H5I_object_verify(src_id, H5I_DATASPACE)))
506
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace");
507
0
    if (NULL == (dst = (H5S_t *)H5I_object_verify(dst_id, H5I_DATASPACE)))
508
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace");
509
510
    /* Copy */
511
0
    if (H5S_extent_copy(dst, src) < 0)
512
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy extent");
513
514
0
done:
515
0
    FUNC_LEAVE_API(ret_value)
516
0
} /* end H5Sextent_copy() */
517
518
/*-------------------------------------------------------------------------
519
 * Function:    H5S_extent_copy
520
 *
521
 * Purpose:     Copies a dataspace extent
522
 *
523
 * Return:      Non-negative on success/Negative on failure
524
 *
525
 *-------------------------------------------------------------------------
526
 */
527
herr_t
528
H5S_extent_copy(H5S_t *dst, const H5S_t *src)
529
0
{
530
0
    herr_t ret_value = SUCCEED; /* Return value */
531
532
0
    FUNC_ENTER_NOAPI(FAIL)
533
534
0
    assert(dst);
535
0
    assert(src);
536
537
    /* Copy extent */
538
0
    if (H5S__extent_copy_real(&(dst->extent), &(src->extent), true) < 0)
539
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy extent");
540
541
    /* If the selection is 'all', update the number of elements selected in the
542
     * destination space */
543
0
    if (H5S_SEL_ALL == H5S_GET_SELECT_TYPE(dst))
544
0
        if (H5S_select_all(dst, false) < 0)
545
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection");
546
547
0
done:
548
0
    FUNC_LEAVE_NOAPI(ret_value)
549
0
} /* end H5S_extent_copy() */
550
551
/*-------------------------------------------------------------------------
552
 * Function:    H5S__extent_copy_real
553
 *
554
 * Purpose:     Copies a dataspace extent
555
 *
556
 * Return:      Non-negative on success/Negative on failure
557
 *
558
 *-------------------------------------------------------------------------
559
 */
560
herr_t
561
H5S__extent_copy_real(H5S_extent_t *dst, const H5S_extent_t *src, bool copy_max)
562
95
{
563
95
    unsigned u;
564
95
    herr_t   ret_value = SUCCEED; /* Return value */
565
566
95
    FUNC_ENTER_PACKAGE
567
568
    /* Release destination extent before we copy over it */
569
95
    if (H5S__extent_release(dst) < 0)
570
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace extent");
571
572
    /* Copy the regular fields */
573
95
    dst->type    = src->type;
574
95
    dst->version = src->version;
575
95
    dst->nelem   = src->nelem;
576
95
    dst->rank    = src->rank;
577
578
95
    switch (src->type) {
579
0
        case H5S_NULL:
580
0
        case H5S_SCALAR:
581
0
            dst->size = NULL;
582
0
            dst->max  = NULL;
583
0
            break;
584
585
95
        case H5S_SIMPLE:
586
95
            if (src->size) {
587
95
                dst->size = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)src->rank);
588
276
                for (u = 0; u < src->rank; u++)
589
181
                    dst->size[u] = src->size[u];
590
95
            } /* end if */
591
0
            else
592
0
                dst->size = NULL;
593
95
            if (copy_max && src->max) {
594
95
                dst->max = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)src->rank);
595
276
                for (u = 0; u < src->rank; u++)
596
181
                    dst->max[u] = src->max[u];
597
95
            } /* end if */
598
0
            else
599
0
                dst->max = NULL;
600
95
            break;
601
602
0
        case H5S_NO_CLASS:
603
0
        default:
604
0
            assert("unknown dataspace type" && 0);
605
0
            break;
606
95
    } /* end switch */
607
608
    /* Copy the shared object info */
609
95
    if (H5O_set_shared(&(dst->sh_loc), &(src->sh_loc)) < 0)
610
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy shared information");
611
612
95
done:
613
95
    if (ret_value < 0)
614
0
        if (dst->size)
615
0
            dst->size = H5FL_ARR_FREE(hsize_t, dst->size);
616
617
95
    FUNC_LEAVE_NOAPI(ret_value)
618
95
} /* end H5S__extent_copy_real() */
619
620
/*-------------------------------------------------------------------------
621
 * Function:    H5S_copy
622
 *
623
 * Purpose:     Copies a dataspace, by copying the extent and selection through
624
 *              H5S_extent_copy and H5S_select_copy.  If the SHARE_SELECTION flag
625
 *              is set, then the selection can be shared between the source and
626
 *              destination dataspaces.  (This should only occur in situations
627
 *              where the destination dataspace will immediately change to a new
628
 *              selection)
629
 *
630
 * Return:      Success:    A pointer to a new copy of SRC
631
 *
632
 *              Failure:    NULL
633
 *
634
 *-------------------------------------------------------------------------
635
 */
636
H5S_t *
637
H5S_copy(const H5S_t *src, bool share_selection, bool copy_max)
638
43
{
639
43
    H5S_t *dst       = NULL;
640
43
    H5S_t *ret_value = NULL; /* Return value */
641
642
43
    FUNC_ENTER_NOAPI(NULL)
643
644
43
    if (NULL == (dst = H5FL_CALLOC(H5S_t)))
645
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
646
647
    /* Copy the source dataspace's extent */
648
43
    if (H5S__extent_copy_real(&(dst->extent), &(src->extent), copy_max) < 0)
649
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy extent");
650
651
    /* Copy the source dataspace's selection */
652
43
    if (H5S_select_copy(dst, src, share_selection) < 0)
653
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy select");
654
655
    /* Set the return value */
656
43
    ret_value = dst;
657
658
43
done:
659
43
    if (NULL == ret_value)
660
0
        if (dst)
661
0
            dst = H5FL_FREE(H5S_t, dst);
662
663
43
    FUNC_LEAVE_NOAPI(ret_value)
664
43
} /* end H5S_copy() */
665
666
/*-------------------------------------------------------------------------
667
 * Function:    H5S_get_simple_extent_npoints
668
 *
669
 * Purpose:     Determines how many data points a dataset extent has.
670
 *
671
 * Return:      Success:    Number of data points in the dataset extent.
672
 *
673
 *              Failure:    Negative
674
 *
675
 * Note:        This routine participates in the "Inlining C function pointers"
676
 *              pattern, don't call it directly, use the appropriate macro
677
 *              defined in H5Sprivate.h.
678
 *
679
 *-------------------------------------------------------------------------
680
 */
681
hssize_t
682
H5S_get_simple_extent_npoints(const H5S_t *ds)
683
168
{
684
168
    hssize_t ret_value = -1; /* Return value */
685
686
168
    FUNC_ENTER_NOAPI_NOERR
687
688
    /* check args */
689
168
    assert(ds);
690
691
    /* Get the number of elements in extent */
692
168
    ret_value = (hssize_t)ds->extent.nelem;
693
694
168
    FUNC_LEAVE_NOAPI(ret_value)
695
168
} /* end H5S_get_simple_extent_npoints() */
696
697
/*-------------------------------------------------------------------------
698
 * Function:    H5Sget_simple_extent_npoints
699
 *
700
 * Purpose:     Determines how many data points a dataset extent has.
701
 *
702
 * Return:      Success:    Number of data points in the dataset.
703
 *              Failure:    Negative
704
 *
705
 *-------------------------------------------------------------------------
706
 */
707
hssize_t
708
H5Sget_simple_extent_npoints(hid_t space_id)
709
0
{
710
0
    H5S_t   *ds;
711
0
    hssize_t ret_value;
712
713
0
    FUNC_ENTER_API(FAIL)
714
715
    /* Check args */
716
0
    if (NULL == (ds = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
717
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace");
718
719
0
    ret_value = (hssize_t)H5S_GET_EXTENT_NPOINTS(ds);
720
721
0
done:
722
0
    FUNC_LEAVE_API(ret_value)
723
0
} /* end H5Sget_simple_extent_npoints() */
724
725
/*-------------------------------------------------------------------------
726
 * Function:    H5S_get_npoints_max
727
 *
728
 * Purpose:     Determines the maximum number of data points a dataspace may
729
 *              have.  If the `max' array is null then the maximum number of
730
 *              data points is the same as the current number of data points
731
 *              without regard to the hyperslab.  If any element of the `max'
732
 *              array is zero then the maximum possible size is returned.
733
 *
734
 * Return:      Success:    Maximum number of data points the dataspace
735
 *                          may have.
736
 *              Failure:    0
737
 *
738
 *-------------------------------------------------------------------------
739
 */
740
hsize_t
741
H5S_get_npoints_max(const H5S_t *ds)
742
0
{
743
0
    unsigned u;
744
0
    hsize_t  ret_value = 0; /* Return value */
745
746
0
    FUNC_ENTER_NOAPI(0)
747
748
    /* check args */
749
0
    assert(ds);
750
751
0
    switch (H5S_GET_EXTENT_TYPE(ds)) {
752
0
        case H5S_NULL:
753
0
            ret_value = 0;
754
0
            break;
755
756
0
        case H5S_SCALAR:
757
0
            ret_value = 1;
758
0
            break;
759
760
0
        case H5S_SIMPLE:
761
0
            if (ds->extent.max) {
762
0
                for (ret_value = 1, u = 0; u < ds->extent.rank; u++) {
763
0
                    if (H5S_UNLIMITED == ds->extent.max[u]) {
764
0
                        ret_value = HSIZET_MAX;
765
0
                        break;
766
0
                    }
767
0
                    else
768
0
                        ret_value *= ds->extent.max[u];
769
0
                }
770
0
            }
771
0
            else
772
0
                for (ret_value = 1, u = 0; u < ds->extent.rank; u++)
773
0
                    ret_value *= ds->extent.size[u];
774
0
            break;
775
776
0
        case H5S_NO_CLASS:
777
0
        default:
778
0
            assert("unknown dataspace class" && 0);
779
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, 0, "internal error (unknown dataspace class)");
780
0
    }
781
782
0
done:
783
0
    FUNC_LEAVE_NOAPI(ret_value)
784
0
} /* end H5S_get_npoints_max() */
785
786
/*-------------------------------------------------------------------------
787
 * Function:    H5Sget_simple_extent_ndims
788
 *
789
 * Purpose:     Determines the dimensionality of a dataspace.
790
 *
791
 * Return:      Success:    The number of dimensions in a dataspace.
792
 *              Failure:    Negative
793
 *
794
 *-------------------------------------------------------------------------
795
 */
796
int
797
H5Sget_simple_extent_ndims(hid_t space_id)
798
46
{
799
46
    H5S_t *ds;
800
46
    int    ret_value = -1;
801
802
92
    FUNC_ENTER_API((-1))
803
804
    /* Check args */
805
92
    if (NULL == (ds = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
806
3
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not a dataspace");
807
808
43
    ret_value = (int)H5S_GET_EXTENT_NDIMS(ds);
809
810
46
done:
811
46
    FUNC_LEAVE_API(ret_value)
812
43
} /* end H5Sget_simple_extent_ndims() */
813
814
/*-------------------------------------------------------------------------
815
 * Function:    H5S_get_simple_extent_ndims
816
 *
817
 * Purpose:     Returns the number of dimensions in a dataspace.
818
 *
819
 * Return:      Success:    Non-negative number of dimensions.
820
 *                          Zero implies a scalar.
821
 *
822
 *              Failure:    Negative
823
 *
824
 * Note:        This routine participates in the "Inlining C function pointers"
825
 *              pattern, don't call it directly, use the appropriate macro
826
 *              defined in H5Sprivate.h.
827
 *
828
 *-------------------------------------------------------------------------
829
 */
830
int
831
H5S_get_simple_extent_ndims(const H5S_t *ds)
832
62
{
833
62
    int ret_value = -1; /* Return value */
834
835
62
    FUNC_ENTER_NOAPI(FAIL)
836
837
    /* check args */
838
62
    assert(ds);
839
840
62
    switch (H5S_GET_EXTENT_TYPE(ds)) {
841
0
        case H5S_NULL:
842
0
        case H5S_SCALAR:
843
62
        case H5S_SIMPLE:
844
62
            ret_value = (int)ds->extent.rank;
845
62
            break;
846
847
0
        case H5S_NO_CLASS:
848
0
        default:
849
0
            assert("unknown dataspace class" && 0);
850
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "internal error (unknown dataspace class)");
851
62
    } /* end switch */
852
853
62
done:
854
62
    FUNC_LEAVE_NOAPI(ret_value)
855
62
} /* end H5S_get_simple_extent_ndims() */
856
857
/*-------------------------------------------------------------------------
858
 * Function:    H5Sget_simple_extent_dims
859
 *
860
 * Purpose:     Returns the size and maximum sizes in each dimension of
861
 *              a dataspace DS through the DIMS and MAXDIMS arguments.
862
 *
863
 * Return:      Success:    Number of dimensions, the same value as
864
 *                          returned by H5Sget_simple_extent_ndims().
865
 *
866
 *              Failure:    Negative
867
 *
868
 *-------------------------------------------------------------------------
869
 */
870
int
871
H5Sget_simple_extent_dims(hid_t space_id, hsize_t dims[] /*out*/, hsize_t maxdims[] /*out*/)
872
43
{
873
43
    H5S_t *ds;
874
43
    int    ret_value = -1;
875
876
86
    FUNC_ENTER_API((-1))
877
878
    /* Check args */
879
86
    if (NULL == (ds = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
880
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not a dataspace");
881
882
43
    ret_value = H5S_get_simple_extent_dims(ds, dims, maxdims);
883
884
43
done:
885
43
    FUNC_LEAVE_API(ret_value)
886
43
} /* end H5Sget_simple_extent_dims() */
887
888
/*-------------------------------------------------------------------------
889
 * Function:    H5S_extent_get_dims
890
 *
891
 * Purpose:     Returns the size in each dimension of a dataspace.  This
892
 *              function may not be meaningful for all types of dataspaces.
893
 *
894
 * Return:      Success:    Number of dimensions.  Zero implies scalar.
895
 *              Failure:    Negative
896
 *
897
 *-------------------------------------------------------------------------
898
 */
899
int
900
H5S_extent_get_dims(const H5S_extent_t *ext, hsize_t dims[], hsize_t max_dims[])
901
95
{
902
95
    int i;              /* Local index variable */
903
95
    int ret_value = -1; /* Return value */
904
905
95
    FUNC_ENTER_NOAPI(FAIL)
906
907
    /* check args */
908
95
    assert(ext);
909
910
95
    switch (ext->type) {
911
0
        case H5S_NULL:
912
0
        case H5S_SCALAR:
913
0
            ret_value = 0;
914
0
            break;
915
916
95
        case H5S_SIMPLE:
917
95
            ret_value = (int)ext->rank;
918
276
            for (i = 0; i < ret_value; i++) {
919
181
                if (dims)
920
181
                    dims[i] = ext->size[i];
921
181
                if (max_dims) {
922
101
                    if (ext->max)
923
101
                        max_dims[i] = ext->max[i];
924
0
                    else
925
0
                        max_dims[i] = ext->size[i];
926
101
                } /* end if */
927
181
            }     /* end for */
928
95
            break;
929
930
0
        case H5S_NO_CLASS:
931
0
        default:
932
0
            assert("unknown dataspace class" && 0);
933
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "internal error (unknown dataspace class)");
934
95
    } /* end switch */
935
936
95
done:
937
95
    FUNC_LEAVE_NOAPI(ret_value)
938
95
} /* end H5S_extent_get_dims() */
939
940
/*-------------------------------------------------------------------------
941
 * Function:    H5S_get_simple_extent_dims
942
 *
943
 * Purpose:     Returns the size in each dimension of a dataspace.  This
944
 *              function may not be meaningful for all types of dataspaces.
945
 *
946
 * Return:      Success:    Number of dimensions.  Zero implies scalar.
947
 *              Failure:    Negative
948
 *
949
 *-------------------------------------------------------------------------
950
 */
951
int
952
H5S_get_simple_extent_dims(const H5S_t *ds, hsize_t dims[], hsize_t max_dims[])
953
95
{
954
95
    int ret_value = -1; /* Return value */
955
956
95
    FUNC_ENTER_NOAPI(FAIL)
957
958
    /* check args */
959
95
    assert(ds);
960
961
    /* Get dims for extent */
962
95
    if ((ret_value = H5S_extent_get_dims(&ds->extent, dims, max_dims)) < 0)
963
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't retrieve dataspace extent dims");
964
965
95
done:
966
95
    FUNC_LEAVE_NOAPI(ret_value)
967
95
} /* end H5S_get_simple_extent_dims() */
968
969
/*-------------------------------------------------------------------------
970
 * Function:    H5S_write
971
 *
972
 * Purpose:     Updates a dataspace by writing a message to an object
973
 *              header.
974
 *
975
 * Return:      Non-negative on success/Negative on failure
976
 *
977
 *-------------------------------------------------------------------------
978
 */
979
herr_t
980
H5S_write(H5F_t *f, H5O_t *oh, unsigned update_flags, H5S_t *ds)
981
0
{
982
0
    herr_t ret_value = SUCCEED; /* Return value */
983
984
0
    FUNC_ENTER_NOAPI(FAIL)
985
986
0
    assert(f);
987
0
    assert(oh);
988
0
    assert(ds);
989
0
    assert(H5S_GET_EXTENT_TYPE(ds) >= 0);
990
991
    /* Write the current dataspace extent to the dataspace message */
992
0
    if (H5O_msg_write_oh(f, oh, H5O_SDSPACE_ID, 0, update_flags, &(ds->extent)) < 0)
993
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update simple dataspace message");
994
995
0
done:
996
0
    FUNC_LEAVE_NOAPI(ret_value)
997
0
} /* end H5S_write() */
998
999
/*-------------------------------------------------------------------------
1000
 * Function:    H5S_append
1001
 *
1002
 * Purpose:     Updates a dataspace by adding a message to an object header.
1003
 *
1004
 * Return:      Non-negative on success/Negative on failure
1005
 *
1006
 *-------------------------------------------------------------------------
1007
 */
1008
herr_t
1009
H5S_append(H5F_t *f, H5O_t *oh, H5S_t *ds)
1010
0
{
1011
0
    herr_t ret_value = SUCCEED; /* Return value */
1012
1013
0
    FUNC_ENTER_NOAPI(FAIL)
1014
1015
0
    assert(f);
1016
0
    assert(oh);
1017
0
    assert(ds);
1018
0
    assert(H5S_GET_EXTENT_TYPE(ds) >= 0);
1019
1020
    /* Add the dataspace message to the object header */
1021
0
    if (H5O_msg_append_oh(f, oh, H5O_SDSPACE_ID, 0, 0, &(ds->extent)) < 0)
1022
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't add simple dataspace message");
1023
1024
0
done:
1025
0
    FUNC_LEAVE_NOAPI(ret_value)
1026
0
} /* end H5S_append() */
1027
1028
/*-------------------------------------------------------------------------
1029
 * Function:    H5S_read
1030
 *
1031
 * Purpose:     Reads the dataspace from an object header.
1032
 *
1033
 * Return:      Success:    Pointer to a new dataspace.
1034
 *
1035
 *              Failure:    NULL
1036
 *
1037
 *-------------------------------------------------------------------------
1038
 */
1039
H5S_t *
1040
H5S_read(const H5O_loc_t *loc)
1041
52
{
1042
52
    H5S_t *ds        = NULL; /* Dataspace to return */
1043
52
    H5S_t *ret_value = NULL; /* Return value */
1044
1045
52
    FUNC_ENTER_NOAPI(NULL)
1046
1047
    /* check args */
1048
52
    assert(loc);
1049
1050
52
    if (NULL == (ds = H5FL_CALLOC(H5S_t)))
1051
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
1052
1053
52
    if (NULL == H5O_msg_read(loc, H5O_SDSPACE_ID, &(ds->extent)))
1054
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to load dataspace info from dataset header");
1055
1056
    /* Default to entire dataspace being selected */
1057
52
    if (H5S_select_all(ds, false) < 0)
1058
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection");
1059
1060
    /* Set the value for successful return */
1061
52
    ret_value = ds;
1062
1063
52
done:
1064
52
    if (ret_value == NULL)
1065
0
        if (ds != NULL)
1066
0
            ds = H5FL_FREE(H5S_t, ds);
1067
1068
52
    FUNC_LEAVE_NOAPI(ret_value)
1069
52
} /* end H5S_read() */
1070
1071
/*--------------------------------------------------------------------------
1072
 NAME
1073
    H5S__is_simple
1074
 PURPOSE
1075
    Check if a dataspace is simple (internal)
1076
 USAGE
1077
    htri_t H5S__is_simple(sdim)
1078
    H5S_t *sdim;        IN: Pointer to dataspace object to query
1079
 RETURNS
1080
    true/false/FAIL
1081
 DESCRIPTION
1082
    This function determines the if a dataspace is "simple". ie. if it
1083
    has orthogonal, evenly spaced dimensions.
1084
--------------------------------------------------------------------------*/
1085
static htri_t
1086
H5S__is_simple(const H5S_t *sdim)
1087
0
{
1088
0
    htri_t ret_value = FAIL; /* Return value */
1089
1090
0
    FUNC_ENTER_PACKAGE_NOERR
1091
1092
    /* Check args and all the boring stuff. */
1093
0
    assert(sdim);
1094
1095
    /* H5S_NULL shouldn't be simple dataspace */
1096
0
    ret_value =
1097
0
        (H5S_GET_EXTENT_TYPE(sdim) == H5S_SIMPLE || H5S_GET_EXTENT_TYPE(sdim) == H5S_SCALAR) ? true : false;
1098
1099
0
    FUNC_LEAVE_NOAPI(ret_value)
1100
0
} /* end H5S__is_simple() */
1101
1102
/*--------------------------------------------------------------------------
1103
 NAME
1104
    H5Sis_simple
1105
 PURPOSE
1106
    Check if a dataspace is simple
1107
 USAGE
1108
    htri_t H5Sis_simple(space_id)
1109
    hid_t space_id;         IN: ID of dataspace object to query
1110
 RETURNS
1111
    true/false/FAIL
1112
 DESCRIPTION
1113
    This function determines the if a dataspace is "simple". ie. if it
1114
    has orthogonal, evenly spaced dimensions.
1115
--------------------------------------------------------------------------*/
1116
htri_t
1117
H5Sis_simple(hid_t space_id)
1118
0
{
1119
0
    H5S_t *space;     /* Dataspace to check */
1120
0
    htri_t ret_value; /* Return value */
1121
1122
0
    FUNC_ENTER_API(FAIL)
1123
1124
    /* Check args and all the boring stuff. */
1125
0
    if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
1126
0
        HGOTO_ERROR(H5E_ID, H5E_BADID, FAIL, "not a dataspace");
1127
1128
0
    ret_value = H5S__is_simple(space);
1129
1130
0
done:
1131
0
    FUNC_LEAVE_API(ret_value)
1132
0
} /* end H5Sis_simple() */
1133
1134
/*--------------------------------------------------------------------------
1135
 NAME
1136
    H5Sset_extent_simple
1137
 PURPOSE
1138
    Sets the size of a simple dataspace
1139
 USAGE
1140
    herr_t H5Sset_extent_simple(space_id, rank, dims, max)
1141
        hid_t space_id;         IN: Dataspace object to query
1142
        int rank;               IN: # of dimensions for the dataspace
1143
        const size_t *dims;     IN: Size of each dimension for the dataspace
1144
        const size_t *max;      IN: Maximum size of each dimension for the
1145
                                    dataspace
1146
 RETURNS
1147
    Non-negative on success/Negative on failure
1148
 DESCRIPTION
1149
    This function sets the number and size of each dimension in the
1150
    dataspace. Setting RANK to a value of zero converts the dataspace to a
1151
    scalar dataspace.  Dimensions are specified from slowest to fastest
1152
    changing in the DIMS array (i.e. 'C' order).  Setting the size of a
1153
    dimension in the MAX array to zero indicates that the dimension is of
1154
    unlimited size and should be allowed to expand.  If MAX is NULL, the
1155
    dimensions in the DIMS array are used as the maximum dimensions.
1156
    Currently, only the first dimension in the array (the slowest) may be
1157
    unlimited in size.
1158
1159
--------------------------------------------------------------------------*/
1160
herr_t
1161
H5Sset_extent_simple(hid_t space_id, int rank, const hsize_t dims[/*rank*/], const hsize_t max[/*rank*/])
1162
0
{
1163
0
    H5S_t *space;               /* Dataspace to modify */
1164
0
    int    u;                   /* Local counting variable */
1165
0
    herr_t ret_value = SUCCEED; /* Return value */
1166
1167
0
    FUNC_ENTER_API(FAIL)
1168
1169
    /* Check args */
1170
0
    if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
1171
0
        HGOTO_ERROR(H5E_ID, H5E_BADID, FAIL, "not a dataspace");
1172
0
    if (rank > 0 && dims == NULL)
1173
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no dimensions specified");
1174
0
    if (rank < 0 || rank > H5S_MAX_RANK)
1175
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid rank");
1176
0
    if (dims)
1177
0
        for (u = 0; u < rank; u++)
1178
0
            if (H5S_UNLIMITED == dims[u])
1179
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
1180
0
                            "current dimension must have a specific size, not H5S_UNLIMITED");
1181
0
    if (max != NULL) {
1182
0
        if (dims == NULL)
1183
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
1184
0
                        "maximum dimension specified, but no current dimensions specified");
1185
0
        for (u = 0; u < rank; u++)
1186
0
            if (max[u] != H5S_UNLIMITED && max[u] < dims[u])
1187
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid maximum dimension size");
1188
0
    }
1189
1190
    /* Do it */
1191
0
    if (H5S_set_extent_simple(space, (unsigned)rank, dims, max) < 0)
1192
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set simple extent");
1193
1194
0
done:
1195
0
    FUNC_LEAVE_API(ret_value)
1196
0
} /* end H5Sset_extent_simple() */
1197
1198
/*-------------------------------------------------------------------------
1199
 * Function:    H5S_set_extent_simple
1200
 *
1201
 * Purpose:     This is where the real work happens for H5Sset_extent_simple().
1202
 *
1203
 * Return:      Non-negative on success/Negative on failure
1204
 *
1205
 *-------------------------------------------------------------------------
1206
 */
1207
herr_t
1208
H5S_set_extent_simple(H5S_t *space, unsigned rank, const hsize_t *dims, const hsize_t *max)
1209
0
{
1210
0
    unsigned u;                   /* Local index variable */
1211
0
    herr_t   ret_value = SUCCEED; /* Return value */
1212
1213
0
    FUNC_ENTER_NOAPI(FAIL)
1214
1215
    /* Check args */
1216
0
    if (rank > H5S_MAX_RANK)
1217
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "dataspace rank too large: %u", rank);
1218
1219
    /* shift out of the previous state to a "simple" dataspace.  */
1220
0
    if (H5S__extent_release(&space->extent) < 0)
1221
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "failed to release previous dataspace extent");
1222
1223
0
    if (rank == 0) { /* scalar variable */
1224
0
        space->extent.type  = H5S_SCALAR;
1225
0
        space->extent.nelem = 1;
1226
0
        space->extent.rank  = 0; /* set to scalar rank */
1227
0
    }                            /* end if */
1228
0
    else {
1229
0
        hsize_t nelem; /* Number of elements in extent */
1230
1231
0
        space->extent.type = H5S_SIMPLE;
1232
1233
        /* Set the rank and allocate space for the dims */
1234
0
        space->extent.rank = rank;
1235
0
        space->extent.size = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)rank);
1236
1237
        /* Copy the dimensions & compute the number of elements in the extent */
1238
0
        for (u = 0, nelem = 1; dims && (u < space->extent.rank); u++) {
1239
0
            space->extent.size[u] = dims[u];
1240
0
            nelem *= dims[u];
1241
0
        } /* end for */
1242
0
        space->extent.nelem = nelem;
1243
1244
        /* Copy the maximum dimensions if specified. Otherwise, the maximal dimensions are the
1245
         * same as the dimension */
1246
0
        space->extent.max = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)rank);
1247
0
        if (max != NULL)
1248
0
            H5MM_memcpy(space->extent.max, max, sizeof(hsize_t) * rank);
1249
0
        else
1250
0
            for (u = 0; dims && (u < space->extent.rank); u++)
1251
0
                space->extent.max[u] = dims[u];
1252
0
    } /* end else */
1253
1254
    /* Selection related cleanup */
1255
1256
    /* Set offset to zeros */
1257
0
    memset(space->select.offset, 0, sizeof(hsize_t) * space->extent.rank);
1258
0
    space->select.offset_changed = false;
1259
1260
    /* If the selection is 'all', update the number of elements selected */
1261
0
    if (H5S_GET_SELECT_TYPE(space) == H5S_SEL_ALL)
1262
0
        if (H5S_select_all(space, false) < 0)
1263
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection");
1264
1265
0
done:
1266
0
    FUNC_LEAVE_NOAPI(ret_value)
1267
0
} /* end H5S_set_extent_simple() */
1268
1269
/*-------------------------------------------------------------------------
1270
 * Function:    H5Screate_simple
1271
 *
1272
 * Purpose:     Creates a new simple dataspace object and opens it for
1273
 *              access. The DIMS argument is the size of the simple dataset
1274
 *              and the MAXDIMS argument is the upper limit on the size of
1275
 *              the dataset.  MAXDIMS may be the null pointer in which case
1276
 *              the upper limit is the same as DIMS.  If an element of
1277
 *              MAXDIMS is H5S_UNLIMITED then the corresponding dimension is
1278
 *              unlimited, otherwise no element of MAXDIMS should be smaller
1279
 *              than the corresponding element of DIMS.
1280
 *
1281
 * Return:      Success:    The ID for the new simple dataspace object.
1282
 *
1283
 *              Failure:    H5I_INVALID_HID
1284
 *
1285
 *-------------------------------------------------------------------------
1286
 */
1287
hid_t
1288
H5Screate_simple(int rank, const hsize_t dims[/*rank*/], const hsize_t maxdims[/*rank*/])
1289
0
{
1290
0
    H5S_t *space = NULL;
1291
0
    int    i;
1292
0
    hid_t  ret_value = H5I_INVALID_HID;
1293
1294
0
    FUNC_ENTER_API(H5I_INVALID_HID)
1295
1296
    /* Check arguments */
1297
0
    if (rank < 0)
1298
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dimensionality cannot be negative");
1299
0
    if (rank > H5S_MAX_RANK)
1300
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dimensionality is too large");
1301
1302
    /* We allow users to use this function to create scalar or null dataspace.
1303
     * Check DIMS isn't set when the RANK is 0.
1304
     */
1305
0
    if (!dims && rank != 0)
1306
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid dataspace information");
1307
1308
    /* Check whether the current dimensions are valid */
1309
0
    for (i = 0; i < rank; i++) {
1310
0
        if (H5S_UNLIMITED == dims[i])
1311
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID,
1312
0
                        "current dimension must have a specific size, not H5S_UNLIMITED");
1313
0
        if (maxdims && H5S_UNLIMITED != maxdims[i] && maxdims[i] < dims[i])
1314
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "maxdims is smaller than dims");
1315
0
    } /* end for */
1316
1317
    /* Create the space and set the extent */
1318
0
    if (NULL == (space = H5S_create_simple((unsigned)rank, dims, maxdims)))
1319
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, H5I_INVALID_HID, "can't create simple dataspace");
1320
1321
    /* Register */
1322
0
    if ((ret_value = H5I_register(H5I_DATASPACE, space, true)) < 0)
1323
0
        HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace ID");
1324
1325
0
done:
1326
0
    if (ret_value < 0)
1327
0
        if (space && H5S_close(space) < 0)
1328
0
            HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, H5I_INVALID_HID, "unable to release dataspace");
1329
1330
0
    FUNC_LEAVE_API(ret_value)
1331
0
} /* end H5Screate_simple() */
1332
1333
/*-------------------------------------------------------------------------
1334
 * Function:    H5S_create_simple
1335
 *
1336
 * Purpose:     Internal function to create simple dataspace
1337
 *
1338
 * Return:      Success:    A pointer to a dataspace object
1339
 *              Failure:    NULL
1340
 *
1341
 *-------------------------------------------------------------------------
1342
 */
1343
H5S_t *
1344
H5S_create_simple(unsigned rank, const hsize_t dims[/*rank*/], const hsize_t maxdims[/*rank*/])
1345
0
{
1346
0
    H5S_t *ret_value = NULL; /* Return value */
1347
1348
0
    FUNC_ENTER_NOAPI(NULL)
1349
1350
    /* Check arguments */
1351
0
    assert(rank <= H5S_MAX_RANK);
1352
1353
    /* Create the space and set the extent */
1354
0
    if (NULL == (ret_value = H5S_create(H5S_SIMPLE)))
1355
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, NULL, "can't create simple dataspace");
1356
0
    if (H5S_set_extent_simple(ret_value, rank, dims, maxdims) < 0)
1357
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "can't set dimensions");
1358
1359
0
done:
1360
0
    FUNC_LEAVE_NOAPI(ret_value)
1361
0
} /* end H5S_create_simple() */
1362
1363
/*-------------------------------------------------------------------------
1364
 * Function:    H5Sencode2
1365
 *
1366
 * Purpose:     Given a dataspace ID, converts the object description
1367
 *              (including selection) into binary in a buffer.
1368
 *              The selection will be encoded according to the file
1369
 *              format setting in the fapl.
1370
 *
1371
 * Return:      Success:    Non-negative
1372
 *              Failure:    Negative
1373
 *
1374
 *-------------------------------------------------------------------------
1375
 */
1376
herr_t
1377
H5Sencode2(hid_t obj_id, void *buf, size_t *nalloc, hid_t fapl_id)
1378
0
{
1379
0
    H5S_t *dspace;
1380
0
    herr_t ret_value = SUCCEED;
1381
1382
0
    FUNC_ENTER_API(FAIL)
1383
1384
    /* Check argument and retrieve object */
1385
0
    if (NULL == (dspace = (H5S_t *)H5I_object_verify(obj_id, H5I_DATASPACE)))
1386
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace");
1387
1388
    /* Verify access property list and set up collective metadata if appropriate */
1389
0
    if (H5CX_set_apl(&fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, true) < 0)
1390
0
        HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info");
1391
1392
0
    if (H5S_encode(dspace, (unsigned char **)&buf, nalloc) < 0)
1393
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode dataspace");
1394
1395
0
done:
1396
0
    FUNC_LEAVE_API(ret_value)
1397
0
} /* end H5Sencode2() */
1398
1399
/*-------------------------------------------------------------------------
1400
 * Function:    H5S_encode
1401
 *
1402
 * Purpose:     Private function for H5Sencode.  Converts an object
1403
 *              description for dataspace and its selection into binary
1404
 *              in a buffer.
1405
 *
1406
 * Return:      SUCCEED/FAIL
1407
 *
1408
 *-------------------------------------------------------------------------
1409
 */
1410
herr_t
1411
H5S_encode(H5S_t *obj, unsigned char **p, size_t *nalloc)
1412
0
{
1413
0
    H5F_t   *f = NULL;            /* Fake file structure*/
1414
0
    size_t   extent_size;         /* Size of serialized dataspace extent */
1415
0
    hssize_t sselect_size;        /* Signed size of serialized dataspace selection */
1416
0
    size_t   select_size;         /* Size of serialized dataspace selection */
1417
0
    herr_t   ret_value = SUCCEED; /* Return value */
1418
1419
0
    FUNC_ENTER_NOAPI_NOINIT
1420
1421
    /* Allocate "fake" file structure */
1422
0
    if (NULL == (f = H5F_fake_alloc((uint8_t)0)))
1423
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate fake file struct");
1424
1425
    /* Find out the size of buffer needed for extent */
1426
0
    if ((extent_size = H5O_msg_raw_size(f, H5O_SDSPACE_ID, true, obj)) == 0)
1427
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADSIZE, FAIL, "can't find dataspace size");
1428
1429
    /* Find out the size of buffer needed for selection */
1430
0
    if ((sselect_size = H5S_SELECT_SERIAL_SIZE(obj)) < 0)
1431
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADSIZE, FAIL, "can't find dataspace selection size");
1432
0
    H5_CHECKED_ASSIGN(select_size, size_t, sselect_size, hssize_t);
1433
1434
    /* Verify the size of buffer.  If it's not big enough, simply return the
1435
     * right size without filling the buffer. */
1436
0
    if (!*p || *nalloc < (extent_size + select_size + 1 + 1 + 1 + 4))
1437
0
        *nalloc = extent_size + select_size + 1 + 1 + 1 + 4;
1438
0
    else {
1439
0
        unsigned char *pp = (*p); /* Local pointer for decoding */
1440
1441
        /* Encode the type of the information */
1442
0
        *pp++ = H5O_SDSPACE_ID;
1443
1444
        /* Encode the version of the dataspace information */
1445
0
        *pp++ = H5S_ENCODE_VERSION;
1446
1447
        /* Encode the "size of size" information */
1448
0
        *pp++ = (unsigned char)H5F_SIZEOF_SIZE(f);
1449
1450
        /* Encode size of extent information. Pointer is actually moved in this macro. */
1451
0
        UINT32ENCODE(pp, extent_size);
1452
1453
        /* Encode the extent part of dataspace */
1454
0
        if (H5O_msg_encode(f, H5O_SDSPACE_ID, true, pp, obj) < 0)
1455
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode extent space");
1456
0
        pp += extent_size;
1457
1458
        /* Encode the selection part of dataspace.  */
1459
0
        *p = pp;
1460
0
        if (H5S_SELECT_SERIALIZE(obj, p) < 0)
1461
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode select space");
1462
0
    } /* end else */
1463
1464
0
done:
1465
    /* Release fake file structure */
1466
0
    if (f && H5F_fake_free(f) < 0)
1467
0
        HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release fake file struct");
1468
1469
0
    FUNC_LEAVE_NOAPI(ret_value)
1470
0
} /* end H5S_encode() */
1471
1472
/*-------------------------------------------------------------------------
1473
 * Function:    H5Sdecode
1474
 *
1475
 * Purpose:     Decode a binary object description of dataspace and
1476
 *              return a new object handle.
1477
 *
1478
 * Return:      Success:    dataspace ID(non-negative)
1479
 *
1480
 *              Failure:    H5I_INVALID_HID
1481
 *
1482
 *-------------------------------------------------------------------------
1483
 */
1484
hid_t
1485
H5Sdecode(const void *buf)
1486
0
{
1487
0
    H5S_t *ds;
1488
0
    hid_t  ret_value;
1489
1490
0
    FUNC_ENTER_API(H5I_INVALID_HID)
1491
1492
0
    if (buf == NULL)
1493
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "empty buffer");
1494
1495
0
    if ((ds = H5S_decode((const unsigned char **)&buf)) == NULL)
1496
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDECODE, H5I_INVALID_HID, "can't decode object");
1497
1498
    /* Register the type and return the ID */
1499
0
    if ((ret_value = H5I_register(H5I_DATASPACE, ds, true)) < 0)
1500
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace");
1501
1502
0
done:
1503
0
    FUNC_LEAVE_API(ret_value)
1504
0
} /* end H5Sdecode() */
1505
1506
/*-------------------------------------------------------------------------
1507
 * Function:    H5S_decode
1508
 *
1509
 * Purpose:     Private function for H5Sdecode.  Reconstructs a binary
1510
 *              description of dataspace and returns a new object handle.
1511
 *
1512
 * Return:      Success:    Pointer to a dataspace buffer
1513
 *
1514
 *              Failure:  NULL
1515
 *
1516
 *-------------------------------------------------------------------------
1517
 */
1518
H5S_t *
1519
H5S_decode(const unsigned char **p)
1520
0
{
1521
0
    H5F_t               *f = NULL;         /* Fake file structure*/
1522
0
    H5S_t               *ds;               /* Decoded dataspace */
1523
0
    H5S_extent_t        *extent;           /* Extent of decoded dataspace */
1524
0
    const unsigned char *pp = (*p);        /* Local pointer for decoding */
1525
0
    size_t               extent_size;      /* size of the extent message*/
1526
0
    uint8_t              sizeof_size;      /* 'Size of sizes' for file */
1527
0
    H5S_t               *ret_value = NULL; /* Return value */
1528
1529
0
    FUNC_ENTER_NOAPI_NOINIT
1530
1531
    /* Decode the type of the information */
1532
0
    if (*pp++ != H5O_SDSPACE_ID)
1533
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_BADMESG, NULL, "not an encoded dataspace");
1534
1535
    /* Decode the version of the dataspace information */
1536
0
    if (*pp++ != H5S_ENCODE_VERSION)
1537
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_VERSION, NULL, "unknown version of encoded dataspace");
1538
1539
    /* Decode the "size of size" information */
1540
0
    sizeof_size = *pp++;
1541
1542
    /* Allocate "fake" file structure */
1543
0
    if (NULL == (f = H5F_fake_alloc(sizeof_size)))
1544
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate fake file struct");
1545
1546
    /* Decode size of extent information */
1547
0
    UINT32DECODE(pp, extent_size);
1548
1549
    /* Decode the extent part of dataspace */
1550
    /* (pass mostly bogus file pointer and bogus DXPL) */
1551
0
    if (NULL == (extent = (H5S_extent_t *)H5O_msg_decode(f, NULL, H5O_SDSPACE_ID, extent_size, pp)))
1552
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDECODE, NULL, "can't decode object");
1553
0
    pp += extent_size;
1554
1555
    /* Copy the extent into dataspace structure */
1556
0
    if (NULL == (ds = H5FL_CALLOC(H5S_t)))
1557
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL,
1558
0
                    "memory allocation failed for dataspace conversion path table");
1559
0
    if (NULL == H5O_msg_copy(H5O_SDSPACE_ID, extent, &(ds->extent)))
1560
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy object");
1561
0
    if (H5S__extent_release(extent) < 0)
1562
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_CANTDELETE, NULL, "can't release previous dataspace");
1563
0
    extent = H5FL_FREE(H5S_extent_t, extent);
1564
1565
    /* Initialize to "all" selection. Deserialization relies on valid existing selection. */
1566
0
    if (H5S_select_all(ds, false) < 0)
1567
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection");
1568
1569
    /* Decode the select part of dataspace.
1570
     *  Because size of buffer is unknown, assume arbitrarily large buffer to allow decoding. */
1571
0
    *p = pp;
1572
0
    if (H5S_SELECT_DESERIALIZE(&ds, p, SIZE_MAX) < 0)
1573
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDECODE, NULL, "can't decode space selection");
1574
1575
    /* Set return value */
1576
0
    ret_value = ds;
1577
1578
0
done:
1579
    /* Release fake file structure */
1580
0
    if (f && H5F_fake_free(f) < 0)
1581
0
        HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, NULL, "unable to release fake file struct");
1582
1583
0
    FUNC_LEAVE_NOAPI(ret_value)
1584
0
} /* end H5S_decode() */
1585
1586
/*-------------------------------------------------------------------------
1587
 * Function:    H5S_get_simple_extent
1588
 *
1589
 * Purpose:     Internal function for retrieving the extent for a dataspace object
1590
 *
1591
 * Return:      Success:    Pointer to the extent for a dataspace (not copied)
1592
 *              Failure:    NULL
1593
 *
1594
 * Note:        This routine participates in the "Inlining C function pointers"
1595
 *              pattern, don't call it directly, use the appropriate macro
1596
 *              defined in H5Sprivate.h.
1597
 *
1598
 *-------------------------------------------------------------------------
1599
 */
1600
const H5S_extent_t *
1601
H5S_get_simple_extent(const H5S_t *space)
1602
0
{
1603
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
1604
1605
0
    assert(space);
1606
1607
0
    FUNC_LEAVE_NOAPI(&space->extent)
1608
0
} /* end H5S_get_simple_extent() */
1609
1610
/*-------------------------------------------------------------------------
1611
 * Function:    H5S_get_simple_extent_type
1612
 *
1613
 * Purpose:     Internal function for retrieving the type of extent for a dataspace object
1614
 *
1615
 * Return:      Success:    The class of the dataspace object
1616
 *
1617
 *              Failure:    N5S_NO_CLASS
1618
 *
1619
 * Note:        This routine participates in the "Inlining C function pointers"
1620
 *              pattern, don't call it directly, use the appropriate macro
1621
 *              defined in H5Sprivate.h.
1622
 *
1623
 *-------------------------------------------------------------------------
1624
 */
1625
H5S_class_t
1626
H5S_get_simple_extent_type(const H5S_t *space)
1627
0
{
1628
0
    H5S_class_t ret_value = H5S_NO_CLASS; /* Return value */
1629
1630
0
    FUNC_ENTER_NOAPI_NOERR
1631
1632
0
    assert(space);
1633
1634
0
    ret_value = H5S_GET_EXTENT_TYPE(space);
1635
1636
0
    FUNC_LEAVE_NOAPI(ret_value)
1637
0
} /* end H5S_get_simple_extent_type() */
1638
1639
/*-------------------------------------------------------------------------
1640
 * Function:    H5Sget_simple_extent_type
1641
 *
1642
 * Purpose:     Retrieves the type of extent for a dataspace object
1643
 *
1644
 * Return:      Success:    The class of the dataspace object
1645
 *
1646
 *              Failure:    N5S_NO_CLASS
1647
 *
1648
 *-------------------------------------------------------------------------
1649
 */
1650
H5S_class_t
1651
H5Sget_simple_extent_type(hid_t sid)
1652
0
{
1653
0
    H5S_t      *space;
1654
0
    H5S_class_t ret_value; /* Return value */
1655
1656
0
    FUNC_ENTER_API(H5S_NO_CLASS)
1657
1658
    /* Check arguments */
1659
0
    if (NULL == (space = (H5S_t *)H5I_object_verify(sid, H5I_DATASPACE)))
1660
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5S_NO_CLASS, "not a dataspace");
1661
1662
0
    ret_value = H5S_GET_EXTENT_TYPE(space);
1663
1664
0
done:
1665
0
    FUNC_LEAVE_API(ret_value)
1666
0
} /* end H5Sget_simple_extent_type() */
1667
1668
/*--------------------------------------------------------------------------
1669
 NAME
1670
    H5Sset_extent_none
1671
 PURPOSE
1672
    Resets the extent of a dataspace back to "none"
1673
 USAGE
1674
    herr_t H5Sset_extent_none(space_id)
1675
        hid_t space_id;         IN: Dataspace object to reset
1676
 RETURNS
1677
    Non-negative on success/Negative on failure
1678
 DESCRIPTION
1679
    This function resets the type of a dataspace to H5S_NULL with no
1680
    extent information stored for the dataspace.
1681
--------------------------------------------------------------------------*/
1682
herr_t
1683
H5Sset_extent_none(hid_t space_id)
1684
0
{
1685
0
    H5S_t *space;               /* Dataspace to modify */
1686
0
    herr_t ret_value = SUCCEED; /* Return value */
1687
1688
0
    FUNC_ENTER_API(FAIL)
1689
1690
    /* Check args */
1691
0
    if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
1692
0
        HGOTO_ERROR(H5E_ID, H5E_BADID, FAIL, "not a dataspace");
1693
1694
    /* Clear the previous extent from the dataspace */
1695
0
    if (H5S__extent_release(&space->extent) < 0)
1696
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_CANTDELETE, FAIL, "can't release previous dataspace");
1697
1698
0
    space->extent.type = H5S_NULL;
1699
1700
0
done:
1701
0
    FUNC_LEAVE_API(ret_value)
1702
0
} /* end H5Sset_extent_none() */
1703
1704
/*-------------------------------------------------------------------------
1705
 * Function:    H5S_set_extent
1706
 *
1707
 * Purpose:     Modify the dimensions of a dataspace.
1708
 *
1709
 * Return:      true/false/FAIL
1710
 *
1711
 *-------------------------------------------------------------------------
1712
 */
1713
htri_t
1714
H5S_set_extent(H5S_t *space, const hsize_t *size)
1715
0
{
1716
0
    unsigned u;                 /* Local index variable */
1717
0
    htri_t   ret_value = false; /* Return value */
1718
1719
0
    FUNC_ENTER_NOAPI(FAIL)
1720
1721
    /* Check args */
1722
0
    assert(space && H5S_SIMPLE == H5S_GET_EXTENT_TYPE(space));
1723
0
    assert(size);
1724
1725
    /* Verify that the dimensions being changed are allowed to change */
1726
0
    for (u = 0; u < space->extent.rank; u++)
1727
0
        if (space->extent.size[u] != size[u]) {
1728
            /* Check for invalid dimension size modification */
1729
0
            if (space->extent.max && H5S_UNLIMITED != space->extent.max[u] && space->extent.max[u] < size[u])
1730
0
                HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL,
1731
0
                            "dimension cannot exceed the existing maximal size (new: %llu max: %llu)",
1732
0
                            (unsigned long long)size[u], (unsigned long long)space->extent.max[u]);
1733
1734
            /* Indicate that dimension size can be modified */
1735
0
            ret_value = true;
1736
0
        } /* end if */
1737
1738
    /* Update dimension size(s) */
1739
0
    if (ret_value)
1740
0
        if (H5S_set_extent_real(space, size) < 0)
1741
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "failed to change dimension size(s)");
1742
1743
0
done:
1744
0
    FUNC_LEAVE_NOAPI(ret_value)
1745
0
} /* end H5S_set_extent() */
1746
1747
/*-------------------------------------------------------------------------
1748
 * Function: H5S_has_extent
1749
 *
1750
 * Purpose: Determines if a simple dataspace's extent has been set (e.g.,
1751
 *          by H5Sset_extent_simple() ).  Helps avoid write errors.
1752
 *
1753
 * Return: true if dataspace has extent set
1754
 *         false if dataspace's extent is uninitialized
1755
 *
1756
 *-------------------------------------------------------------------------
1757
 */
1758
H5_ATTR_PURE bool
1759
H5S_has_extent(const H5S_t *ds)
1760
62
{
1761
62
    bool ret_value = false; /* Return value */
1762
1763
62
    FUNC_ENTER_NOAPI_NOINIT_NOERR
1764
1765
62
    assert(ds);
1766
1767
62
    if (0 == ds->extent.rank && 0 == ds->extent.nelem && H5S_NULL != ds->extent.type)
1768
0
        ret_value = false;
1769
62
    else
1770
62
        ret_value = true;
1771
1772
62
    FUNC_LEAVE_NOAPI(ret_value)
1773
62
} /* end H5S_has_extent() */
1774
1775
/*-------------------------------------------------------------------------
1776
 * Function:    H5S_set_extent_real
1777
 *
1778
 * Purpose:     Modify the dimensions of a dataspace.
1779
 *
1780
 * Return:      Success: Non-negative
1781
 *              Failure: Negative
1782
 *
1783
 *-------------------------------------------------------------------------
1784
 */
1785
herr_t
1786
H5S_set_extent_real(H5S_t *space, const hsize_t *size)
1787
0
{
1788
0
    hsize_t  nelem;               /* Number of elements in extent */
1789
0
    unsigned u;                   /* Local index variable */
1790
0
    herr_t   ret_value = SUCCEED; /* Return value */
1791
1792
0
    FUNC_ENTER_NOAPI(FAIL)
1793
1794
    /* Check args */
1795
0
    assert(space && H5S_SIMPLE == H5S_GET_EXTENT_TYPE(space));
1796
0
    assert(size);
1797
1798
    /* Change the dataspace size & re-compute the number of elements in the extent */
1799
0
    for (u = 0, nelem = 1; u < space->extent.rank; u++) {
1800
0
        space->extent.size[u] = size[u];
1801
0
        nelem *= size[u];
1802
0
    } /* end for */
1803
0
    space->extent.nelem = nelem;
1804
1805
    /* If the selection is 'all', update the number of elements selected */
1806
0
    if (H5S_SEL_ALL == H5S_GET_SELECT_TYPE(space))
1807
0
        if (H5S_select_all(space, false) < 0)
1808
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection");
1809
1810
    /* Mark the dataspace as no longer shared if it was before */
1811
0
    if (H5O_msg_reset_share(H5O_SDSPACE_ID, space) < 0)
1812
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRESET, FAIL, "can't stop sharing dataspace");
1813
1814
0
done:
1815
0
    FUNC_LEAVE_NOAPI(ret_value)
1816
0
} /* end H5S_set_extent_real() */
1817
1818
/*-------------------------------------------------------------------------
1819
 * Function:    H5Sextent_equal
1820
 *
1821
 * Purpose:     Determines if two dataspace extents are equal.
1822
 *
1823
 * Return:      Success:    true if equal, false if unequal
1824
 *
1825
 *              Failure:    FAIL
1826
 *
1827
 *-------------------------------------------------------------------------
1828
 */
1829
htri_t
1830
H5Sextent_equal(hid_t space1_id, hid_t space2_id)
1831
0
{
1832
0
    const H5S_t *ds1; /* Dataspaces to compare */
1833
0
    const H5S_t *ds2;
1834
0
    htri_t       ret_value;
1835
1836
0
    FUNC_ENTER_API(FAIL)
1837
1838
    /* check args */
1839
0
    if (NULL == (ds1 = (const H5S_t *)H5I_object_verify(space1_id, H5I_DATASPACE)) ||
1840
0
        NULL == (ds2 = (const H5S_t *)H5I_object_verify(space2_id, H5I_DATASPACE)))
1841
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace");
1842
1843
    /* Check dataspaces for extent's equality */
1844
0
    if ((ret_value = H5S_extent_equal(ds1, ds2)) < 0)
1845
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "dataspace comparison failed");
1846
1847
0
done:
1848
0
    FUNC_LEAVE_API(ret_value)
1849
0
} /* end H5Sextent_equal() */
1850
1851
/*--------------------------------------------------------------------------
1852
 NAME
1853
    H5S_extent_equal
1854
 PURPOSE
1855
    Check if two dataspaces have equal extents
1856
 USAGE
1857
    htri_t H5S_extent_equal(ds1, ds2)
1858
        H5S_t *ds1, *ds2;            IN: Dataspace objects to compare
1859
 RETURNS
1860
     true if equal, false if unequal on success/Negative on failure
1861
 DESCRIPTION
1862
    Compare two dataspaces if their extents are identical.
1863
--------------------------------------------------------------------------*/
1864
H5_ATTR_PURE htri_t
1865
H5S_extent_equal(const H5S_t *ds1, const H5S_t *ds2)
1866
0
{
1867
0
    unsigned u;                /* Local index variable */
1868
0
    htri_t   ret_value = true; /* Return value */
1869
1870
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
1871
1872
    /* Check args */
1873
0
    assert(ds1);
1874
0
    assert(ds2);
1875
1876
    /* Make certain the dataspaces are the same type */
1877
0
    if (ds1->extent.type != ds2->extent.type)
1878
0
        HGOTO_DONE(false);
1879
1880
    /* Make certain the dataspaces are the same rank */
1881
0
    if (ds1->extent.rank != ds2->extent.rank)
1882
0
        HGOTO_DONE(false);
1883
1884
    /* Make certain the dataspaces' current dimensions are the same size */
1885
0
    if (ds1->extent.rank > 0) {
1886
0
        assert(ds1->extent.size);
1887
0
        assert(ds2->extent.size);
1888
0
        for (u = 0; u < ds1->extent.rank; u++)
1889
0
            if (ds1->extent.size[u] != ds2->extent.size[u])
1890
0
                HGOTO_DONE(false);
1891
0
    } /* end if */
1892
1893
    /* Make certain the dataspaces' maximum dimensions are the same size */
1894
0
    if (ds1->extent.rank > 0) {
1895
        /* Check for no maximum dimensions on dataspaces */
1896
0
        if (ds1->extent.max != NULL && ds2->extent.max != NULL) {
1897
0
            for (u = 0; u < ds1->extent.rank; u++)
1898
0
                if (ds1->extent.max[u] != ds2->extent.max[u])
1899
0
                    HGOTO_DONE(false);
1900
0
        } /* end if */
1901
0
        else if ((ds1->extent.max == NULL && ds2->extent.max != NULL) ||
1902
0
                 (ds1->extent.max != NULL && ds2->extent.max == NULL))
1903
0
            HGOTO_DONE(false);
1904
0
    } /* end if */
1905
1906
0
done:
1907
0
    FUNC_LEAVE_NOAPI(ret_value)
1908
0
} /* end H5S_extent_equal() */
1909
1910
/*-------------------------------------------------------------------------
1911
 * Function:    H5S_extent_nelem
1912
 *
1913
 * Purpose:     Determines how many elements a dataset extent describes.
1914
 *
1915
 * Return:      Success:    Number of data points in the dataset extent.
1916
 *              Failure:    Negative
1917
 *
1918
 *-------------------------------------------------------------------------
1919
 */
1920
H5_ATTR_PURE hsize_t
1921
H5S_extent_nelem(const H5S_extent_t *ext)
1922
0
{
1923
0
    FUNC_ENTER_NOAPI_NOINIT_NOERR
1924
1925
    /* check args */
1926
0
    assert(ext);
1927
1928
    /* Return the number of elements in extent */
1929
0
    FUNC_LEAVE_NOAPI(ext->nelem)
1930
0
} /* end H5S_extent_nelem() */
1931
1932
/*-------------------------------------------------------------------------
1933
 * Function:    H5S_set_version
1934
 *
1935
 * Purpose:     Set the version to encode a dataspace with.
1936
 *
1937
 * Return:      Non-negative on success/Negative on failure
1938
 *
1939
 *-------------------------------------------------------------------------
1940
 */
1941
herr_t
1942
H5S_set_version(H5F_t *f, H5S_t *ds)
1943
0
{
1944
0
    unsigned version;             /* Message version */
1945
0
    herr_t   ret_value = SUCCEED; /* Return value */
1946
1947
0
    FUNC_ENTER_NOAPI(FAIL)
1948
1949
    /* Sanity check */
1950
0
    assert(f);
1951
0
    assert(ds);
1952
1953
    /* Upgrade to the version indicated by the file's low bound if higher */
1954
0
    version = MAX(ds->extent.version, H5O_sdspace_ver_bounds[H5F_LOW_BOUND(f)]);
1955
1956
    /* Version bounds check */
1957
0
    if (version > H5O_sdspace_ver_bounds[H5F_HIGH_BOUND(f)])
1958
0
        HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, FAIL, "Dataspace version out of bounds");
1959
1960
    /* Set the message version */
1961
0
    ds->extent.version = version;
1962
1963
0
done:
1964
0
    FUNC_LEAVE_NOAPI(ret_value)
1965
0
} /* end H5S_set_version() */