Line | Count | Source (jump to first uncovered line) |
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 variable-length |
15 | | * datatypes in the H5T interface. |
16 | | */ |
17 | | |
18 | | /****************/ |
19 | | /* Module Setup */ |
20 | | /****************/ |
21 | | |
22 | | #include "H5Tmodule.h" /* This source code file is part of the H5T module */ |
23 | | |
24 | | /***********/ |
25 | | /* Headers */ |
26 | | /***********/ |
27 | | #include "H5private.h" /* Generic Functions */ |
28 | | #include "H5CXprivate.h" /* API Contexts */ |
29 | | #include "H5Eprivate.h" /* Error handling */ |
30 | | #include "H5Iprivate.h" /* IDs */ |
31 | | #include "H5MMprivate.h" /* Memory management */ |
32 | | #include "H5Tpkg.h" /* Datatypes */ |
33 | | #include "H5VLprivate.h" /* Virtual Object Layer */ |
34 | | |
35 | | /****************/ |
36 | | /* Local Macros */ |
37 | | /****************/ |
38 | | |
39 | | /******************/ |
40 | | /* Local Typedefs */ |
41 | | /******************/ |
42 | | |
43 | | /********************/ |
44 | | /* Package Typedefs */ |
45 | | /********************/ |
46 | | |
47 | | /********************/ |
48 | | /* Local Prototypes */ |
49 | | /********************/ |
50 | | |
51 | | /* Memory-based VL sequence callbacks */ |
52 | | static herr_t H5T__vlen_mem_seq_getlen(H5VL_object_t *file, const void *_vl, size_t *len); |
53 | | static void *H5T__vlen_mem_seq_getptr(void *_vl); |
54 | | static herr_t H5T__vlen_mem_seq_isnull(const H5VL_object_t *file, void *_vl, bool *isnull); |
55 | | static herr_t H5T__vlen_mem_seq_setnull(H5VL_object_t *file, void *_vl, void *_bg); |
56 | | static herr_t H5T__vlen_mem_seq_read(H5VL_object_t *file, void *_vl, void *_buf, size_t len); |
57 | | static herr_t H5T__vlen_mem_seq_write(H5VL_object_t *file, const H5T_vlen_alloc_info_t *vl_alloc_info, |
58 | | void *_vl, void *_buf, void *_bg, size_t seq_len, size_t base_size); |
59 | | |
60 | | /* Memory-based VL string callbacks */ |
61 | | static herr_t H5T__vlen_mem_str_getlen(H5VL_object_t *file, const void *_vl, size_t *len); |
62 | | static void *H5T__vlen_mem_str_getptr(void *_vl); |
63 | | static herr_t H5T__vlen_mem_str_isnull(const H5VL_object_t *file, void *_vl, bool *isnull); |
64 | | static herr_t H5T__vlen_mem_str_setnull(H5VL_object_t *file, void *_vl, void *_bg); |
65 | | static herr_t H5T__vlen_mem_str_read(H5VL_object_t *file, void *_vl, void *_buf, size_t len); |
66 | | static herr_t H5T__vlen_mem_str_write(H5VL_object_t *file, const H5T_vlen_alloc_info_t *vl_alloc_info, |
67 | | void *_vl, void *_buf, void *_bg, size_t seq_len, size_t base_size); |
68 | | |
69 | | /* Disk-based VL sequence (and string) callbacks */ |
70 | | static herr_t H5T__vlen_disk_getlen(H5VL_object_t *file, const void *_vl, size_t *len); |
71 | | static herr_t H5T__vlen_disk_isnull(const H5VL_object_t *file, void *_vl, bool *isnull); |
72 | | static herr_t H5T__vlen_disk_setnull(H5VL_object_t *file, void *_vl, void *_bg); |
73 | | static herr_t H5T__vlen_disk_read(H5VL_object_t *file, void *_vl, void *_buf, size_t len); |
74 | | static herr_t H5T__vlen_disk_write(H5VL_object_t *file, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, |
75 | | void *_buf, void *_bg, size_t seq_len, size_t base_size); |
76 | | static herr_t H5T__vlen_disk_delete(H5VL_object_t *file, void *_vl); |
77 | | |
78 | | /*********************/ |
79 | | /* Public Variables */ |
80 | | /*********************/ |
81 | | |
82 | | /*********************/ |
83 | | /* Package Variables */ |
84 | | /*********************/ |
85 | | |
86 | | /*****************************/ |
87 | | /* Library Private Variables */ |
88 | | /*****************************/ |
89 | | |
90 | | /*******************/ |
91 | | /* Local Variables */ |
92 | | /*******************/ |
93 | | |
94 | | /* Class for VL sequences in memory */ |
95 | | static const H5T_vlen_class_t H5T_vlen_mem_seq_g = { |
96 | | H5T__vlen_mem_seq_getlen, /* 'getlen' */ |
97 | | H5T__vlen_mem_seq_getptr, /* 'getptr' */ |
98 | | H5T__vlen_mem_seq_isnull, /* 'isnull' */ |
99 | | H5T__vlen_mem_seq_setnull, /* 'setnull' */ |
100 | | H5T__vlen_mem_seq_read, /* 'read' */ |
101 | | H5T__vlen_mem_seq_write, /* 'write' */ |
102 | | NULL /* 'delete' */ |
103 | | }; |
104 | | |
105 | | /* Class for VL strings in memory */ |
106 | | static const H5T_vlen_class_t H5T_vlen_mem_str_g = { |
107 | | H5T__vlen_mem_str_getlen, /* 'getlen' */ |
108 | | H5T__vlen_mem_str_getptr, /* 'getptr' */ |
109 | | H5T__vlen_mem_str_isnull, /* 'isnull' */ |
110 | | H5T__vlen_mem_str_setnull, /* 'setnull' */ |
111 | | H5T__vlen_mem_str_read, /* 'read' */ |
112 | | H5T__vlen_mem_str_write, /* 'write' */ |
113 | | NULL /* 'delete' */ |
114 | | }; |
115 | | |
116 | | /* Class for both VL strings and sequences in file */ |
117 | | static const H5T_vlen_class_t H5T_vlen_disk_g = { |
118 | | H5T__vlen_disk_getlen, /* 'getlen' */ |
119 | | NULL, /* 'getptr' */ |
120 | | H5T__vlen_disk_isnull, /* 'isnull' */ |
121 | | H5T__vlen_disk_setnull, /* 'setnull' */ |
122 | | H5T__vlen_disk_read, /* 'read' */ |
123 | | H5T__vlen_disk_write, /* 'write' */ |
124 | | H5T__vlen_disk_delete /* 'delete' */ |
125 | | }; |
126 | | |
127 | | /*------------------------------------------------------------------------- |
128 | | * Function: H5Tvlen_create |
129 | | * |
130 | | * Purpose: Create a new variable-length datatype based on the |
131 | | * specified base datatype ID. |
132 | | * |
133 | | * Return: Success: ID of new VL datatype |
134 | | * Failure: H5I_INVALID_HID |
135 | | * |
136 | | *------------------------------------------------------------------------- |
137 | | */ |
138 | | hid_t |
139 | | H5Tvlen_create(hid_t base_id) |
140 | 0 | { |
141 | 0 | H5T_t *base = NULL; /*base datatype */ |
142 | 0 | H5T_t *dt = NULL; /*new datatype */ |
143 | 0 | hid_t ret_value; /*return value */ |
144 | |
|
145 | 0 | FUNC_ENTER_API(H5I_INVALID_HID) |
146 | | |
147 | | /* Check args */ |
148 | 0 | if (NULL == (base = (H5T_t *)H5I_object_verify(base_id, H5I_DATATYPE))) |
149 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not an valid base datatype"); |
150 | | |
151 | | /* Create up VL datatype */ |
152 | 0 | if ((dt = H5T__vlen_create(base)) == NULL) |
153 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, "invalid VL location"); |
154 | | |
155 | | /* Register the type */ |
156 | 0 | if ((ret_value = H5I_register(H5I_DATATYPE, dt, true)) < 0) |
157 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register datatype"); |
158 | | |
159 | 0 | done: |
160 | 0 | FUNC_LEAVE_API(ret_value) |
161 | 0 | } /* end H5Tvlen_create() */ |
162 | | |
163 | | /*------------------------------------------------------------------------- |
164 | | * Function: H5T__vlen_create |
165 | | * |
166 | | * Purpose: Create a new variable-length datatype based on the |
167 | | * specified base datatype. |
168 | | * |
169 | | * Return: Success: new VL datatype |
170 | | * Failure: NULL |
171 | | * |
172 | | *------------------------------------------------------------------------- |
173 | | */ |
174 | | H5T_t * |
175 | | H5T__vlen_create(const H5T_t *base) |
176 | 1 | { |
177 | 1 | H5T_t *dt = NULL; /* New VL datatype */ |
178 | 1 | H5T_t *ret_value = NULL; /* Return value */ |
179 | | |
180 | 1 | FUNC_ENTER_PACKAGE |
181 | | |
182 | | /* Check args */ |
183 | 1 | assert(base); |
184 | | |
185 | | /* Build new type */ |
186 | 1 | if (NULL == (dt = H5T__alloc())) |
187 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, NULL, "memory allocation failed"); |
188 | 1 | dt->shared->type = H5T_VLEN; |
189 | | |
190 | | /* |
191 | | * Force conversions (i.e. memory to memory conversions should duplicate |
192 | | * data, not point to the same VL sequences) |
193 | | */ |
194 | 1 | dt->shared->force_conv = true; |
195 | 1 | if (NULL == (dt->shared->parent = H5T_copy(base, H5T_COPY_ALL))) |
196 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy base datatype"); |
197 | | |
198 | | /* Inherit encoding version from base type */ |
199 | 1 | dt->shared->version = base->shared->version; |
200 | | |
201 | | /* This is a sequence, not a string */ |
202 | 1 | dt->shared->u.vlen.type = H5T_VLEN_SEQUENCE; |
203 | | |
204 | | /* Set up VL information */ |
205 | 1 | if (H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0) |
206 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location"); |
207 | | |
208 | | /* Set return value */ |
209 | 1 | ret_value = dt; |
210 | | |
211 | 1 | done: |
212 | 1 | if (!ret_value) |
213 | 0 | if (dt && H5T_close_real(dt) < 0) |
214 | 0 | HDONE_ERROR(H5E_DATATYPE, H5E_CANTRELEASE, NULL, "unable to release datatype info"); |
215 | | |
216 | 1 | FUNC_LEAVE_NOAPI(ret_value) |
217 | 1 | } /* end H5T__vlen_create() */ |
218 | | |
219 | | /*------------------------------------------------------------------------- |
220 | | * Function: H5T__vlen_set_loc |
221 | | * |
222 | | * Purpose: Sets the location of a VL datatype to be either on disk or in memory |
223 | | * |
224 | | * Return: |
225 | | * One of two values on success: |
226 | | * true - If the location of any vlen types changed |
227 | | * false - If the location of any vlen types is the same |
228 | | * <0 is returned on failure |
229 | | * |
230 | | *------------------------------------------------------------------------- |
231 | | */ |
232 | | htri_t |
233 | | H5T__vlen_set_loc(H5T_t *dt, H5VL_object_t *file, H5T_loc_t loc) |
234 | 1 | { |
235 | 1 | htri_t ret_value = false; /* Indicate success, but no location change */ |
236 | | |
237 | 1 | FUNC_ENTER_PACKAGE |
238 | | |
239 | | /* check parameters */ |
240 | 1 | assert(dt); |
241 | 1 | assert(loc >= H5T_LOC_BADLOC && loc < H5T_LOC_MAXLOC); |
242 | | |
243 | | /* Only change the location if it's different */ |
244 | 1 | if (loc != dt->shared->u.vlen.loc || file != dt->shared->u.vlen.file) { |
245 | 1 | switch (loc) { |
246 | 1 | case H5T_LOC_MEMORY: /* Memory based VL datatype */ |
247 | 1 | assert(NULL == file); |
248 | | |
249 | | /* Mark this type as being stored in memory */ |
250 | 1 | dt->shared->u.vlen.loc = H5T_LOC_MEMORY; |
251 | | |
252 | 1 | if (dt->shared->u.vlen.type == H5T_VLEN_SEQUENCE) { |
253 | | /* Size in memory, disk size is different */ |
254 | 1 | dt->shared->size = sizeof(hvl_t); |
255 | | |
256 | | /* Set up the function pointers to access the VL sequence in memory */ |
257 | 1 | dt->shared->u.vlen.cls = &H5T_vlen_mem_seq_g; |
258 | 1 | } /* end if */ |
259 | 0 | else if (dt->shared->u.vlen.type == H5T_VLEN_STRING) { |
260 | | /* Size in memory, disk size is different */ |
261 | 0 | dt->shared->size = sizeof(char *); |
262 | | |
263 | | /* Set up the function pointers to access the VL string in memory */ |
264 | 0 | dt->shared->u.vlen.cls = &H5T_vlen_mem_str_g; |
265 | 0 | } /* end else-if */ |
266 | 0 | else |
267 | 0 | assert(0 && "Invalid VL type"); |
268 | | |
269 | | /* Release owned file */ |
270 | 1 | if (dt->shared->owned_vol_obj) { |
271 | 0 | if (H5VL_free_object(dt->shared->owned_vol_obj) < 0) |
272 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close owned VOL object"); |
273 | 0 | dt->shared->owned_vol_obj = NULL; |
274 | 0 | } /* end if */ |
275 | | |
276 | | /* Reset file pointer (since this VL is in memory) */ |
277 | 1 | dt->shared->u.vlen.file = NULL; |
278 | 1 | break; |
279 | | |
280 | | /* Disk based VL datatype */ |
281 | 0 | case H5T_LOC_DISK: { |
282 | 0 | H5VL_file_cont_info_t cont_info = {H5VL_CONTAINER_INFO_VERSION, 0, 0, 0}; |
283 | 0 | H5VL_file_get_args_t vol_cb_args; /* Arguments to VOL callback */ |
284 | |
|
285 | 0 | assert(file); |
286 | | |
287 | | /* Mark this type as being stored on disk */ |
288 | 0 | dt->shared->u.vlen.loc = H5T_LOC_DISK; |
289 | | |
290 | | /* Set up VOL callback arguments */ |
291 | 0 | vol_cb_args.op_type = H5VL_FILE_GET_CONT_INFO; |
292 | 0 | vol_cb_args.args.get_cont_info.info = &cont_info; |
293 | | |
294 | | /* Get container info */ |
295 | 0 | if (H5VL_file_get(file, &vol_cb_args, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0) |
296 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get container info"); |
297 | | |
298 | | /* The datatype size is equal to 4 bytes for the sequence length |
299 | | * plus the size of a blob id */ |
300 | 0 | dt->shared->size = 4 + cont_info.blob_id_size; |
301 | | |
302 | | /* Set up the function pointers to access the VL information on disk */ |
303 | | /* VL sequences and VL strings are stored identically on disk, so use the same functions */ |
304 | 0 | dt->shared->u.vlen.cls = &H5T_vlen_disk_g; |
305 | | |
306 | | /* Set file ID (since this VL is on disk) */ |
307 | 0 | dt->shared->u.vlen.file = file; |
308 | | |
309 | | /* dt now owns a reference to file */ |
310 | 0 | if (H5T_own_vol_obj(dt, file) < 0) |
311 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "can't give ownership of VOL object"); |
312 | 0 | break; |
313 | 0 | } |
314 | | |
315 | 0 | case H5T_LOC_BADLOC: |
316 | | /* Allow undefined location. In H5Odtype.c, H5O_dtype_decode sets undefined |
317 | | * location for VL type and leaves it for the caller to decide. |
318 | | */ |
319 | 0 | dt->shared->u.vlen.loc = H5T_LOC_BADLOC; |
320 | | |
321 | | /* Reset the function pointers to access the VL information */ |
322 | 0 | dt->shared->u.vlen.cls = NULL; |
323 | | |
324 | | /* Reset file pointer */ |
325 | 0 | dt->shared->u.vlen.file = NULL; |
326 | 0 | break; |
327 | | |
328 | 0 | case H5T_LOC_MAXLOC: |
329 | | /* MAXLOC is invalid */ |
330 | 0 | default: |
331 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_BADRANGE, FAIL, "invalid VL datatype location"); |
332 | 1 | } /* end switch */ |
333 | | |
334 | | /* Indicate that the location changed */ |
335 | 1 | ret_value = true; |
336 | 1 | } /* end if */ |
337 | | |
338 | 1 | done: |
339 | 1 | FUNC_LEAVE_NOAPI(ret_value) |
340 | 1 | } /* end H5T__vlen_set_loc() */ |
341 | | |
342 | | /*------------------------------------------------------------------------- |
343 | | * Function: H5T__vlen_mem_seq_getlen |
344 | | * |
345 | | * Purpose: Retrieves the length of a memory based VL element. |
346 | | * |
347 | | * Return: Non-negative on success/Negative on failure |
348 | | * |
349 | | *------------------------------------------------------------------------- |
350 | | */ |
351 | | static herr_t |
352 | | H5T__vlen_mem_seq_getlen(H5VL_object_t H5_ATTR_UNUSED *file, const void *_vl, size_t *len) |
353 | 0 | { |
354 | 0 | hvl_t vl; /* User's hvl_t information */ |
355 | |
|
356 | 0 | FUNC_ENTER_PACKAGE_NOERR |
357 | |
|
358 | 0 | assert(_vl); |
359 | 0 | assert(len); |
360 | | |
361 | | /* Copy to ensure correct alignment */ |
362 | 0 | H5MM_memcpy(&vl, _vl, sizeof(hvl_t)); |
363 | |
|
364 | 0 | *len = vl.len; |
365 | |
|
366 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
367 | 0 | } /* end H5T__vlen_mem_seq_getlen() */ |
368 | | |
369 | | /*------------------------------------------------------------------------- |
370 | | * Function: H5T__vlen_mem_seq_getptr |
371 | | * |
372 | | * Purpose: Retrieves the pointer for a memory based VL element. |
373 | | * |
374 | | * Return: Non-NULL on success/NULL on failure |
375 | | * |
376 | | *------------------------------------------------------------------------- |
377 | | */ |
378 | | static void * |
379 | | H5T__vlen_mem_seq_getptr(void *_vl) |
380 | 0 | { |
381 | 0 | hvl_t vl; /* User's hvl_t information */ |
382 | |
|
383 | 0 | FUNC_ENTER_PACKAGE_NOERR |
384 | |
|
385 | 0 | assert(_vl); |
386 | | |
387 | | /* Copy to ensure correct alignment */ |
388 | 0 | H5MM_memcpy(&vl, _vl, sizeof(hvl_t)); |
389 | |
|
390 | 0 | FUNC_LEAVE_NOAPI(vl.p) |
391 | 0 | } /* end H5T__vlen_mem_seq_getptr() */ |
392 | | |
393 | | /*------------------------------------------------------------------------- |
394 | | * Function: H5T__vlen_mem_seq_isnull |
395 | | * |
396 | | * Purpose: Checks if a memory sequence is the "null" sequence |
397 | | * |
398 | | * Return: Non-negative on success / Negative on failure |
399 | | * |
400 | | *------------------------------------------------------------------------- |
401 | | */ |
402 | | static herr_t |
403 | | H5T__vlen_mem_seq_isnull(const H5VL_object_t H5_ATTR_UNUSED *file, void *_vl, bool *isnull) |
404 | 0 | { |
405 | 0 | hvl_t vl; /* User's hvl_t information */ |
406 | |
|
407 | 0 | FUNC_ENTER_PACKAGE_NOERR |
408 | |
|
409 | 0 | assert(_vl); |
410 | | |
411 | | /* Copy to ensure correct alignment */ |
412 | 0 | H5MM_memcpy(&vl, _vl, sizeof(hvl_t)); |
413 | |
|
414 | 0 | *isnull = ((vl.len == 0 || vl.p == NULL) ? true : false); |
415 | |
|
416 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
417 | 0 | } /* end H5T__vlen_mem_seq_isnull() */ |
418 | | |
419 | | /*------------------------------------------------------------------------- |
420 | | * Function: H5T__vlen_mem_seq_setnull |
421 | | * |
422 | | * Purpose: Sets a VL info object in memory to the "nil" value |
423 | | * |
424 | | * Return: Non-negative on success/Negative on failure |
425 | | * |
426 | | *------------------------------------------------------------------------- |
427 | | */ |
428 | | static herr_t |
429 | | H5T__vlen_mem_seq_setnull(H5VL_object_t H5_ATTR_UNUSED *file, void *_vl, void H5_ATTR_UNUSED *_bg) |
430 | 0 | { |
431 | 0 | hvl_t vl; /* Temporary hvl_t to use during operation */ |
432 | |
|
433 | 0 | FUNC_ENTER_PACKAGE_NOERR |
434 | | |
435 | | /* check parameters */ |
436 | 0 | assert(_vl); |
437 | | |
438 | | /* Set the "nil" hvl_t */ |
439 | 0 | vl.len = 0; |
440 | 0 | vl.p = NULL; |
441 | | |
442 | | /* Set pointer in user's buffer with memcpy, to avoid alignment issues */ |
443 | 0 | H5MM_memcpy(_vl, &vl, sizeof(hvl_t)); |
444 | |
|
445 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
446 | 0 | } /* end H5T__vlen_mem_seq_setnull() */ |
447 | | |
448 | | /*------------------------------------------------------------------------- |
449 | | * Function: H5T__vlen_mem_seq_read |
450 | | * |
451 | | * Purpose: "Reads" the memory based VL sequence into a buffer |
452 | | * |
453 | | * Return: Non-negative on success/Negative on failure |
454 | | * |
455 | | *------------------------------------------------------------------------- |
456 | | */ |
457 | | static herr_t |
458 | | H5T__vlen_mem_seq_read(H5VL_object_t H5_ATTR_UNUSED *file, void *_vl, void *buf, size_t len) |
459 | 0 | { |
460 | 0 | hvl_t vl; /* User's hvl_t information */ |
461 | |
|
462 | 0 | FUNC_ENTER_PACKAGE_NOERR |
463 | |
|
464 | 0 | assert(buf); |
465 | 0 | assert(_vl); |
466 | | |
467 | | /* Copy to ensure correct alignment */ |
468 | 0 | H5MM_memcpy(&vl, _vl, sizeof(hvl_t)); |
469 | 0 | assert(vl.p); |
470 | |
|
471 | 0 | H5MM_memcpy(buf, vl.p, len); |
472 | |
|
473 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
474 | 0 | } /* end H5T__vlen_mem_seq_read() */ |
475 | | |
476 | | /*------------------------------------------------------------------------- |
477 | | * Function: H5T__vlen_mem_seq_write |
478 | | * |
479 | | * Purpose: "Writes" the memory based VL sequence from a buffer |
480 | | * |
481 | | * Return: Non-negative on success/Negative on failure |
482 | | * |
483 | | *------------------------------------------------------------------------- |
484 | | */ |
485 | | static herr_t |
486 | | H5T__vlen_mem_seq_write(H5VL_object_t H5_ATTR_UNUSED *file, const H5T_vlen_alloc_info_t *vl_alloc_info, |
487 | | void *_vl, void *buf, void H5_ATTR_UNUSED *_bg, size_t seq_len, size_t base_size) |
488 | 0 | { |
489 | 0 | hvl_t vl; /* Temporary hvl_t to use during operation */ |
490 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
491 | |
|
492 | 0 | FUNC_ENTER_PACKAGE |
493 | | |
494 | | /* check parameters */ |
495 | 0 | assert(_vl); |
496 | 0 | assert(buf); |
497 | |
|
498 | 0 | if (seq_len) { |
499 | 0 | size_t len = seq_len * base_size; /* Sequence size */ |
500 | | |
501 | | /* Use the user's memory allocation routine if one is defined */ |
502 | 0 | if (vl_alloc_info->alloc_func != NULL) { |
503 | | /* Prepare & restore library for user callback */ |
504 | 0 | H5_BEFORE_USER_CB(FAIL) |
505 | 0 | { |
506 | 0 | vl.p = (vl_alloc_info->alloc_func)(len, vl_alloc_info->alloc_info); |
507 | 0 | } |
508 | 0 | H5_AFTER_USER_CB(FAIL) |
509 | 0 | if (NULL == vl.p) |
510 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, |
511 | 0 | "application memory allocation routine failed for VL data"); |
512 | 0 | } /* end if */ |
513 | 0 | else /* Default to system malloc */ |
514 | 0 | if (NULL == (vl.p = malloc(len))) |
515 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "memory allocation failed for VL data"); |
516 | | |
517 | | /* Copy the data into the newly allocated buffer */ |
518 | 0 | H5MM_memcpy(vl.p, buf, len); |
519 | 0 | } /* end if */ |
520 | 0 | else |
521 | 0 | vl.p = NULL; |
522 | | |
523 | | /* Set the sequence length */ |
524 | 0 | vl.len = seq_len; |
525 | | |
526 | | /* Set pointer in user's buffer with memcpy, to avoid alignment issues */ |
527 | 0 | H5MM_memcpy(_vl, &vl, sizeof(hvl_t)); |
528 | |
|
529 | 0 | done: |
530 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
531 | 0 | } /* end H5T__vlen_mem_seq_write() */ |
532 | | |
533 | | /*------------------------------------------------------------------------- |
534 | | * Function: H5T__vlen_mem_str_getlen |
535 | | * |
536 | | * Purpose: Retrieves the length of a memory based VL string. |
537 | | * |
538 | | * Return: Non-negative on success/Negative on failure |
539 | | * |
540 | | *------------------------------------------------------------------------- |
541 | | */ |
542 | | static herr_t |
543 | | H5T__vlen_mem_str_getlen(H5VL_object_t H5_ATTR_UNUSED *file, const void *_vl, size_t *len) |
544 | 0 | { |
545 | 0 | const char *s = NULL; /* Pointer to the user's string information */ |
546 | |
|
547 | 0 | FUNC_ENTER_PACKAGE_NOERR |
548 | |
|
549 | 0 | assert(_vl); |
550 | | |
551 | | /* Copy to ensure correct alignment */ |
552 | 0 | H5MM_memcpy(&s, _vl, sizeof(char *)); |
553 | |
|
554 | 0 | *len = strlen(s); |
555 | |
|
556 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
557 | 0 | } /* end H5T__vlen_mem_str_getlen() */ |
558 | | |
559 | | /*------------------------------------------------------------------------- |
560 | | * Function: H5T__vlen_mem_str_getptr |
561 | | * |
562 | | * Purpose: Retrieves the pointer for a memory based VL string. |
563 | | * |
564 | | * Return: Non-NULL on success/NULL on failure |
565 | | * |
566 | | *------------------------------------------------------------------------- |
567 | | */ |
568 | | static void * |
569 | | H5T__vlen_mem_str_getptr(void *_vl) |
570 | 0 | { |
571 | 0 | char *s = NULL; /* Pointer to the user's string information */ |
572 | |
|
573 | 0 | FUNC_ENTER_PACKAGE_NOERR |
574 | |
|
575 | 0 | assert(_vl); |
576 | | |
577 | | /* Copy to ensure correct alignment */ |
578 | 0 | H5MM_memcpy(&s, _vl, sizeof(char *)); |
579 | |
|
580 | 0 | FUNC_LEAVE_NOAPI(s) |
581 | 0 | } /* end H5T__vlen_mem_str_getptr() */ |
582 | | |
583 | | /*------------------------------------------------------------------------- |
584 | | * Function: H5T__vlen_mem_str_isnull |
585 | | * |
586 | | * Purpose: Checks if a memory string is a NULL pointer |
587 | | * |
588 | | * Return: Non-negative on success / Negative on failure |
589 | | * |
590 | | *------------------------------------------------------------------------- |
591 | | */ |
592 | | static herr_t |
593 | | H5T__vlen_mem_str_isnull(const H5VL_object_t H5_ATTR_UNUSED *file, void *_vl, bool *isnull) |
594 | 0 | { |
595 | 0 | char *s = NULL; /* Pointer to the user's string information */ |
596 | |
|
597 | 0 | FUNC_ENTER_PACKAGE_NOERR |
598 | | |
599 | | /* Copy to ensure correct alignment */ |
600 | 0 | H5MM_memcpy(&s, _vl, sizeof(char *)); |
601 | |
|
602 | 0 | *isnull = (s == NULL ? true : false); |
603 | |
|
604 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
605 | 0 | } /* end H5T__vlen_mem_str_isnull() */ |
606 | | |
607 | | /*------------------------------------------------------------------------- |
608 | | * Function: H5T__vlen_mem_str_setnull |
609 | | * |
610 | | * Purpose: Sets a VL info object in memory to the "null" value |
611 | | * |
612 | | * Return: Non-negative on success/Negative on failure |
613 | | * |
614 | | *------------------------------------------------------------------------- |
615 | | */ |
616 | | static herr_t |
617 | | H5T__vlen_mem_str_setnull(H5VL_object_t H5_ATTR_UNUSED *file, void *_vl, void H5_ATTR_UNUSED *_bg) |
618 | 0 | { |
619 | 0 | char *t = NULL; /* Pointer to temporary buffer allocated */ |
620 | |
|
621 | 0 | FUNC_ENTER_PACKAGE_NOERR |
622 | | |
623 | | /* Set pointer in user's buffer with memcpy, to avoid alignment issues */ |
624 | 0 | H5MM_memcpy(_vl, &t, sizeof(char *)); |
625 | |
|
626 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
627 | 0 | } /* end H5T__vlen_mem_str_setnull() */ |
628 | | |
629 | | /*------------------------------------------------------------------------- |
630 | | * Function: H5T__vlen_mem_str_read |
631 | | * |
632 | | * Purpose: "Reads" the memory based VL string into a buffer |
633 | | * |
634 | | * Return: Non-negative on success/Negative on failure |
635 | | * |
636 | | *------------------------------------------------------------------------- |
637 | | */ |
638 | | static herr_t |
639 | | H5T__vlen_mem_str_read(H5VL_object_t H5_ATTR_UNUSED *file, void *_vl, void *buf, size_t len) |
640 | 0 | { |
641 | 0 | char *s; /* Pointer to the user's string information */ |
642 | |
|
643 | 0 | FUNC_ENTER_PACKAGE_NOERR |
644 | |
|
645 | 0 | if (len > 0) { |
646 | 0 | assert(buf); |
647 | 0 | assert(_vl); |
648 | | |
649 | | /* Copy to ensure correct alignment */ |
650 | 0 | H5MM_memcpy(&s, _vl, sizeof(char *)); |
651 | 0 | H5MM_memcpy(buf, s, len); |
652 | 0 | } |
653 | |
|
654 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
655 | 0 | } /* end H5T__vlen_mem_str_read() */ |
656 | | |
657 | | /*------------------------------------------------------------------------- |
658 | | * Function: H5T__vlen_mem_str_write |
659 | | * |
660 | | * Purpose: "Writes" the memory based VL string from a buffer |
661 | | * |
662 | | * Return: Non-negative on success/Negative on failure |
663 | | * |
664 | | *------------------------------------------------------------------------- |
665 | | */ |
666 | | static herr_t |
667 | | H5T__vlen_mem_str_write(H5VL_object_t H5_ATTR_UNUSED *file, const H5T_vlen_alloc_info_t *vl_alloc_info, |
668 | | void *_vl, void *buf, void H5_ATTR_UNUSED *_bg, size_t seq_len, size_t base_size) |
669 | 0 | { |
670 | 0 | char *t; /* Pointer to temporary buffer allocated */ |
671 | 0 | size_t len; /* Maximum length of the string to copy */ |
672 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
673 | |
|
674 | 0 | FUNC_ENTER_PACKAGE |
675 | | |
676 | | /* check parameters */ |
677 | 0 | assert(buf); |
678 | | |
679 | | /* Use the user's memory allocation routine if one is defined */ |
680 | 0 | if (vl_alloc_info->alloc_func != NULL) { |
681 | | /* Prepare & restore library for user callback */ |
682 | 0 | H5_BEFORE_USER_CB(FAIL) |
683 | 0 | { |
684 | 0 | t = (vl_alloc_info->alloc_func)((seq_len + 1) * base_size, vl_alloc_info->alloc_info); |
685 | 0 | } |
686 | 0 | H5_AFTER_USER_CB(FAIL) |
687 | 0 | if (NULL == t) |
688 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, |
689 | 0 | "application memory allocation routine failed for VL data"); |
690 | 0 | } /* end if */ |
691 | 0 | else /* Default to system malloc */ |
692 | 0 | if (NULL == (t = (char *)malloc((seq_len + 1) * base_size))) |
693 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "memory allocation failed for VL data"); |
694 | | |
695 | | /* 'write' the string into the buffer, with memcpy() */ |
696 | 0 | len = (seq_len * base_size); |
697 | 0 | H5MM_memcpy(t, buf, len); |
698 | 0 | t[len] = '\0'; |
699 | | |
700 | | /* Set pointer in user's buffer with memcpy, to avoid alignment issues */ |
701 | 0 | H5MM_memcpy(_vl, &t, sizeof(char *)); |
702 | |
|
703 | 0 | done: |
704 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
705 | 0 | } /* end H5T__vlen_mem_str_write() */ |
706 | | |
707 | | /*------------------------------------------------------------------------- |
708 | | * Function: H5T__vlen_disk_getlen |
709 | | * |
710 | | * Purpose: Retrieves the length of a disk based VL element. |
711 | | * |
712 | | * Return: Non-negative on success/Negative on failure |
713 | | * |
714 | | *------------------------------------------------------------------------- |
715 | | */ |
716 | | static herr_t |
717 | | H5T__vlen_disk_getlen(H5VL_object_t H5_ATTR_UNUSED *file, const void *_vl, size_t *seq_len) |
718 | 0 | { |
719 | 0 | const uint8_t *vl = (const uint8_t *)_vl; /* Pointer to the user's hvl_t information */ |
720 | |
|
721 | 0 | FUNC_ENTER_PACKAGE_NOERR |
722 | | |
723 | | /* Check parameters */ |
724 | 0 | assert(vl); |
725 | 0 | assert(seq_len); |
726 | | |
727 | | /* Get length of sequence (different from blob size) */ |
728 | 0 | UINT32DECODE(vl, *seq_len); |
729 | |
|
730 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
731 | 0 | } /* end H5T__vlen_disk_getlen() */ |
732 | | |
733 | | /*------------------------------------------------------------------------- |
734 | | * Function: H5T__vlen_disk_isnull |
735 | | * |
736 | | * Purpose: Checks if a disk VL info object is the "nil" object |
737 | | * |
738 | | * Return: Non-negative on success / Negative on failure |
739 | | * |
740 | | *------------------------------------------------------------------------- |
741 | | */ |
742 | | static herr_t |
743 | | H5T__vlen_disk_isnull(const H5VL_object_t *file, void *_vl, bool *isnull) |
744 | 0 | { |
745 | 0 | H5VL_blob_specific_args_t vol_cb_args; /* Arguments to VOL callback */ |
746 | 0 | uint8_t *vl = (uint8_t *)_vl; /* Pointer to the user's hvl_t information */ |
747 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
748 | |
|
749 | 0 | FUNC_ENTER_PACKAGE |
750 | | |
751 | | /* Check parameters */ |
752 | 0 | assert(file); |
753 | 0 | assert(vl); |
754 | 0 | assert(isnull); |
755 | | |
756 | | /* Skip the sequence's length */ |
757 | 0 | vl += 4; |
758 | | |
759 | | /* Set up VOL callback arguments */ |
760 | 0 | vol_cb_args.op_type = H5VL_BLOB_ISNULL; |
761 | 0 | vol_cb_args.args.is_null.isnull = isnull; |
762 | | |
763 | | /* Check if blob ID is "nil" */ |
764 | 0 | if (H5VL_blob_specific(file, vl, &vol_cb_args) < 0) |
765 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to check if a blob ID is 'nil'"); |
766 | | |
767 | 0 | done: |
768 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
769 | 0 | } /* end H5T__vlen_disk_isnull() */ |
770 | | |
771 | | /*------------------------------------------------------------------------- |
772 | | * Function: H5T__vlen_disk_setnull |
773 | | * |
774 | | * Purpose: Sets a VL info object on disk to the "nil" value |
775 | | * |
776 | | * Return: Non-negative on success/Negative on failure |
777 | | * |
778 | | *------------------------------------------------------------------------- |
779 | | */ |
780 | | static herr_t |
781 | | H5T__vlen_disk_setnull(H5VL_object_t *file, void *_vl, void *bg) |
782 | 0 | { |
783 | 0 | H5VL_blob_specific_args_t vol_cb_args; /* Arguments to VOL callback */ |
784 | 0 | uint8_t *vl = (uint8_t *)_vl; /* Pointer to the user's hvl_t information */ |
785 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
786 | |
|
787 | 0 | FUNC_ENTER_PACKAGE |
788 | | |
789 | | /* check parameters */ |
790 | 0 | assert(file); |
791 | 0 | assert(vl); |
792 | | |
793 | | /* Free heap object for old data */ |
794 | 0 | if (bg != NULL) |
795 | | /* Delete sequence in destination location */ |
796 | 0 | if (H5T__vlen_disk_delete(file, bg) < 0) |
797 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREMOVE, FAIL, "unable to remove background heap object"); |
798 | | |
799 | | /* Set the length of the sequence */ |
800 | 0 | UINT32ENCODE(vl, 0); |
801 | | |
802 | | /* Set up VOL callback arguments */ |
803 | 0 | vol_cb_args.op_type = H5VL_BLOB_SETNULL; |
804 | | |
805 | | /* Set blob ID to "nil" */ |
806 | 0 | if (H5VL_blob_specific(file, vl, &vol_cb_args) < 0) |
807 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "unable to set a blob ID to 'nil'"); |
808 | | |
809 | 0 | done: |
810 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
811 | 0 | } /* end H5T__vlen_disk_setnull() */ |
812 | | |
813 | | /*------------------------------------------------------------------------- |
814 | | * Function: H5T__vlen_disk_read |
815 | | * |
816 | | * Purpose: Reads the disk based VL element into a buffer |
817 | | * |
818 | | * Return: Non-negative on success/Negative on failure |
819 | | * |
820 | | *------------------------------------------------------------------------- |
821 | | */ |
822 | | static herr_t |
823 | | H5T__vlen_disk_read(H5VL_object_t *file, void *_vl, void *buf, size_t len) |
824 | 0 | { |
825 | 0 | const uint8_t *vl = (const uint8_t *)_vl; /* Pointer to the user's hvl_t information */ |
826 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
827 | |
|
828 | 0 | FUNC_ENTER_PACKAGE |
829 | | |
830 | | /* Check parameters */ |
831 | 0 | assert(file); |
832 | 0 | assert(vl); |
833 | 0 | assert(buf); |
834 | | |
835 | | /* Skip the length of the sequence */ |
836 | 0 | vl += 4; |
837 | | |
838 | | /* Retrieve blob */ |
839 | 0 | if (H5VL_blob_get(file, vl, buf, len, NULL) < 0) |
840 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get blob"); |
841 | | |
842 | 0 | done: |
843 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
844 | 0 | } /* end H5T__vlen_disk_read() */ |
845 | | |
846 | | /*------------------------------------------------------------------------- |
847 | | * Function: H5T__vlen_disk_write |
848 | | * |
849 | | * Purpose: Writes the disk based VL element from a buffer |
850 | | * |
851 | | * Return: Non-negative on success/Negative on failure |
852 | | * |
853 | | *------------------------------------------------------------------------- |
854 | | */ |
855 | | static herr_t |
856 | | H5T__vlen_disk_write(H5VL_object_t *file, const H5T_vlen_alloc_info_t H5_ATTR_UNUSED *vl_alloc_info, |
857 | | void *_vl, void *buf, void *_bg, size_t seq_len, size_t base_size) |
858 | 0 | { |
859 | 0 | uint8_t *vl = (uint8_t *)_vl; /* Pointer to the user's hvl_t information */ |
860 | 0 | uint8_t *bg = (uint8_t *)_bg; /* Pointer to the old data hvl_t */ |
861 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
862 | |
|
863 | 0 | FUNC_ENTER_PACKAGE |
864 | | |
865 | | /* check parameters */ |
866 | 0 | assert(vl); |
867 | 0 | assert(seq_len == 0 || buf); |
868 | 0 | assert(file); |
869 | | |
870 | | /* Free heap object for old data, if non-NULL */ |
871 | 0 | if (bg != NULL) |
872 | 0 | if (H5T__vlen_disk_delete(file, bg) < 0) |
873 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREMOVE, FAIL, "unable to remove background heap object"); |
874 | | |
875 | | /* Set the length of the sequence */ |
876 | 0 | UINT32ENCODE(vl, seq_len); |
877 | | |
878 | | /* Store blob */ |
879 | 0 | if (H5VL_blob_put(file, buf, (seq_len * base_size), vl, NULL) < 0) |
880 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "unable to put blob"); |
881 | | |
882 | 0 | done: |
883 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
884 | 0 | } /* end H5T__vlen_disk_write() */ |
885 | | |
886 | | /*------------------------------------------------------------------------- |
887 | | * Function: H5T__vlen_disk_delete |
888 | | * |
889 | | * Purpose: Deletes a disk-based VL element |
890 | | * |
891 | | * Return: Non-negative on success / Negative on failure |
892 | | * |
893 | | *------------------------------------------------------------------------- |
894 | | */ |
895 | | static herr_t |
896 | | H5T__vlen_disk_delete(H5VL_object_t *file, void *_vl) |
897 | 0 | { |
898 | 0 | uint8_t *vl = (uint8_t *)_vl; /* Pointer to the user's hvl_t information */ |
899 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
900 | |
|
901 | 0 | FUNC_ENTER_PACKAGE |
902 | | |
903 | | /* Check parameters */ |
904 | 0 | assert(file); |
905 | | |
906 | | /* Free heap object for old data */ |
907 | 0 | if (vl != NULL) { |
908 | 0 | size_t seq_len; /* VL sequence's length */ |
909 | | |
910 | | /* Get length of sequence */ |
911 | 0 | UINT32DECODE(vl, seq_len); |
912 | | |
913 | | /* Delete object, if length > 0 */ |
914 | 0 | if (seq_len > 0) { |
915 | 0 | H5VL_blob_specific_args_t vol_cb_args; /* Arguments to VOL callback */ |
916 | | |
917 | | /* Set up VOL callback arguments */ |
918 | 0 | vol_cb_args.op_type = H5VL_BLOB_DELETE; |
919 | |
|
920 | 0 | if (H5VL_blob_specific(file, vl, &vol_cb_args) < 0) |
921 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREMOVE, FAIL, "unable to delete blob"); |
922 | 0 | } /* end if */ |
923 | 0 | } /* end if */ |
924 | | |
925 | 0 | done: |
926 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
927 | 0 | } /* end H5T__vlen_disk_delete() */ |
928 | | |
929 | | /*------------------------------------------------------------------------- |
930 | | * Function: H5T__vlen_reclaim |
931 | | * |
932 | | * Purpose: Internal recursive routine to free VL datatypes |
933 | | * |
934 | | * Return: Non-negative on success / Negative on failure |
935 | | * |
936 | | *------------------------------------------------------------------------- |
937 | | */ |
938 | | herr_t |
939 | | H5T__vlen_reclaim(void *elem, const H5T_t *dt, H5T_vlen_alloc_info_t *alloc_info) |
940 | 0 | { |
941 | 0 | unsigned u; /* Local index variable */ |
942 | 0 | H5MM_free_t free_func; /* Free function */ |
943 | 0 | void *free_info; /* Free info */ |
944 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
945 | |
|
946 | 0 | FUNC_ENTER_PACKAGE |
947 | | |
948 | | /* Sanity checks */ |
949 | 0 | assert(elem); |
950 | 0 | assert(dt); |
951 | 0 | assert(alloc_info); |
952 | |
|
953 | 0 | free_func = alloc_info->free_func; |
954 | 0 | free_info = alloc_info->free_info; |
955 | | |
956 | | /* Check the datatype of this element */ |
957 | 0 | switch (dt->shared->type) { |
958 | 0 | case H5T_ARRAY: |
959 | | /* Recurse on each element, if the array's base type is array, VL, enum or compound */ |
960 | 0 | if (H5T_IS_COMPOSITE(dt->shared->parent->shared->type)) { |
961 | 0 | void *off; /* offset of field */ |
962 | | |
963 | | /* Calculate the offset member and recurse on it */ |
964 | 0 | for (u = 0; u < dt->shared->u.array.nelem; u++) { |
965 | 0 | off = ((uint8_t *)elem) + u * (dt->shared->parent->shared->size); |
966 | 0 | if (H5T_reclaim_cb(off, dt->shared->parent, 0, NULL, alloc_info) < 0) |
967 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free array element"); |
968 | 0 | } /* end for */ |
969 | 0 | } /* end if */ |
970 | 0 | break; |
971 | | |
972 | 0 | case H5T_COMPOUND: |
973 | | /* Check each field and recurse on VL, compound, enum or array ones */ |
974 | 0 | for (u = 0; u < dt->shared->u.compnd.nmembs; u++) { |
975 | | /* Recurse if it's VL, compound, enum or array */ |
976 | 0 | if (H5T_IS_COMPOSITE(dt->shared->u.compnd.memb[u].type->shared->type)) { |
977 | 0 | void *off; /* offset of field */ |
978 | | |
979 | | /* Calculate the offset member and recurse on it */ |
980 | 0 | off = ((uint8_t *)elem) + dt->shared->u.compnd.memb[u].offset; |
981 | 0 | if (H5T_reclaim_cb(off, dt->shared->u.compnd.memb[u].type, 0, NULL, alloc_info) < 0) |
982 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free compound field"); |
983 | 0 | } /* end if */ |
984 | 0 | } /* end for */ |
985 | 0 | break; |
986 | | |
987 | 0 | case H5T_VLEN: |
988 | | /* Recurse on the VL information if it's VL, compound, enum or array, then free VL sequence */ |
989 | 0 | if (dt->shared->u.vlen.type == H5T_VLEN_SEQUENCE) { |
990 | 0 | hvl_t *vl = (hvl_t *)elem; /* Temp. ptr to the vl info */ |
991 | | |
992 | | /* Check if there is anything actually in this sequence */ |
993 | 0 | if (vl->len != 0) { |
994 | | /* Recurse if it's VL, array, enum or compound */ |
995 | 0 | if (H5T_IS_COMPOSITE(dt->shared->parent->shared->type)) { |
996 | 0 | void *off; /* offset of field */ |
997 | | |
998 | | /* Calculate the offset of each array element and recurse on it */ |
999 | 0 | while (vl->len > 0) { |
1000 | 0 | off = ((uint8_t *)vl->p) + (vl->len - 1) * dt->shared->parent->shared->size; |
1001 | 0 | if (H5T_reclaim_cb(off, dt->shared->parent, 0, NULL, alloc_info) < 0) |
1002 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "unable to free VL element"); |
1003 | 0 | vl->len--; |
1004 | 0 | } /* end while */ |
1005 | 0 | } /* end if */ |
1006 | | |
1007 | | /* Free the VL sequence */ |
1008 | 0 | if (free_func != NULL) |
1009 | 0 | (*free_func)(vl->p, free_info); |
1010 | 0 | else |
1011 | 0 | free(vl->p); |
1012 | 0 | } /* end if */ |
1013 | 0 | } |
1014 | 0 | else if (dt->shared->u.vlen.type == H5T_VLEN_STRING) { |
1015 | | /* Free the VL string */ |
1016 | 0 | if (free_func != NULL) |
1017 | 0 | (*free_func)(*(char **)elem, free_info); |
1018 | 0 | else |
1019 | 0 | free(*(char **)elem); |
1020 | 0 | } |
1021 | 0 | else { |
1022 | 0 | assert(0 && "Invalid VL type"); |
1023 | 0 | } /* end else */ |
1024 | 0 | break; |
1025 | | |
1026 | | /* Don't do anything for simple types */ |
1027 | 0 | case H5T_INTEGER: |
1028 | 0 | case H5T_FLOAT: |
1029 | 0 | case H5T_TIME: |
1030 | 0 | case H5T_STRING: |
1031 | 0 | case H5T_BITFIELD: |
1032 | 0 | case H5T_OPAQUE: |
1033 | 0 | case H5T_ENUM: |
1034 | 0 | case H5T_COMPLEX: |
1035 | 0 | break; |
1036 | | |
1037 | | /* Should never have these values */ |
1038 | 0 | case H5T_REFERENCE: |
1039 | 0 | case H5T_NO_CLASS: |
1040 | 0 | case H5T_NCLASSES: |
1041 | 0 | default: |
1042 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_BADRANGE, FAIL, "invalid VL datatype class"); |
1043 | 0 | break; |
1044 | |
|
1045 | 0 | } /* end switch */ |
1046 | | |
1047 | 0 | done: |
1048 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1049 | 0 | } /* end H5T__vlen_reclaim() */ |
1050 | | |
1051 | | /*------------------------------------------------------------------------- |
1052 | | * Function: H5T_vlen_reclaim_elmt |
1053 | | * |
1054 | | * Purpose: Alternative method to reclaim any VL data for a buffer element. |
1055 | | * |
1056 | | * Use this function when the datatype is already available, but |
1057 | | * the allocation info is needed from the context before jumping |
1058 | | * into recursion. |
1059 | | * |
1060 | | * Return: Non-negative on success/Negative on failure |
1061 | | * |
1062 | | *------------------------------------------------------------------------- |
1063 | | */ |
1064 | | herr_t |
1065 | | H5T_vlen_reclaim_elmt(void *elem, const H5T_t *dt) |
1066 | 0 | { |
1067 | 0 | H5T_vlen_alloc_info_t vl_alloc_info; /* VL allocation info */ |
1068 | 0 | herr_t ret_value = SUCCEED; /* return value */ |
1069 | |
|
1070 | 0 | assert(dt); |
1071 | 0 | assert(elem); |
1072 | |
|
1073 | 0 | FUNC_ENTER_NOAPI(FAIL) |
1074 | | |
1075 | | /* Get VL allocation info */ |
1076 | 0 | if (H5CX_get_vlen_alloc_info(&vl_alloc_info) < 0) |
1077 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to retrieve VL allocation info"); |
1078 | | |
1079 | | /* Recurse on buffer to free dynamic fields */ |
1080 | 0 | if (H5T__vlen_reclaim(elem, dt, &vl_alloc_info) < 0) |
1081 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTFREE, FAIL, "can't reclaim vlen elements"); |
1082 | | |
1083 | 0 | done: |
1084 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1085 | 0 | } /* H5T_vlen_reclaim_elmt() */ |