Coverage Report

Created: 2026-09-14 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Tconv_string.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 string 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_string.h"
29
30
/*-------------------------------------------------------------------------
31
 * Function:    H5T__conv_s_s
32
 *
33
 * Purpose:     Convert one fixed-length string type to another.
34
 *
35
 * Return:      Non-negative on success/Negative on failure
36
 *
37
 *-------------------------------------------------------------------------
38
 */
39
herr_t
40
H5T__conv_s_s(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata,
41
              const H5T_conv_ctx_t H5_ATTR_UNUSED *conv_ctx, size_t nelmts, size_t buf_stride,
42
              size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg)
43
0
{
44
0
    ssize_t  src_delta, dst_delta; /*source & destination stride    */
45
0
    int      direction;            /*direction of traversal    */
46
0
    size_t   elmtno;               /*element number        */
47
0
    size_t   olap;                 /*num overlapping elements    */
48
0
    size_t   nchars = 0;           /*number of characters copied    */
49
0
    uint8_t *s, *sp, *d, *dp;      /*src and dst traversal pointers*/
50
0
    uint8_t *dbuf      = NULL;     /*temp buf for overlap converts.    */
51
0
    herr_t   ret_value = SUCCEED;  /* Return value */
52
53
0
    FUNC_ENTER_PACKAGE
54
55
0
    switch (cdata->command) {
56
0
        case H5T_CONV_INIT:
57
0
            if (NULL == src || NULL == dst)
58
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
59
0
            if (8 * src->shared->size != src->shared->u.atomic.prec ||
60
0
                8 * dst->shared->size != dst->shared->u.atomic.prec)
61
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bad precision");
62
0
            if (0 != src->shared->u.atomic.offset || 0 != dst->shared->u.atomic.offset)
63
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bad offset");
64
0
            if (H5T_CSET_ASCII != src->shared->u.atomic.u.s.cset &&
65
0
                H5T_CSET_UTF8 != src->shared->u.atomic.u.s.cset)
66
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bad source character set");
67
0
            if (H5T_CSET_ASCII != dst->shared->u.atomic.u.s.cset &&
68
0
                H5T_CSET_UTF8 != dst->shared->u.atomic.u.s.cset)
69
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bad destination character set");
70
0
            if ((H5T_CSET_ASCII == src->shared->u.atomic.u.s.cset &&
71
0
                 H5T_CSET_UTF8 == dst->shared->u.atomic.u.s.cset) ||
72
0
                (H5T_CSET_ASCII == dst->shared->u.atomic.u.s.cset &&
73
0
                 H5T_CSET_UTF8 == src->shared->u.atomic.u.s.cset))
74
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
75
0
                            "The library doesn't convert between strings of ASCII and UTF");
76
0
            if (src->shared->u.atomic.u.s.pad < 0 || src->shared->u.atomic.u.s.pad >= H5T_NSTR ||
77
0
                dst->shared->u.atomic.u.s.pad < 0 || dst->shared->u.atomic.u.s.pad >= H5T_NSTR)
78
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bad character padding");
79
0
            cdata->need_bkg = H5T_BKG_NO;
80
0
            break;
81
82
0
        case H5T_CONV_FREE:
83
0
            break;
84
85
0
        case H5T_CONV_CONV:
86
            /* Get the datatypes */
87
0
            if (NULL == src || NULL == dst)
88
0
                HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
89
90
            /*
91
             * Do we process the values from beginning to end or vice versa? Also,
92
             * how many of the elements have the source and destination areas
93
             * overlapping?
94
             */
95
0
            if (src->shared->size == dst->shared->size || buf_stride) {
96
                /*
97
                 * When the source and destination are the same size we can do
98
                 * all the conversions in place.
99
                 */
100
0
                sp = dp   = (uint8_t *)buf;
101
0
                direction = 1;
102
0
                olap      = 0;
103
0
            }
104
0
            else if (src->shared->size >= dst->shared->size) {
105
0
                double olapd =
106
0
                    ceil((double)(dst->shared->size) / (double)(src->shared->size - dst->shared->size));
107
0
                olap = (size_t)olapd;
108
0
                sp = dp   = (uint8_t *)buf;
109
0
                direction = 1;
110
0
            }
111
0
            else {
112
0
                double olapd =
113
0
                    ceil((double)(src->shared->size) / (double)(dst->shared->size - src->shared->size));
114
0
                olap      = (size_t)olapd;
115
0
                sp        = (uint8_t *)buf + (nelmts - 1) * src->shared->size;
116
0
                dp        = (uint8_t *)buf + (nelmts - 1) * dst->shared->size;
117
0
                direction = -1;
118
0
            }
119
120
            /*
121
             * Direction & size of buffer traversal.
122
             */
123
0
            H5_CHECK_OVERFLOW(buf_stride, size_t, ssize_t);
124
0
            H5_CHECK_OVERFLOW(src->shared->size, size_t, ssize_t);
125
0
            H5_CHECK_OVERFLOW(dst->shared->size, size_t, ssize_t);
126
0
            src_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : src->shared->size);
127
0
            dst_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : dst->shared->size);
128
129
            /* Allocate the overlap buffer */
130
0
            if (NULL == (dbuf = (uint8_t *)H5MM_calloc(dst->shared->size)))
131
0
                HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
132
0
                            "memory allocation failed for string conversion");
133
134
            /* The conversion loop. */
135
0
            for (elmtno = 0; elmtno < nelmts; elmtno++) {
136
137
                /*
138
                 * If the source and destination buffers overlap then use a
139
                 * temporary buffer for the destination.
140
                 */
141
0
                if (direction > 0) {
142
0
                    s = sp;
143
0
                    d = elmtno < olap ? dbuf : dp;
144
0
                }
145
0
                else {
146
0
                    s = sp;
147
0
                    d = elmtno + olap >= nelmts ? dbuf : dp;
148
0
                }
149
#ifndef NDEBUG
150
                /* I don't quite trust the overlap calculations yet  */
151
                if (src->shared->size == dst->shared->size || buf_stride) {
152
                    assert(s == d);
153
                }
154
                else if (d == dbuf) {
155
                    assert((dp >= sp && dp < sp + src->shared->size) ||
156
                           (sp >= dp && sp < dp + dst->shared->size));
157
                }
158
                else {
159
                    assert((dp < sp && dp + dst->shared->size <= sp) ||
160
                           (sp < dp && sp + src->shared->size <= dp));
161
                }
162
#endif
163
164
                /* Copy characters from source to destination */
165
0
                switch (src->shared->u.atomic.u.s.pad) {
166
0
                    case H5T_STR_NULLTERM:
167
0
                        for (nchars = 0;
168
0
                             nchars < dst->shared->size && nchars < src->shared->size && s[nchars];
169
0
                             nchars++) {
170
0
                            d[nchars] = s[nchars];
171
0
                        }
172
0
                        break;
173
174
0
                    case H5T_STR_NULLPAD:
175
0
                        for (nchars = 0;
176
0
                             nchars < dst->shared->size && nchars < src->shared->size && s[nchars];
177
0
                             nchars++) {
178
0
                            d[nchars] = s[nchars];
179
0
                        }
180
0
                        break;
181
182
0
                    case H5T_STR_SPACEPAD:
183
0
                        nchars = src->shared->size;
184
0
                        while (nchars > 0 && ' ' == s[nchars - 1])
185
0
                            --nchars;
186
0
                        nchars = MIN(dst->shared->size, nchars);
187
0
                        if (d != s)
188
0
                            H5MM_memcpy(d, s, nchars);
189
0
                        break;
190
191
0
                    case H5T_STR_RESERVED_3:
192
0
                    case H5T_STR_RESERVED_4:
193
0
                    case H5T_STR_RESERVED_5:
194
0
                    case H5T_STR_RESERVED_6:
195
0
                    case H5T_STR_RESERVED_7:
196
0
                    case H5T_STR_RESERVED_8:
197
0
                    case H5T_STR_RESERVED_9:
198
0
                    case H5T_STR_RESERVED_10:
199
0
                    case H5T_STR_RESERVED_11:
200
0
                    case H5T_STR_RESERVED_12:
201
0
                    case H5T_STR_RESERVED_13:
202
0
                    case H5T_STR_RESERVED_14:
203
0
                    case H5T_STR_RESERVED_15:
204
0
                    case H5T_STR_ERROR:
205
0
                    default:
206
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
207
0
                                    "source string padding method not supported");
208
0
                } /* end switch */
209
210
                /* Terminate or pad the destination */
211
0
                switch (dst->shared->u.atomic.u.s.pad) {
212
0
                    case H5T_STR_NULLTERM:
213
0
                        while (nchars < dst->shared->size)
214
0
                            d[nchars++] = '\0';
215
0
                        d[dst->shared->size - 1] = '\0';
216
0
                        break;
217
218
0
                    case H5T_STR_NULLPAD:
219
0
                        while (nchars < dst->shared->size)
220
0
                            d[nchars++] = '\0';
221
0
                        break;
222
223
0
                    case H5T_STR_SPACEPAD:
224
0
                        while (nchars < dst->shared->size)
225
0
                            d[nchars++] = ' ';
226
0
                        break;
227
228
0
                    case H5T_STR_RESERVED_3:
229
0
                    case H5T_STR_RESERVED_4:
230
0
                    case H5T_STR_RESERVED_5:
231
0
                    case H5T_STR_RESERVED_6:
232
0
                    case H5T_STR_RESERVED_7:
233
0
                    case H5T_STR_RESERVED_8:
234
0
                    case H5T_STR_RESERVED_9:
235
0
                    case H5T_STR_RESERVED_10:
236
0
                    case H5T_STR_RESERVED_11:
237
0
                    case H5T_STR_RESERVED_12:
238
0
                    case H5T_STR_RESERVED_13:
239
0
                    case H5T_STR_RESERVED_14:
240
0
                    case H5T_STR_RESERVED_15:
241
0
                    case H5T_STR_ERROR:
242
0
                    default:
243
0
                        HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
244
0
                                    "destination string padding method not supported");
245
0
                } /* end switch */
246
247
                /*
248
                 * If we used a temporary buffer for the destination then we
249
                 * should copy the value to the true destination buffer.
250
                 */
251
0
                if (d == dbuf)
252
0
                    H5MM_memcpy(dp, d, dst->shared->size);
253
254
                /* Advance source & destination pointers by delta amounts */
255
0
                sp += src_delta;
256
0
                dp += dst_delta;
257
0
            } /* end for */
258
0
            break;
259
260
0
        default:
261
0
            HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command");
262
0
    } /* end switch */
263
264
0
done:
265
0
    H5MM_xfree(dbuf);
266
267
0
    FUNC_LEAVE_NOAPI(ret_value)
268
0
} /* end H5T__conv_s_s() */