Coverage Report

Created: 2026-01-09 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Tconv_enum.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
 * Purpose: Datatype conversion functions for enum datatypes
15
 */
16
17
/****************/
18
/* Module Setup */
19
/****************/
20
#include "H5Tmodule.h" /* This source code file is part of the H5T module */
21
22
/***********/
23
/* Headers */
24
/***********/
25
#include "H5private.h"  /* Generic Functions                    */
26
#include "H5Eprivate.h" /* Error handling                       */
27
#include "H5Tconv.h"    /* Datatype conversions                 */
28
#include "H5Tconv_enum.h"
29
30
/******************/
31
/* Local Typedefs */
32
/******************/
33
34
/* Private conversion data for enum datatypes */
35
typedef struct H5T_conv_enum_t {
36
    H5T_t   *src_copy; /* cached copy of source datatype      */
37
    H5T_t   *dst_copy; /* cached copy of destination datatype */
38
    int      base;     /* lowest `in' value                   */
39
    unsigned length;   /* num elements in arrays              */
40
    int     *src2dst;  /* map from src to dst index           */
41
} H5T_conv_enum_t;
42
43
/********************/
44
/* Local Prototypes */
45
/********************/
46
47
static herr_t H5T__conv_enum_init(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata,
48
                                  const H5T_conv_ctx_t *conv_ctx);
49
static herr_t H5T__conv_enum_free(H5T_conv_enum_t *priv);
50
51
/*-------------------------------------------------------------------------
52
 * Function:    H5T__conv_enum_init
53
 *
54
 * Purpose:     Initialize private data for enum datatype conversions.
55
 *
56
 * Return:      Non-negative on success/Negative on failure
57
 *
58
 *-------------------------------------------------------------------------
59
 */
60
static herr_t
61
H5T__conv_enum_init(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx)
62
0
{
63
0
    H5T_conv_enum_t *priv          = NULL; /* Private conversion data */
64
0
    int             *map           = NULL; /* Map from src value to dst idx */
65
0
    bool             rebuild_cache = false;
66
0
    herr_t           ret_value     = SUCCEED;
67
68
0
    FUNC_ENTER_PACKAGE
69
70
0
    cdata->need_bkg = H5T_BKG_NO;
71
72
0
    priv = (H5T_conv_enum_t *)(cdata->priv);
73
0
    if (!priv) {
74
0
        if (NULL == (priv = (H5T_conv_enum_t *)(cdata->priv = calloc(1, sizeof(*priv)))))
75
0
            HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
76
0
        rebuild_cache = true;
77
0
    }
78
0
    else {
79
        /* Check if we need to rebuild our cache. For now, treat
80
         * enums as different even if one is just a subset of the
81
         * other
82
         */
83
0
        if (cdata->command == H5T_CONV_CONV && conv_ctx->u.conv.recursive)
84
            /* Recursive conversion; we can reuse the cache */
85
0
            rebuild_cache = false;
86
0
        else {
87
0
            if (0 != H5T_cmp(src, priv->src_copy, false) || 0 != H5T_cmp(dst, priv->dst_copy, false))
88
0
                rebuild_cache = true;
89
0
        }
90
0
    }
91
92
0
    if (rebuild_cache) {
93
0
        H5T_shared_t *src_sh;
94
0
        H5T_shared_t *dst_sh;
95
0
        size_t        src_nmembs;
96
0
        size_t        dst_nmembs;
97
0
        void         *tmp_realloc;
98
99
        /* Allocate everything we need to cache */
100
0
        if (priv->src_copy && H5T_close(priv->src_copy) < 0)
101
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close copied source datatype");
102
0
        if (priv->dst_copy && H5T_close(priv->dst_copy) < 0)
103
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close copied destination datatype");
104
105
0
        if (NULL == (priv->src_copy = H5T_copy(src, H5T_COPY_ALL)))
106
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy source datatype");
107
0
        if (NULL == (priv->dst_copy = H5T_copy(dst, H5T_COPY_ALL)))
108
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "unable to copy destination datatype");
109
110
        /* Nothing more to do if enum has no members */
111
0
        if (0 == src->shared->u.enumer.nmembs)
112
0
            HGOTO_DONE(SUCCEED);
113
114
0
        src_sh     = priv->src_copy->shared;
115
0
        dst_sh     = priv->src_copy->shared;
116
0
        src_nmembs = src_sh->u.enumer.nmembs;
117
0
        dst_nmembs = dst_sh->u.enumer.nmembs;
118
119
0
        if (NULL == (tmp_realloc = realloc(priv->src2dst, src_nmembs * sizeof(int)))) {
120
0
            free(priv->src2dst);
121
0
            HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL,
122
0
                        "unable to allocate space for source to destination enum mapping");
123
0
        }
124
0
        priv->src2dst = tmp_realloc;
125
126
        /*
127
         * Check that the source symbol names are a subset of the destination
128
         * symbol names and build a map from source member index to destination
129
         * member index.
130
         */
131
0
        H5T__sort_name(priv->src_copy, NULL);
132
0
        H5T__sort_name(priv->dst_copy, NULL);
133
0
        for (size_t i = 0, j = 0; i < src_nmembs && j < dst_nmembs; i++, j++) {
134
0
            char *src_name = src_sh->u.enumer.name[i];
135
0
            char *dst_name = dst_sh->u.enumer.name[j];
136
137
0
            while (j < dst_nmembs && strcmp(src_name, dst_name) != 0)
138
0
                j++;
139
140
0
            if (j >= dst_nmembs)
141
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
142
0
                            "source enum type is not a subset of destination enum type");
143
144
0
            H5_CHECKED_ASSIGN(priv->src2dst[i], int, j, size_t);
145
0
        }
146
147
        /*
148
         * The conversion function will use an O(log N) lookup method for each
149
         * value converted. However, if all of the following constraints are met
150
         * then we can build a perfect hash table and use an O(1) lookup method.
151
         *
152
         *      A: The source datatype size matches one of our native datatype
153
         *         sizes.
154
         *
155
         *      B: After casting the source value bit pattern to a native type
156
         *         the size of the range of values is less than 20% larger than
157
         *         the number of values.
158
         *
159
         * If this special case is met then we use the source bit pattern cast as
160
         * a native integer type as an index into the `val2dst'. The values of
161
         * that array are the index numbers in the destination type or negative
162
         * if the entry is unused.
163
         *
164
         * (This optimized algorithm doesn't work when the byte orders are different.
165
         * The code such as "n = *((int *)((void *)((uint8_t *)src_sh->u.enumer.value + (i *
166
         * src_sh->size))));" can change the value significantly. i.g. if the source value is big-endian
167
         * 0x0000000f, executing the casting on little-endian machine will get a big number 0x0f000000. Then
168
         * it can't meet the condition "if (src_nmembs < 2 || ((double)length / (double)src_nmembs <
169
         * (double)(1.2F)))" Because this is the optimized code, we won't fix it. It should still work in some
170
         * situations. SLU - 2011/5/24)
171
         */
172
0
        if (1 == src_sh->size || sizeof(short) == src_sh->size || sizeof(int) == src_sh->size) {
173
0
            unsigned length;
174
0
            int      domain[2] = {0, 0}; /* Min and max source values */
175
176
0
            for (size_t i = 0; i < src_nmembs; i++) {
177
0
                int n;
178
179
0
                if (1 == src_sh->size)
180
0
                    n = *((signed char *)((uint8_t *)src_sh->u.enumer.value + i));
181
0
                else if (sizeof(short) == src_sh->size)
182
0
                    n = *((short *)((void *)((uint8_t *)src_sh->u.enumer.value + (i * src_sh->size))));
183
0
                else
184
0
                    n = *((int *)((void *)((uint8_t *)src_sh->u.enumer.value + (i * src_sh->size))));
185
0
                if (0 == i) {
186
0
                    domain[0] = domain[1] = n;
187
0
                }
188
0
                else {
189
0
                    domain[0] = MIN(domain[0], n);
190
0
                    domain[1] = MAX(domain[1], n);
191
0
                }
192
0
            }
193
0
            assert(domain[1] >= domain[0]);
194
195
0
            length = (unsigned)(domain[1] - domain[0]) + 1;
196
0
            if (src_nmembs < 2 || ((double)length / (double)src_nmembs < (double)(1.2F))) {
197
0
                priv->base   = domain[0];
198
0
                priv->length = length;
199
200
0
                if (NULL == (map = malloc(length * sizeof(int))))
201
0
                    HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "memory allocation failed");
202
203
0
                for (size_t i = 0; i < length; i++)
204
0
                    map[i] = -1; /*entry unused*/
205
206
0
                for (size_t i = 0; i < src_nmembs; i++) {
207
0
                    int n;
208
209
0
                    if (1 == src_sh->size)
210
0
                        n = *((signed char *)((uint8_t *)src_sh->u.enumer.value + i));
211
0
                    else if (sizeof(short) == src_sh->size)
212
0
                        n = *((short *)((void *)((uint8_t *)src_sh->u.enumer.value + (i * src_sh->size))));
213
0
                    else
214
0
                        n = *((int *)((void *)((uint8_t *)src_sh->u.enumer.value + (i * src_sh->size))));
215
0
                    n -= priv->base;
216
0
                    assert(n >= 0 && (unsigned)n < priv->length);
217
0
                    assert(map[n] < 0);
218
0
                    map[n] = priv->src2dst[i];
219
0
                }
220
221
                /*
222
                 * Replace original src2dst array with our new one. The original
223
                 * was indexed by source member number while the new one is
224
                 * indexed by source values.
225
                 */
226
0
                free(priv->src2dst);
227
0
                priv->src2dst = map;
228
229
0
                HGOTO_DONE(SUCCEED);
230
0
            }
231
0
        }
232
233
        /* Sort source type by value and adjust src2dst[] appropriately */
234
0
        H5T__sort_value(priv->src_copy, priv->src2dst);
235
0
    }
236
237
#ifdef H5T_DEBUG
238
    if (H5DEBUG(T)) {
239
        fprintf(H5DEBUG(T), "      Using %s mapping function%s\n", priv->length ? "O(1)" : "O(log N)",
240
                priv->length ? "" : ", where N is the number of enum members");
241
    }
242
#endif
243
244
0
done:
245
0
    if (ret_value < 0 && priv) {
246
0
        if (map) {
247
0
            free(map);
248
0
            priv->src2dst = NULL;
249
0
        }
250
251
0
        if (H5T__conv_enum_free(priv) < 0)
252
0
            HDONE_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "can't free enum conversion data");
253
254
0
        cdata->priv = NULL;
255
0
    }
256
257
0
    FUNC_LEAVE_NOAPI(ret_value)
258
0
} /* end H5T__conv_enum_init() */
259
260
/*-------------------------------------------------------------------------
261
 * Function:    H5T__conv_enum_free
262
 *
263
 * Purpose:     Free the private data structure used by the enum conversion
264
 *              functions.
265
 *
266
 * Return:      Non-negative on success/Negative on failure
267
 *
268
 *-------------------------------------------------------------------------
269
 */
270
static herr_t
271
H5T__conv_enum_free(H5T_conv_enum_t *priv)
272
0
{
273
0
    herr_t ret_value = SUCCEED;
274
275
0
    FUNC_ENTER_PACKAGE
276
277
0
    if (priv) {
278
0
        free(priv->src2dst);
279
280
0
        if (priv->dst_copy && H5T_close(priv->dst_copy) < 0)
281
0
            HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close copied source datatype");
282
0
        if (priv->src_copy && H5T_close(priv->src_copy) < 0)
283
0
            HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close copied destination datatype");
284
285
0
        free(priv);
286
0
    }
287
288
0
    FUNC_LEAVE_NOAPI(ret_value)
289
0
} /* end H5T__conv_enum_free() */
290
291
/*-------------------------------------------------------------------------
292
 * Function:    H5T__conv_enum
293
 *
294
 * Purpose:     Converts one type of enumerated data to another.
295
 *
296
 * Return:      Non-negative on success/Negative on failure
297
 *
298
 *-------------------------------------------------------------------------
299
 */
300
herr_t
301
H5T__conv_enum(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx,
302
               size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *_buf,
303
               void H5_ATTR_UNUSED *bkg)
304
0
{
305
0
    H5T_conv_enum_t *priv   = (H5T_conv_enum_t *)(cdata->priv);
306
0
    H5T_shared_t    *src_sh = NULL;
307
0
    H5T_shared_t    *dst_sh = NULL;
308
0
    uint8_t         *buf    = (uint8_t *)_buf; /*cast for pointer arithmetic    */
309
0
    uint8_t         *s = NULL, *d = NULL;      /*src and dst BUF pointers    */
310
0
    ssize_t          src_delta, dst_delta;     /*conversion strides        */
311
0
    int              n;                        /*src value cast as native int    */
312
0
    H5T_conv_ret_t   except_ret;               /*return of callback function   */
313
0
    size_t           i;                        /*counters            */
314
0
    herr_t           ret_value = SUCCEED;      /* Return value                 */
315
316
0
    FUNC_ENTER_PACKAGE
317
318
0
    switch (cdata->command) {
319
0
        case H5T_CONV_INIT:
320
            /*
321
             * Determine if this conversion function applies to the conversion
322
             * path SRC->DST.  If not return failure; otherwise initialize
323
             * the `priv' field of `cdata' with information about the underlying
324
             * integer conversion.
325
             */
326
0
            if (NULL == src || NULL == dst)
327
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a datatype");
328
0
            if (H5T_ENUM != src->shared->type)
329
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a H5T_ENUM datatype");
330
0
            if (H5T_ENUM != dst->shared->type)
331
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a H5T_ENUM datatype");
332
333
0
            if (H5T__conv_enum_init(src, dst, cdata, conv_ctx) < 0)
334
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize private data");
335
0
            break;
336
337
0
        case H5T_CONV_FREE: {
338
0
            herr_t status = H5T__conv_enum_free(priv);
339
0
            cdata->priv   = NULL;
340
0
            if (status < 0)
341
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free private conversion data");
342
343
0
            break;
344
0
        }
345
346
0
        case H5T_CONV_CONV:
347
0
            if (NULL == src || NULL == dst)
348
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
349
0
            if (NULL == conv_ctx)
350
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid datatype conversion context pointer");
351
0
            if (H5T_ENUM != src->shared->type)
352
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a H5T_ENUM datatype");
353
0
            if (H5T_ENUM != dst->shared->type)
354
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a H5T_ENUM datatype");
355
356
            /* Reuse cache if possible, rebuild otherwise */
357
0
            if (H5T__conv_enum_init(src, dst, cdata, conv_ctx) < 0)
358
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize private data");
359
360
0
            src_sh = priv->src_copy->shared;
361
0
            dst_sh = priv->dst_copy->shared;
362
363
            /*
364
             * Direction of conversion.
365
             */
366
0
            if (buf_stride) {
367
0
                H5_CHECK_OVERFLOW(buf_stride, size_t, ssize_t);
368
0
                src_delta = dst_delta = (ssize_t)buf_stride;
369
0
                s = d = buf;
370
0
            }
371
0
            else if (dst_sh->size <= src_sh->size) {
372
0
                H5_CHECKED_ASSIGN(src_delta, ssize_t, src_sh->size, size_t);
373
0
                H5_CHECKED_ASSIGN(dst_delta, ssize_t, dst_sh->size, size_t);
374
0
                s = d = buf;
375
0
            }
376
0
            else {
377
0
                H5_CHECK_OVERFLOW(src_sh->size, size_t, ssize_t);
378
0
                H5_CHECK_OVERFLOW(dst_sh->size, size_t, ssize_t);
379
0
                src_delta = -(ssize_t)src_sh->size;
380
0
                dst_delta = -(ssize_t)dst_sh->size;
381
0
                s         = buf + (nelmts - 1) * src_sh->size;
382
0
                d         = buf + (nelmts - 1) * dst_sh->size;
383
0
            }
384
385
0
            if (priv->length) {
386
0
                for (i = 0; i < nelmts; i++, s += src_delta, d += dst_delta) {
387
                    /* Use O(1) lookup */
388
                    /* (The casting won't work when the byte orders are different. i.g. if the source value
389
                     * is big-endian 0x0000000f, the direct casting "n = *((int *)((void *)s));" will make
390
                     * it a big number 0x0f000000 on little-endian machine. But we won't fix it because it's
391
                     * an optimization code. Please also see the comment in the H5T__conv_enum_init()
392
                     * function. SLU - 2011/5/24)
393
                     */
394
0
                    if (1 == src_sh->size)
395
0
                        n = *((signed char *)s);
396
0
                    else if (sizeof(short) == src_sh->size)
397
0
                        n = *((short *)((void *)s));
398
0
                    else
399
0
                        n = *((int *)((void *)s));
400
0
                    n -= priv->base;
401
0
                    if (n < 0 || (unsigned)n >= priv->length || priv->src2dst[n] < 0) {
402
                        /*overflow*/
403
0
                        except_ret = H5T_CONV_UNHANDLED;
404
405
                        /* If user's exception handler is present, use it*/
406
0
                        if (conv_ctx->u.conv.cb_struct.func) {
407
                            /* Prepare & restore library for user callback */
408
0
                            H5_BEFORE_USER_CB(FAIL)
409
0
                                {
410
0
                                    except_ret = (conv_ctx->u.conv.cb_struct.func)(
411
0
                                        H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id,
412
0
                                        conv_ctx->u.conv.dst_type_id, s, d,
413
0
                                        conv_ctx->u.conv.cb_struct.user_data);
414
0
                                }
415
0
                            H5_AFTER_USER_CB(FAIL)
416
0
                        }
417
418
0
                        if (except_ret == H5T_CONV_UNHANDLED)
419
0
                            memset(d, 0xff, dst_sh->size);
420
0
                        else if (except_ret == H5T_CONV_ABORT)
421
0
                            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL,
422
0
                                        "can't handle conversion exception");
423
0
                    }
424
0
                    else
425
0
                        H5MM_memcpy(d,
426
0
                                    (uint8_t *)dst_sh->u.enumer.value +
427
0
                                        ((unsigned)priv->src2dst[n] * dst_sh->size),
428
0
                                    dst_sh->size);
429
0
                }
430
0
            }
431
0
            else {
432
0
                for (i = 0; i < nelmts; i++, s += src_delta, d += dst_delta) {
433
                    /* Use O(log N) lookup */
434
0
                    unsigned lt = 0;
435
0
                    unsigned rt = src_sh->u.enumer.nmembs;
436
0
                    unsigned md = 0;
437
0
                    int      cmp;
438
439
0
                    while (lt < rt) {
440
0
                        md = (lt + rt) / 2;
441
0
                        cmp =
442
0
                            memcmp(s, (uint8_t *)src_sh->u.enumer.value + (md * src_sh->size), src_sh->size);
443
0
                        if (cmp < 0)
444
0
                            rt = md;
445
0
                        else if (cmp > 0)
446
0
                            lt = md + 1;
447
0
                        else
448
0
                            break;
449
0
                    } /* end while */
450
0
                    if (lt >= rt) {
451
0
                        except_ret = H5T_CONV_UNHANDLED;
452
453
                        /* If user's exception handler is present, use it*/
454
0
                        if (conv_ctx->u.conv.cb_struct.func) {
455
                            /* Prepare & restore library for user callback */
456
0
                            H5_BEFORE_USER_CB(FAIL)
457
0
                                {
458
0
                                    except_ret = (conv_ctx->u.conv.cb_struct.func)(
459
0
                                        H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id,
460
0
                                        conv_ctx->u.conv.dst_type_id, s, d,
461
0
                                        conv_ctx->u.conv.cb_struct.user_data);
462
0
                                }
463
0
                            H5_AFTER_USER_CB(FAIL)
464
0
                        }
465
466
0
                        if (except_ret == H5T_CONV_UNHANDLED)
467
0
                            memset(d, 0xff, dst_sh->size);
468
0
                        else if (except_ret == H5T_CONV_ABORT)
469
0
                            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL,
470
0
                                        "can't handle conversion exception");
471
0
                    } /* end if */
472
0
                    else {
473
0
                        assert(priv->src2dst[md] >= 0);
474
0
                        H5MM_memcpy(d,
475
0
                                    (uint8_t *)dst_sh->u.enumer.value +
476
0
                                        ((unsigned)priv->src2dst[md] * dst_sh->size),
477
0
                                    dst_sh->size);
478
0
                    } /* end else */
479
0
                }
480
0
            }
481
482
0
            break;
483
484
0
        default:
485
            /* Some other command we don't know about yet.*/
486
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command");
487
0
    } /* end switch */
488
489
0
done:
490
0
    FUNC_LEAVE_NOAPI(ret_value)
491
0
} /* end H5T__conv_enum() */
492
493
/*-------------------------------------------------------------------------
494
 * Function:    H5T__conv_enum_numeric
495
 *
496
 * Purpose:     Converts enumerated data to a numeric type (integer or
497
 *              floating-point number). This function is registered into
498
 *              the conversion table twice in H5T_init_interface in H5T.c.
499
 *              Once for enum-integer conversion. Once for enum-float
500
 *              conversion.
501
 *
502
 * Return:      Non-negative on success/Negative on failure
503
 *
504
 *-------------------------------------------------------------------------
505
 */
506
herr_t
507
H5T__conv_enum_numeric(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata,
508
                       const H5T_conv_ctx_t H5_ATTR_UNUSED *conv_ctx, size_t nelmts,
509
                       size_t H5_ATTR_UNUSED buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *_buf,
510
                       void H5_ATTR_UNUSED *bkg)
511
0
{
512
0
    H5T_t      *src_parent;          /*parent type for src           */
513
0
    H5T_path_t *tpath;               /* Conversion information       */
514
0
    herr_t      ret_value = SUCCEED; /* Return value                 */
515
516
0
    FUNC_ENTER_PACKAGE
517
518
0
    switch (cdata->command) {
519
0
        case H5T_CONV_INIT:
520
            /*
521
             * Determine if this conversion function applies to the conversion
522
             * path SRC->DST.  If not, return failure.
523
             */
524
0
            if (NULL == src || NULL == dst)
525
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a datatype");
526
0
            if (H5T_ENUM != src->shared->type)
527
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "source type is not a H5T_ENUM datatype");
528
0
            if (H5T_INTEGER != dst->shared->type && H5T_FLOAT != dst->shared->type)
529
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "destination is not an integer type");
530
531
0
            cdata->need_bkg = H5T_BKG_NO;
532
0
            break;
533
534
0
        case H5T_CONV_FREE:
535
0
            break;
536
537
0
        case H5T_CONV_CONV:
538
0
            if (NULL == src || NULL == dst)
539
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
540
541
0
            src_parent = src->shared->parent;
542
543
0
            if (NULL == (tpath = H5T_path_find(src_parent, dst))) {
544
0
                HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
545
0
                            "unable to convert between src and dest datatype");
546
0
            }
547
0
            else if (!H5T_path_noop(tpath)) {
548
                /* Convert the data */
549
0
                if (H5T_convert(tpath, src_parent, dst, nelmts, buf_stride, bkg_stride, _buf, bkg) < 0)
550
0
                    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype conversion failed");
551
0
            }
552
0
            break;
553
554
0
        default:
555
            /* Some other command we don't know about yet.*/
556
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command");
557
0
    } /* end switch */
558
559
0
done:
560
0
    FUNC_LEAVE_NOAPI(ret_value)
561
0
} /* end H5T__conv_enum_numeric() */