/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() */ |