Coverage Report

Created: 2026-08-31 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Tprecis.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 Info: This module contains the functionality for setting & querying
15
 *      the datatype precision for the H5T interface.
16
 */
17
18
#include "H5Tmodule.h" /* This source code file is part of the H5T module */
19
20
#include "H5private.h"  /* Generic Functions      */
21
#include "H5Eprivate.h" /* Error handling       */
22
#include "H5Iprivate.h" /* IDs            */
23
#include "H5Tpkg.h"     /* Datatypes        */
24
25
/* Static local functions */
26
static herr_t H5T__set_precision(const H5T_t *dt, size_t prec);
27
28
/*-------------------------------------------------------------------------
29
 * Function:  H5Tget_precision
30
 *
31
 * Purpose: Gets the precision of a datatype.  The precision is
32
 *    the number of significant bits which, unless padding is
33
 *    present, is 8 times larger than the value returned by
34
 *    H5Tget_size().
35
 *
36
 * Return:  Success:  Number of significant bits
37
 *
38
 *    Failure:  0 (all atomic types have at least one
39
 *        significant bit)
40
 *
41
 *-------------------------------------------------------------------------
42
 */
43
size_t
44
H5Tget_precision(hid_t type_id)
45
0
{
46
0
    H5T_t *dt;
47
0
    size_t ret_value;
48
49
0
    FUNC_ENTER_API(0)
50
51
    /* Check args */
52
0
    if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
53
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a datatype");
54
55
    /* Get precision */
56
0
    if ((ret_value = H5T_get_precision(dt)) == 0)
57
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, 0, "can't get precision for specified datatype");
58
59
0
done:
60
0
    FUNC_LEAVE_API(ret_value)
61
0
} /* end H5Tget_precision() */
62
63
/*-------------------------------------------------------------------------
64
 * Function:  H5T_get_precision
65
 *
66
 * Purpose: Gets the precision of a datatype.  The precision is
67
 *    the number of significant bits which, unless padding is
68
 *    present, is 8 times larger than the value returned by
69
 *    H5Tget_size().
70
 *
71
 * Return:  Success:  Number of significant bits
72
 *    Failure:  0 (all atomic types have at least one
73
 *        significant bit)
74
 *
75
 *-------------------------------------------------------------------------
76
 */
77
size_t
78
H5T_get_precision(const H5T_t *dt)
79
0
{
80
0
    size_t ret_value = 0; /* Return value */
81
82
0
    FUNC_ENTER_NOAPI(0)
83
84
    /* Defer to parent*/
85
0
    while (dt->shared->parent)
86
0
        dt = dt->shared->parent;
87
0
    if (!H5T_IS_ATOMIC(dt->shared))
88
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, 0, "operation not defined for specified datatype");
89
90
    /* Precision */
91
0
    ret_value = dt->shared->u.atomic.prec;
92
93
0
done:
94
0
    FUNC_LEAVE_NOAPI(ret_value)
95
0
} /* end H5T_get_precision() */
96
97
/*-------------------------------------------------------------------------
98
 * Function:  H5Tset_precision
99
 *
100
 * Purpose: Sets the precision of a datatype.  The precision is
101
 *    the number of significant bits which, unless padding is
102
 *    present, is 8 times larger than the value returned by
103
 *    H5Tget_size().
104
 *
105
 *    If the precision is increased then the offset is decreased
106
 *    and then the size is increased to insure that significant
107
 *    bits do not "hang over" the edge of the datatype.
108
 *
109
 *    The precision property of strings is read-only.
110
 *
111
 *    When decreasing the precision of a floating point type, set
112
 *    the locations and sizes of the sign, mantissa, and exponent
113
 *    fields first.
114
 *
115
 * Return:  Non-negative on success/Negative on failure
116
 *
117
 *-------------------------------------------------------------------------
118
 */
119
herr_t
120
H5Tset_precision(hid_t type_id, size_t prec)
121
0
{
122
0
    H5T_t *dt        = NULL;
123
0
    herr_t ret_value = SUCCEED; /* Return value */
124
125
0
    FUNC_ENTER_API(FAIL)
126
127
    /* Check args */
128
0
    if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
129
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
130
0
    if (H5T_STATE_TRANSIENT != dt->shared->state)
131
0
        HGOTO_ERROR(H5E_ARGS, H5E_CANTSET, FAIL, "datatype is read-only");
132
0
    if (NULL != dt->vol_obj)
133
0
        HGOTO_ERROR(H5E_ARGS, H5E_CANTSET, FAIL, "datatype is committed");
134
0
    if (prec == 0)
135
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "precision must be positive");
136
0
    if (H5T_ENUM == dt->shared->type && dt->shared->u.enumer.nmembs > 0)
137
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "operation not allowed after members are defined");
138
0
    if (H5T_STRING == dt->shared->type)
139
0
        HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "precision for this type is read-only");
140
0
    if (H5T_COMPOUND == dt->shared->type || H5T_OPAQUE == dt->shared->type)
141
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "operation not defined for specified datatype");
142
143
    /* Do the work */
144
0
    if (H5T__set_precision(dt, prec) < 0)
145
0
        HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "unable to set precision");
146
147
0
done:
148
0
    FUNC_LEAVE_API(ret_value)
149
0
}
150
151
/*-------------------------------------------------------------------------
152
 * Function:  H5T__set_precision
153
 *
154
 * Purpose: Sets the precision of a datatype.  The precision is
155
 *    the number of significant bits which, unless padding is
156
 *    present, is 8 times larger than the value returned by
157
 *    H5Tget_size().
158
 *
159
 *    If the precision is increased then the offset is decreased
160
 *    and then the size is increased to insure that significant
161
 *    bits do not "hang over" the edge of the datatype.
162
 *
163
 *    The precision property of strings is read-only.
164
 *
165
 *    When decreasing the precision of a floating point type, set
166
 *    the locations and sizes of the sign, mantissa, and exponent
167
 *    fields first.
168
 *
169
 * Return:  Non-negative on success/Negative on failure
170
 *
171
 *-------------------------------------------------------------------------
172
 */
173
static herr_t
174
H5T__set_precision(const H5T_t *dt, size_t prec)
175
0
{
176
0
    size_t offset, size;
177
0
    herr_t ret_value = SUCCEED; /* Return value */
178
179
0
    FUNC_ENTER_PACKAGE
180
181
    /* Check args */
182
0
    assert(dt);
183
0
    assert(prec > 0);
184
0
    assert(H5T_OPAQUE != dt->shared->type);
185
0
    assert(H5T_COMPOUND != dt->shared->type);
186
0
    assert(H5T_STRING != dt->shared->type);
187
0
    assert(!(H5T_ENUM == dt->shared->type && 0 == dt->shared->u.enumer.nmembs));
188
189
0
    if (dt->shared->parent) {
190
0
        if (H5T__set_precision(dt->shared->parent, prec) < 0)
191
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "unable to set precision for base type");
192
193
        /* Adjust size of datatype appropriately */
194
0
        if (dt->shared->type == H5T_ARRAY)
195
0
            dt->shared->size = dt->shared->parent->shared->size * dt->shared->u.array.nelem;
196
0
        else if (dt->shared->type == H5T_COMPLEX)
197
0
            dt->shared->size = 2 * dt->shared->parent->shared->size;
198
0
        else if (dt->shared->type != H5T_VLEN)
199
0
            dt->shared->size = dt->shared->parent->shared->size;
200
0
    }
201
0
    else {
202
0
        if (H5T_IS_ATOMIC(dt->shared)) {
203
            /* Adjust the offset and size */
204
0
            offset = dt->shared->u.atomic.offset;
205
0
            size   = dt->shared->size;
206
0
            if (prec > 8 * size)
207
0
                offset = 0;
208
0
            else if (offset + prec > 8 * size)
209
0
                offset = 8 * size - prec;
210
0
            if (prec > 8 * size)
211
0
                size = (prec + 7) / 8;
212
213
            /* Check that things are still kosher */
214
0
            switch (dt->shared->type) {
215
0
                case H5T_INTEGER:
216
0
                case H5T_TIME:
217
0
                case H5T_BITFIELD:
218
                    /* nothing to check */
219
0
                    break;
220
221
0
                case H5T_FLOAT:
222
                    /*
223
                     * The sign, mantissa, and exponent fields should be adjusted
224
                     * first when decreasing the precision of a floating point
225
                     * type.
226
                     */
227
0
                    if (dt->shared->u.atomic.u.f.sign >= prec + offset ||
228
0
                        dt->shared->u.atomic.u.f.epos + dt->shared->u.atomic.u.f.esize > prec + offset ||
229
0
                        dt->shared->u.atomic.u.f.mpos + dt->shared->u.atomic.u.f.msize > prec + offset)
230
0
                        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
231
0
                                    "adjust sign, mantissa, and exponent fields first");
232
0
                    break;
233
234
0
                case H5T_NO_CLASS:
235
0
                case H5T_STRING:
236
0
                case H5T_OPAQUE:
237
0
                case H5T_COMPOUND:
238
0
                case H5T_REFERENCE:
239
0
                case H5T_ENUM:
240
0
                case H5T_VLEN:
241
0
                case H5T_ARRAY:
242
0
                case H5T_COMPLEX:
243
0
                case H5T_NCLASSES:
244
0
                default:
245
0
                    HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "operation not defined for datatype class");
246
0
            } /* end switch */
247
248
            /* Commit */
249
0
            dt->shared->size            = size;
250
0
            dt->shared->u.atomic.offset = offset;
251
0
            dt->shared->u.atomic.prec   = prec;
252
0
        } /* end if */
253
0
        else
254
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for specified datatype");
255
0
    } /* end else */
256
257
0
done:
258
0
    FUNC_LEAVE_NOAPI(ret_value)
259
0
}