Coverage Report

Created: 2026-03-03 00:31

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