1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://www.hdfgroup.org/licenses.               *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 #include "H5LTprivate.h"
15 #include "H5TBprivate.h"
16 
17 /*-------------------------------------------------------------------------
18  *
19  * internal functions
20  *
21  *-------------------------------------------------------------------------
22  */
23 
24 static hbool_t H5TB_find_field(const char *field, const char *field_list);
25 
26 static herr_t H5TB_attach_attributes(const char *table_title, hid_t loc_id, const char *dset_name,
27                                      hsize_t nfields, hid_t tid);
28 
29 static hid_t H5TB_create_type(hid_t loc_id, const char *dset_name, size_t type_size,
30                               const size_t *field_offset, const size_t *field_sizes, hid_t ftype_id);
31 
32 /*-------------------------------------------------------------------------
33  *
34  * Create functions
35  *
36  *-------------------------------------------------------------------------
37  */
38 
39 /*-------------------------------------------------------------------------
40  * Function: H5TBmake_table
41  *
42  * Purpose: Make a table
43  *
44  * Return: Success: 0, Failure: -1
45  *
46  * Programmer: Pedro Vicente
47  *             Quincey Koziol
48  *
49  * Date: January 17, 2001
50  *
51  * Comments:
52  *
53  *-------------------------------------------------------------------------
54  */
55 herr_t
H5TBmake_table(const char * table_title,hid_t loc_id,const char * dset_name,hsize_t nfields,hsize_t nrecords,size_t type_size,const char * field_names[],const size_t * field_offset,const hid_t * field_types,hsize_t chunk_size,void * fill_data,int compress,const void * buf)56 H5TBmake_table(const char *table_title, hid_t loc_id, const char *dset_name, hsize_t nfields,
57                hsize_t nrecords, size_t type_size, const char *field_names[], const size_t *field_offset,
58                const hid_t *field_types, hsize_t chunk_size, void *fill_data, int compress, const void *buf)
59 {
60     hid_t          did         = H5I_INVALID_HID;
61     hid_t          sid         = H5I_INVALID_HID;
62     hid_t          mem_type_id = H5I_INVALID_HID;
63     hid_t          plist_id    = H5I_INVALID_HID;
64     hid_t          attr_id     = H5I_INVALID_HID;
65     hsize_t        dims[1];
66     hsize_t        dims_chunk[1];
67     hsize_t        maxdims[1] = {H5S_UNLIMITED};
68     char           attr_name[255];
69     char *         member_name = NULL;
70     unsigned char *tmp_buf     = NULL;
71     hsize_t        i;
72     herr_t         ret_val = -1;
73 
74     /* check the arguments */
75     if (table_title == NULL) {
76         goto out;
77     }
78     if (dset_name == NULL) {
79         goto out;
80     }
81     if (field_names == NULL) {
82         goto out;
83     }
84 
85     dims[0]       = nrecords;
86     dims_chunk[0] = chunk_size;
87 
88     /* create the memory data type. */
89     if ((mem_type_id = H5Tcreate(H5T_COMPOUND, type_size)) < 0)
90         goto out;
91 
92     /* insert fields. */
93     for (i = 0; i < nfields; i++)
94         if (H5Tinsert(mem_type_id, field_names[i], field_offset[i], field_types[i]) < 0)
95             goto out;
96 
97     /* create a simple data space with unlimited size */
98     if ((sid = H5Screate_simple(1, dims, maxdims)) < 0)
99         goto out;
100 
101     /* modify dataset creation properties, i.e. enable chunking  */
102     if ((plist_id = H5Pcreate(H5P_DATASET_CREATE)) < 0)
103         goto out;
104     if (H5Pset_chunk(plist_id, 1, dims_chunk) < 0)
105         goto out;
106 
107     /* set the fill value using a struct as the data type. */
108     if (fill_data)
109         if (H5Pset_fill_value(plist_id, mem_type_id, fill_data) < 0)
110             goto out;
111 
112     /*
113     dataset creation property list is modified to use
114     GZIP compression with the compression effort set to 6.
115     */
116     if (compress)
117         if (H5Pset_deflate(plist_id, 6) < 0)
118             goto out;
119 
120     /* create the dataset. */
121     if ((did = H5Dcreate2(loc_id, dset_name, mem_type_id, sid, H5P_DEFAULT, plist_id, H5P_DEFAULT)) < 0)
122         goto out;
123 
124     /* only write if there is something to write */
125     if (buf)
126         if (H5Dwrite(did, mem_type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0)
127             goto out;
128 
129     /* terminate access to the data space. */
130     if (H5Sclose(sid) < 0)
131         goto out;
132     sid = H5I_INVALID_HID;
133 
134     /* end access to the dataset */
135     if (H5Dclose(did) < 0)
136         goto out;
137     did = H5I_INVALID_HID;
138 
139     /* end access to the property list */
140     if (H5Pclose(plist_id) < 0)
141         goto out;
142     plist_id = H5I_INVALID_HID;
143 
144     /*-------------------------------------------------------------------------
145      * set the conforming table attributes
146      *-------------------------------------------------------------------------
147      */
148 
149     /* attach the CLASS attribute */
150     if (H5LTset_attribute_string(loc_id, dset_name, "CLASS", TABLE_CLASS) < 0)
151         goto out;
152 
153     /* attach the VERSION attribute */
154     if (H5LTset_attribute_string(loc_id, dset_name, "VERSION", TABLE_VERSION) < 0)
155         goto out;
156 
157     /* attach the TITLE attribute */
158     if (H5LTset_attribute_string(loc_id, dset_name, "TITLE", table_title) < 0)
159         goto out;
160 
161     /* attach the FIELD_ name attribute */
162     for (i = 0; i < nfields; i++) {
163         /* get the member name */
164         if (NULL == (member_name = H5Tget_member_name(mem_type_id, (unsigned)i)))
165             goto out;
166 
167         HDsnprintf(attr_name, sizeof(attr_name), "FIELD_%d_NAME", (int)i);
168 
169         /* attach the attribute */
170         if (H5LTset_attribute_string(loc_id, dset_name, attr_name, member_name) < 0)
171             goto out;
172 
173         H5free_memory(member_name);
174         member_name = NULL;
175     } /* end for */
176 
177     /* attach the FIELD_ fill value attribute */
178     if (fill_data) {
179         tmp_buf = (unsigned char *)fill_data;
180 
181         /* open the dataset. */
182         if ((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
183             goto out;
184 
185         if ((sid = H5Screate(H5S_SCALAR)) < 0)
186             goto out;
187 
188         for (i = 0; i < nfields; i++) {
189             HDsnprintf(attr_name, sizeof(attr_name), "FIELD_%d_FILL", (int)i);
190 
191             if ((attr_id = H5Acreate2(did, attr_name, field_types[i], sid, H5P_DEFAULT, H5P_DEFAULT)) < 0)
192                 goto out;
193 
194             if (H5Awrite(attr_id, field_types[i], tmp_buf + field_offset[i]) < 0)
195                 goto out;
196 
197             if (H5Aclose(attr_id) < 0)
198                 goto out;
199             attr_id = H5I_INVALID_HID;
200         } /* end for */
201 
202         /* terminate access to the data space. */
203         if (H5Sclose(sid) < 0)
204             goto out;
205         sid = H5I_INVALID_HID;
206 
207         /* end access to the dataset */
208         if (H5Dclose(did) < 0)
209             goto out;
210         did = H5I_INVALID_HID;
211     } /* end if */
212 
213     /* release the datatype. */
214     if (H5Tclose(mem_type_id) < 0)
215         goto out;
216     mem_type_id = H5I_INVALID_HID;
217 
218     ret_val = 0;
219 
220 out:
221     if (member_name)
222         H5free_memory(member_name);
223     if (attr_id > 0)
224         if (H5Aclose(attr_id) < 0)
225             ret_val = -1;
226     if (plist_id > 0)
227         if (H5Pclose(plist_id) < 0)
228             ret_val = -1;
229     if (sid > 0)
230         if (H5Sclose(sid) < 0)
231             ret_val = -1;
232     if (did > 0)
233         if (H5Dclose(did) < 0)
234             ret_val = -1;
235     if (mem_type_id > 0)
236         if (H5Tclose(mem_type_id) < 0)
237             ret_val = -1;
238 
239     return ret_val;
240 } /* end H5TBmake_table() */
241 
242 /*-------------------------------------------------------------------------
243  *
244  * Write functions
245  *
246  *-------------------------------------------------------------------------
247  */
248 
249 /*-------------------------------------------------------------------------
250  * Function: H5TBappend_records
251  *
252  * Purpose: Appends records to a table
253  *
254  * Return: Success: 0, Failure: -1
255  *
256  * Programmers:
257  *  Pedro Vicente
258  *  Quincey Koziol
259  *
260  * Date: November 19, 2001
261  *
262  * Comments: Uses memory offsets
263  *
264  *-------------------------------------------------------------------------
265  */
266 herr_t
H5TBappend_records(hid_t loc_id,const char * dset_name,hsize_t nrecords,size_t type_size,const size_t * field_offset,const size_t * field_sizes,const void * buf)267 H5TBappend_records(hid_t loc_id, const char *dset_name, hsize_t nrecords, size_t type_size,
268                    const size_t *field_offset, const size_t *field_sizes, const void *buf)
269 {
270     hid_t   did         = H5I_INVALID_HID;
271     hid_t   tid         = H5I_INVALID_HID;
272     hid_t   mem_type_id = H5I_INVALID_HID;
273     hsize_t nrecords_orig;
274     hsize_t nfields;
275     herr_t  ret_val = -1;
276 
277     /* check the arguments */
278     if (dset_name == NULL)
279         goto out;
280 
281     /* get the original number of records and fields  */
282     if (H5TBget_table_info(loc_id, dset_name, &nfields, &nrecords_orig) < 0)
283         goto out;
284 
285     /* open the dataset. */
286     if ((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
287         goto out;
288 
289     /* get the datatypes */
290     if ((tid = H5Dget_type(did)) < 0)
291         goto out;
292 
293     if ((mem_type_id = H5TB_create_type(loc_id, dset_name, type_size, field_offset, field_sizes, tid)) < 0)
294         goto out;
295 
296     /* append the records */
297     if ((H5TB_common_append_records(did, mem_type_id, (size_t)nrecords, nrecords_orig, buf)) < 0)
298         goto out;
299 
300     ret_val = 0;
301 
302 out:
303     if (tid > 0)
304         if (H5Tclose(tid) < 0)
305             ret_val = -1;
306     if (mem_type_id > 0)
307         if (H5Tclose(mem_type_id) < 0)
308             ret_val = -1;
309     if (did > 0)
310         if (H5Dclose(did) < 0)
311             ret_val = -1;
312 
313     return ret_val;
314 } /* end H5TBappend_records() */
315 
316 /*-------------------------------------------------------------------------
317  * Function: H5TBwrite_records
318  *
319  * Purpose: Writes records
320  *
321  * Return: Success: 0, Failure: -1
322  *
323  * Programmer: Pedro Vicente
324  *
325  * Date: November 19, 2001
326  *
327  * Comments: Uses memory offsets
328  *
329  *-------------------------------------------------------------------------
330  */
331 herr_t
H5TBwrite_records(hid_t loc_id,const char * dset_name,hsize_t start,hsize_t nrecords,size_t type_size,const size_t * field_offset,const size_t * field_sizes,const void * buf)332 H5TBwrite_records(hid_t loc_id, const char *dset_name, hsize_t start, hsize_t nrecords, size_t type_size,
333                   const size_t *field_offset, const size_t *field_sizes, const void *buf)
334 {
335     hid_t   did         = H5I_INVALID_HID;
336     hid_t   tid         = H5I_INVALID_HID;
337     hid_t   sid         = H5I_INVALID_HID;
338     hid_t   m_sid       = H5I_INVALID_HID;
339     hid_t   mem_type_id = H5I_INVALID_HID;
340     hsize_t count[1];
341     hsize_t offset[1];
342     hsize_t mem_size[1];
343     hsize_t dims[1];
344     herr_t  ret_val = -1;
345 
346     /* check the arguments */
347     if (dset_name == NULL)
348         goto out;
349 
350     /* open the dataset. */
351     if ((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
352         goto out;
353 
354     /* get the datatype */
355     if ((tid = H5Dget_type(did)) < 0)
356         goto out;
357 
358     if ((mem_type_id = H5TB_create_type(loc_id, dset_name, type_size, field_offset, field_sizes, tid)) < 0)
359         goto out;
360 
361     /* get the dataspace handle */
362     if ((sid = H5Dget_space(did)) < 0)
363         goto out;
364 
365     /* get records */
366     if (H5Sget_simple_extent_dims(sid, dims, NULL) < 0)
367         goto out;
368 
369     if (start + nrecords > dims[0])
370         goto out;
371 
372     /* define a hyperslab in the dataset of the size of the records */
373     offset[0] = start;
374     count[0]  = nrecords;
375     if (H5Sselect_hyperslab(sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0)
376         goto out;
377 
378     /* create a memory dataspace handle */
379     mem_size[0] = count[0];
380     if ((m_sid = H5Screate_simple(1, mem_size, NULL)) < 0)
381         goto out;
382 
383     if (H5Dwrite(did, mem_type_id, m_sid, sid, H5P_DEFAULT, buf) < 0)
384         goto out;
385 
386     ret_val = 0;
387 
388 out:
389     if (m_sid > 0)
390         if (H5Sclose(m_sid) < 0)
391             ret_val = -1;
392     if (sid > 0)
393         if (H5Sclose(sid) < 0)
394             ret_val = -1;
395     if (tid > 0)
396         if (H5Tclose(tid) < 0)
397             ret_val = -1;
398     if (mem_type_id > 0)
399         if (H5Tclose(mem_type_id) < 0)
400             ret_val = -1;
401     if (did > 0)
402         if (H5Dclose(did) < 0)
403             ret_val = -1;
404 
405     return ret_val;
406 } /* end H5TBwrite_records() */
407 
408 /*-------------------------------------------------------------------------
409  * Function: H5TBwrite_fields_name
410  *
411  * Purpose: Writes fields
412  *
413  * Return: Success: 0, Failure: -1
414  *
415  * Programmer: Pedro Vicente
416  *
417  * Date: November 21, 2001
418  *
419  * Comments:
420  *
421  *-------------------------------------------------------------------------
422  */
423 herr_t
H5TBwrite_fields_name(hid_t loc_id,const char * dset_name,const char * field_names,hsize_t start,hsize_t nrecords,size_t type_size,const size_t * field_offset,const size_t * field_sizes,const void * buf)424 H5TBwrite_fields_name(hid_t loc_id, const char *dset_name, const char *field_names, hsize_t start,
425                       hsize_t nrecords, size_t type_size, const size_t *field_offset,
426                       const size_t *field_sizes, const void *buf)
427 {
428     hid_t    did            = H5I_INVALID_HID;
429     hid_t    tid            = H5I_INVALID_HID;
430     hid_t    write_type_id  = H5I_INVALID_HID;
431     hid_t    member_type_id = H5I_INVALID_HID;
432     hid_t    nmtype_id      = H5I_INVALID_HID;
433     hid_t    m_sid          = H5I_INVALID_HID;
434     hid_t    file_space_id  = H5I_INVALID_HID;
435     hid_t    preserve_id    = H5I_INVALID_HID;
436     hssize_t nfields;
437     hssize_t i, j;
438     hsize_t  count[1];
439     hsize_t  offset[1];
440     char *   member_name = NULL;
441     size_t   size_native;
442     herr_t   ret_val = -1;
443 
444     /* check the arguments */
445     if (dset_name == NULL)
446         goto out;
447     if (field_names == NULL)
448         goto out;
449 
450     /* create xfer properties to preserve initialized data */
451     if ((preserve_id = H5Pcreate(H5P_DATASET_XFER)) < 0)
452         goto out;
453     if (H5Pset_preserve(preserve_id, 1) < 0)
454         goto out;
455 
456     /* open the dataset. */
457     if ((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
458         goto out;
459 
460     /* get the datatype */
461     if ((tid = H5Dget_type(did)) < 0)
462         goto out;
463 
464     /* get the number of fields */
465     if ((nfields = H5Tget_nmembers(tid)) < 0)
466         goto out;
467 
468     /* create a write id */
469     if ((write_type_id = H5Tcreate(H5T_COMPOUND, type_size)) < 0)
470         goto out;
471 
472     j = 0;
473 
474     /* iterate though the members */
475     for (i = 0; i < nfields; i++) {
476         /* get the member name */
477         if (NULL == (member_name = H5Tget_member_name(tid, (unsigned)i)))
478             goto out;
479 
480         if (H5TB_find_field(member_name, field_names)) {
481             /* get the member type */
482             if ((member_type_id = H5Tget_member_type(tid, (unsigned)i)) < 0)
483                 goto out;
484 
485             /* convert to native type */
486             if ((nmtype_id = H5Tget_native_type(member_type_id, H5T_DIR_DEFAULT)) < 0)
487                 goto out;
488 
489             if (0 == (size_native = H5Tget_size(nmtype_id)))
490                 goto out;
491 
492             /* adjust, if necessary */
493             if (field_sizes[j] != size_native)
494                 if (H5Tset_size(nmtype_id, field_sizes[j]) < 0)
495                     goto out;
496 
497             /* the field in the file is found by its name */
498             if (field_offset) {
499                 if (H5Tinsert(write_type_id, member_name, field_offset[j], nmtype_id) < 0)
500                     goto out;
501             } /* end if */
502             /* only one field */
503             else {
504                 if (H5Tinsert(write_type_id, member_name, (size_t)0, nmtype_id) < 0)
505                     goto out;
506             } /* end else */
507 
508             j++;
509 
510             /* close */
511             if (H5Tclose(member_type_id) < 0)
512                 goto out;
513             member_type_id = H5I_INVALID_HID;
514             if (H5Tclose(nmtype_id) < 0)
515                 goto out;
516             nmtype_id = H5I_INVALID_HID;
517         } /* end if */
518 
519         H5free_memory(member_name);
520         member_name = NULL;
521     } /* end for */
522 
523     /* get the dataspace handle */
524     if ((file_space_id = H5Dget_space(did)) < 0)
525         goto out;
526     if ((m_sid = H5Screate_simple(1, &nrecords, NULL)) < 0)
527         goto out;
528 
529     /* define a hyperslab in the dataset */
530     offset[0] = start;
531     count[0]  = nrecords;
532     if (H5Sselect_hyperslab(file_space_id, H5S_SELECT_SET, offset, NULL, count, NULL) < 0)
533         goto out;
534 
535     /* write */
536     if (H5Dwrite(did, write_type_id, m_sid, file_space_id, preserve_id, buf) < 0)
537         goto out;
538 
539     ret_val = 0;
540 
541 out:
542     if (member_name)
543         H5free_memory(member_name);
544     if (preserve_id > 0)
545         if (H5Pclose(preserve_id) < 0)
546             ret_val = -1;
547     if (write_type_id > 0)
548         if (H5Tclose(write_type_id) < 0)
549             ret_val = -1;
550     if (tid > 0)
551         if (H5Tclose(tid) < 0)
552             ret_val = -1;
553     if (file_space_id > 0)
554         if (H5Sclose(file_space_id) < 0)
555             ret_val = -1;
556     if (m_sid > 0)
557         if (H5Sclose(m_sid) < 0)
558             ret_val = -1;
559     if (did > 0)
560         if (H5Dclose(did) < 0)
561             ret_val = -1;
562 
563     return ret_val;
564 } /* end H5TBwrite_fields_name() */
565 
566 /*-------------------------------------------------------------------------
567  * Function: H5TBwrite_fields_index
568  *
569  * Purpose: Writes fields
570  *
571  * Return: Success: 0, Failure: -1
572  *
573  * Programmer: Pedro Vicente
574  *
575  * Date: November 21, 2001
576  *
577  * Comments: Uses memory offsets
578  *
579  *-------------------------------------------------------------------------
580  */
581 herr_t
H5TBwrite_fields_index(hid_t loc_id,const char * dset_name,hsize_t nfields,const int * field_index,hsize_t start,hsize_t nrecords,size_t type_size,const size_t * field_offset,const size_t * field_sizes,const void * buf)582 H5TBwrite_fields_index(hid_t loc_id, const char *dset_name, hsize_t nfields, const int *field_index,
583                        hsize_t start, hsize_t nrecords, size_t type_size, const size_t *field_offset,
584                        const size_t *field_sizes, const void *buf)
585 {
586     hid_t   did            = H5I_INVALID_HID;
587     hid_t   tid            = H5I_INVALID_HID;
588     hid_t   write_type_id  = H5I_INVALID_HID;
589     hid_t   member_type_id = H5I_INVALID_HID;
590     hid_t   nmtype_id      = H5I_INVALID_HID;
591     hid_t   m_sid          = H5I_INVALID_HID;
592     hid_t   file_space_id  = H5I_INVALID_HID;
593     hid_t   preserve_id    = H5I_INVALID_HID;
594     hsize_t count[1];
595     hsize_t offset[1];
596     hsize_t i;
597     size_t  size_native;
598     char *  member_name = NULL;
599     herr_t  ret_val     = -1;
600 
601     /* check the arguments */
602     if (dset_name == NULL)
603         goto out;
604 
605     /* create xfer properties to preserve initialized data */
606     if ((preserve_id = H5Pcreate(H5P_DATASET_XFER)) < 0)
607         goto out;
608     if (H5Pset_preserve(preserve_id, 1) < 0)
609         goto out;
610 
611     /* open the dataset. */
612     if ((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
613         goto out;
614 
615     /* get the datatype */
616     if ((tid = H5Dget_type(did)) < 0)
617         goto out;
618 
619     /* create a write id */
620     if ((write_type_id = H5Tcreate(H5T_COMPOUND, type_size)) < 0)
621         goto out;
622 
623     /* iterate tru the members */
624     for (i = 0; i < nfields; i++) {
625         unsigned j;
626 
627         /* Range check value */
628         if (field_index[i] < 0)
629             goto out;
630 
631         j = (unsigned)field_index[i];
632 
633         /* get the member name */
634         if (NULL == (member_name = H5Tget_member_name(tid, j)))
635             goto out;
636 
637         /* get the member type */
638         if ((member_type_id = H5Tget_member_type(tid, j)) < 0)
639             goto out;
640 
641         /* convert to native type */
642         if ((nmtype_id = H5Tget_native_type(member_type_id, H5T_DIR_DEFAULT)) < 0)
643             goto out;
644 
645         if (0 == (size_native = H5Tget_size(nmtype_id)))
646             goto out;
647 
648         if (field_sizes[i] != size_native)
649             if (H5Tset_size(nmtype_id, field_sizes[i]) < 0)
650                 goto out;
651 
652         /* the field in the file is found by its name */
653         if (field_offset) {
654             if (H5Tinsert(write_type_id, member_name, field_offset[i], nmtype_id) < 0)
655                 goto out;
656         } /* end if */
657         /* only one field */
658         else {
659             if (H5Tinsert(write_type_id, member_name, (size_t)0, nmtype_id) < 0)
660                 goto out;
661         } /* end else */
662 
663         /* close */
664         if (H5Tclose(member_type_id) < 0)
665             goto out;
666         member_type_id = H5I_INVALID_HID;
667         if (H5Tclose(nmtype_id) < 0)
668             goto out;
669         nmtype_id = H5I_INVALID_HID;
670 
671         H5free_memory(member_name);
672         member_name = NULL;
673     } /* end for */
674 
675     /* get the dataspace handles */
676     if ((file_space_id = H5Dget_space(did)) < 0)
677         goto out;
678     if ((m_sid = H5Screate_simple(1, &nrecords, NULL)) < 0)
679         goto out;
680 
681     /* define a hyperslab in the dataset */
682     offset[0] = start;
683     count[0]  = nrecords;
684     if (H5Sselect_hyperslab(file_space_id, H5S_SELECT_SET, offset, NULL, count, NULL) < 0)
685         goto out;
686 
687     /* write */
688     if (H5Dwrite(did, write_type_id, m_sid, file_space_id, preserve_id, buf) < 0)
689         goto out;
690 
691     ret_val = 0;
692 
693 out:
694     if (member_name)
695         H5free_memory(member_name);
696     if (preserve_id > 0)
697         if (H5Pclose(preserve_id) < 0)
698             ret_val = -1;
699     if (write_type_id > 0)
700         if (H5Tclose(write_type_id) < 0)
701             ret_val = -1;
702     if (member_type_id > 0)
703         if (H5Tclose(member_type_id) < 0)
704             ret_val = -1;
705     if (nmtype_id > 0)
706         if (H5Tclose(nmtype_id) < 0)
707             ret_val = -1;
708     if (tid > 0)
709         if (H5Tclose(tid) < 0)
710             ret_val = -1;
711     if (file_space_id > 0)
712         if (H5Sclose(file_space_id) < 0)
713             ret_val = -1;
714     if (m_sid > 0)
715         if (H5Sclose(m_sid) < 0)
716             ret_val = -1;
717     if (did > 0)
718         if (H5Dclose(did) < 0)
719             ret_val = -1;
720 
721     return ret_val;
722 } /* end H5TBwrite_fields_index() */
723 
724 /*-------------------------------------------------------------------------
725  *
726  * Read functions
727  *
728  *-------------------------------------------------------------------------
729  */
730 
731 /*-------------------------------------------------------------------------
732  * Function: H5TBread_table
733  *
734  * Purpose: Reads a table
735  *
736  * Return: Success: 0, Failure: -1
737  *
738  * Programmer: Pedro Vicente
739  *
740  * Date: November 20, 2001
741  *
742  * Comments:
743  *
744  *-------------------------------------------------------------------------
745  */
746 herr_t
H5TBread_table(hid_t loc_id,const char * dset_name,size_t type_size,const size_t * field_offset,const size_t * field_sizes,void * dst_buf)747 H5TBread_table(hid_t loc_id, const char *dset_name, size_t type_size, const size_t *field_offset,
748                const size_t *field_sizes, void *dst_buf)
749 {
750     hid_t   did         = H5I_INVALID_HID;
751     hid_t   ftype_id    = H5I_INVALID_HID;
752     hid_t   mem_type_id = H5I_INVALID_HID;
753     hid_t   sid         = H5I_INVALID_HID;
754     hsize_t dims[1];
755     herr_t  ret_val = -1;
756 
757     /* check the arguments */
758     if (dset_name == NULL)
759         goto out;
760 
761     /* open the dataset. */
762     if ((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
763         goto out;
764 
765     /* get the dataspace handle */
766     if ((sid = H5Dget_space(did)) < 0)
767         goto out;
768 
769     /* get dimensions */
770     if (H5Sget_simple_extent_dims(sid, dims, NULL) < 0)
771         goto out;
772 
773     /* get the datatypes */
774     if ((ftype_id = H5Dget_type(did)) < 0)
775         goto out;
776 
777     if ((mem_type_id = H5TB_create_type(loc_id, dset_name, type_size, field_offset, field_sizes, ftype_id)) <
778         0)
779         goto out;
780 
781     /* read */
782     if (H5Dread(did, mem_type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, dst_buf) < 0)
783         goto out;
784 
785     ret_val = 0;
786 
787 out:
788     if (mem_type_id > 0)
789         if (H5Tclose(mem_type_id) < 0)
790             ret_val = -1;
791     if (ftype_id > 0)
792         if (H5Tclose(ftype_id) < 0)
793             ret_val = -1;
794     if (sid > 0)
795         if (H5Sclose(sid) < 0)
796             ret_val = -1;
797     if (did > 0)
798         if (H5Dclose(did) < 0)
799             ret_val = -1;
800 
801     return ret_val;
802 } /* end H5TBread_table() */
803 
804 /*-------------------------------------------------------------------------
805  * Function: H5TBread_records
806  *
807  * Purpose: Reads records
808  *
809  * Return: Success: 0, Failure: -1
810  *
811  * Programmer: Pedro Vicente
812  *
813  * Date: November 19, 2001
814  *
815  * Comments:
816  *
817  *-------------------------------------------------------------------------
818  */
819 herr_t
H5TBread_records(hid_t loc_id,const char * dset_name,hsize_t start,hsize_t nrecords,size_t type_size,const size_t * field_offset,const size_t * field_sizes,void * buf)820 H5TBread_records(hid_t loc_id, const char *dset_name, hsize_t start, hsize_t nrecords, size_t type_size,
821                  const size_t *field_offset, const size_t *field_sizes, void *buf)
822 {
823     hid_t   did         = H5I_INVALID_HID;
824     hid_t   ftype_id    = H5I_INVALID_HID;
825     hid_t   mem_type_id = H5I_INVALID_HID;
826     hsize_t nrecords_orig;
827     hsize_t nfields;
828     herr_t  ret_val = -1;
829 
830     /* check the arguments */
831     if (dset_name == NULL)
832         goto out;
833 
834     /* get the number of records and fields  */
835     if (H5TBget_table_info(loc_id, dset_name, &nfields, &nrecords_orig) < 0)
836         goto out;
837 
838     /* open the dataset */
839     if ((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
840         goto out;
841 
842     /* get the datatypes */
843     if ((ftype_id = H5Dget_type(did)) < 0)
844         goto out;
845 
846     if ((mem_type_id = H5TB_create_type(loc_id, dset_name, type_size, field_offset, field_sizes, ftype_id)) <
847         0)
848         goto out;
849 
850     /* read the records */
851     if ((H5TB_common_read_records(did, mem_type_id, start, (size_t)nrecords, nrecords_orig, buf)) < 0)
852         goto out;
853 
854     ret_val = 0;
855 
856 out:
857     if (mem_type_id > 0)
858         if (H5Tclose(mem_type_id) < 0)
859             ret_val = -1;
860     if (ftype_id > 0)
861         if (H5Tclose(ftype_id) < 0)
862             ret_val = -1;
863     if (did > 0)
864         if (H5Dclose(did) < 0)
865             ret_val = -1;
866 
867     return ret_val;
868 } /* end H5TBread_records() */
869 
870 /*-------------------------------------------------------------------------
871  * Function: H5TBread_fields_name
872  *
873  * Purpose: Reads fields
874  *
875  * Return: Success: 0, Failure: -1
876  *
877  * Programmer: Pedro Vicente
878  *
879  * Date: November 19, 2001
880  *
881  * Comments:
882  *
883  *-------------------------------------------------------------------------
884  */
885 herr_t
H5TBread_fields_name(hid_t loc_id,const char * dset_name,const char * field_names,hsize_t start,hsize_t nrecords,size_t type_size,const size_t * field_offset,const size_t * field_sizes,void * buf)886 H5TBread_fields_name(hid_t loc_id, const char *dset_name, const char *field_names, hsize_t start,
887                      hsize_t nrecords, size_t type_size, const size_t *field_offset,
888                      const size_t *field_sizes, void *buf)
889 {
890     hid_t    did         = H5I_INVALID_HID;
891     hid_t    ftype_id    = H5I_INVALID_HID;
892     hid_t    mem_type_id = H5I_INVALID_HID;
893     hid_t    mtype_id    = H5I_INVALID_HID;
894     hid_t    nmtype_id   = H5I_INVALID_HID;
895     hid_t    sid         = H5I_INVALID_HID;
896     hid_t    m_sid       = H5I_INVALID_HID;
897     hssize_t nfields;
898     hsize_t  count[1];
899     hsize_t  offset[1];
900     hsize_t  mem_size[1];
901     size_t   size_native;
902     char *   member_name = NULL;
903     hssize_t i, j;
904     herr_t   ret_val = -1;
905 
906     /* check the arguments */
907     if (dset_name == NULL)
908         goto out;
909     if (field_names == NULL)
910         goto out;
911 
912     /* open the dataset */
913     if ((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
914         goto out;
915 
916     /* get the datatype */
917     if ((ftype_id = H5Dget_type(did)) < 0)
918         goto out;
919 
920     /* get the number of fields */
921     if ((nfields = H5Tget_nmembers(ftype_id)) < 0)
922         goto out;
923 
924     /* create a memory read id */
925     if ((mem_type_id = H5Tcreate(H5T_COMPOUND, type_size)) < 0)
926         goto out;
927 
928     /* iterate through the members */
929     for (i = 0, j = 0; i < nfields; i++) {
930         /* get the member name */
931         if (NULL == (member_name = H5Tget_member_name(ftype_id, (unsigned)i)))
932             goto out;
933 
934         if (H5TB_find_field(member_name, field_names)) {
935             /* get the member type */
936             if ((mtype_id = H5Tget_member_type(ftype_id, (unsigned)i)) < 0)
937                 goto out;
938 
939             /* convert to native type */
940             if ((nmtype_id = H5Tget_native_type(mtype_id, H5T_DIR_DEFAULT)) < 0)
941                 goto out;
942 
943             if (0 == (size_native = H5Tget_size(nmtype_id)))
944                 goto out;
945 
946             if (field_sizes[j] != size_native)
947                 if (H5Tset_size(nmtype_id, field_sizes[j]) < 0)
948                     goto out;
949 
950             /* the field in the file is found by its name */
951             if (field_offset) {
952                 if (H5Tinsert(mem_type_id, member_name, field_offset[j], nmtype_id) < 0)
953                     goto out;
954             } /* end if */
955             else {
956                 if (H5Tinsert(mem_type_id, member_name, (size_t)0, nmtype_id) < 0)
957                     goto out;
958             } /* end else */
959 
960             /* close */
961             if (H5Tclose(mtype_id) < 0)
962                 goto out;
963             mtype_id = H5I_INVALID_HID;
964             if (H5Tclose(nmtype_id) < 0)
965                 goto out;
966             nmtype_id = H5I_INVALID_HID;
967             j++;
968         } /* end if */
969 
970         H5free_memory(member_name);
971         member_name = NULL;
972     } /* end for */
973 
974     /* check to make sure field was found, no reason to continue if it does not exist */
975     if (j == 0)
976         goto out;
977 
978     /* get the dataspace handle */
979     if ((sid = H5Dget_space(did)) < 0)
980         goto out;
981 
982     /* define a hyperslab in the dataset */
983     offset[0] = start;
984     count[0]  = nrecords;
985     if (H5Sselect_hyperslab(sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0)
986         goto out;
987 
988     /* create a memory dataspace handle */
989     mem_size[0] = count[0];
990     if ((m_sid = H5Screate_simple(1, mem_size, NULL)) < 0)
991         goto out;
992 
993     /* read */
994     if (H5Dread(did, mem_type_id, m_sid, sid, H5P_DEFAULT, buf) < 0)
995         goto out;
996 
997     ret_val = 0;
998 
999 out:
1000     if (member_name)
1001         H5free_memory(member_name);
1002     if (mtype_id > 0)
1003         if (H5Tclose(mtype_id) < 0)
1004             ret_val = -1;
1005     if (nmtype_id > 0)
1006         if (H5Tclose(nmtype_id) < 0)
1007             ret_val = -1;
1008     if (mem_type_id > 0)
1009         if (H5Tclose(mem_type_id) < 0)
1010             ret_val = -1;
1011     if (ftype_id > 0)
1012         if (H5Tclose(ftype_id) < 0)
1013             ret_val = -1;
1014     if (m_sid > 0)
1015         if (H5Sclose(m_sid) < 0)
1016             ret_val = -1;
1017     if (sid > 0)
1018         if (H5Sclose(sid) < 0)
1019             ret_val = -1;
1020     if (did > 0)
1021         if (H5Dclose(did) < 0)
1022             ret_val = -1;
1023 
1024     return ret_val;
1025 } /* end H5TBread_fields_name() */
1026 
1027 /*-------------------------------------------------------------------------
1028  * Function: H5TBread_fields_index
1029  *
1030  * Purpose: Reads fields
1031  *
1032  * Return: Success: 0, Failure: -1
1033  *
1034  * Programmer: Pedro Vicente
1035  *
1036  * Date: November 19, 2001
1037  *
1038  * Comments:
1039  *
1040  *-------------------------------------------------------------------------
1041  */
1042 herr_t
H5TBread_fields_index(hid_t loc_id,const char * dset_name,hsize_t nfields,const int * field_index,hsize_t start,hsize_t nrecords,size_t type_size,const size_t * field_offset,const size_t * field_sizes,void * buf)1043 H5TBread_fields_index(hid_t loc_id, const char *dset_name, hsize_t nfields, const int *field_index,
1044                       hsize_t start, hsize_t nrecords, size_t type_size, const size_t *field_offset,
1045                       const size_t *field_sizes, void *buf)
1046 {
1047     hid_t   did            = H5I_INVALID_HID;
1048     hid_t   tid            = H5I_INVALID_HID;
1049     hid_t   read_type_id   = H5I_INVALID_HID;
1050     hid_t   member_type_id = H5I_INVALID_HID;
1051     hid_t   nmtype_id      = H5I_INVALID_HID;
1052     hid_t   sid            = H5I_INVALID_HID;
1053     hid_t   m_sid          = H5I_INVALID_HID;
1054     hsize_t count[1];
1055     hsize_t offset[1];
1056     hsize_t mem_size[1];
1057     hsize_t i;
1058     size_t  size_native;
1059     char *  member_name = NULL;
1060     herr_t  ret_val     = -1;
1061 
1062     /* check the arguments */
1063     if (dset_name == NULL)
1064         goto out;
1065 
1066     /* open the dataset. */
1067     if ((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
1068         goto out;
1069 
1070     /* get the datatype */
1071     if ((tid = H5Dget_type(did)) < 0)
1072         goto out;
1073 
1074     /* create a read id */
1075     if ((read_type_id = H5Tcreate(H5T_COMPOUND, type_size)) < 0)
1076         goto out;
1077 
1078     /* iterate tru the members */
1079     for (i = 0; i < nfields; i++) {
1080         unsigned j;
1081 
1082         /* Range check */
1083         if (field_index[i] < 0)
1084             goto out;
1085 
1086         j = (unsigned)field_index[i];
1087 
1088         /* get the member name */
1089         if (NULL == (member_name = H5Tget_member_name(tid, (unsigned)j)))
1090             goto out;
1091 
1092         /* get the member type */
1093         if ((member_type_id = H5Tget_member_type(tid, (unsigned)j)) < 0)
1094             goto out;
1095 
1096         /* convert to native type */
1097         if ((nmtype_id = H5Tget_native_type(member_type_id, H5T_DIR_DEFAULT)) < 0)
1098             goto out;
1099 
1100         if (0 == (size_native = H5Tget_size(nmtype_id)))
1101             goto out;
1102 
1103         if (field_sizes[i] != size_native)
1104             if (H5Tset_size(nmtype_id, field_sizes[i]) < 0)
1105                 goto out;
1106 
1107         /* the field in the file is found by its name */
1108         if (field_offset) {
1109             if (H5Tinsert(read_type_id, member_name, field_offset[i], nmtype_id) < 0)
1110                 goto out;
1111         } /* end if */
1112         else {
1113             if (H5Tinsert(read_type_id, member_name, (size_t)0, nmtype_id) < 0)
1114                 goto out;
1115         } /* end else */
1116 
1117         /* close the member type */
1118         if (H5Tclose(member_type_id) < 0)
1119             goto out;
1120         member_type_id = H5I_INVALID_HID;
1121         if (H5Tclose(nmtype_id) < 0)
1122             goto out;
1123         nmtype_id = H5I_INVALID_HID;
1124 
1125         H5free_memory(member_name);
1126         member_name = NULL;
1127     } /* end for */
1128 
1129     /* get the dataspace handle */
1130     if ((sid = H5Dget_space(did)) < 0)
1131         goto out;
1132 
1133     /* define a hyperslab in the dataset */
1134     offset[0] = start;
1135     count[0]  = nrecords;
1136     if (H5Sselect_hyperslab(sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0)
1137         goto out;
1138 
1139     /* create a memory dataspace handle */
1140     mem_size[0] = count[0];
1141     if ((m_sid = H5Screate_simple(1, mem_size, NULL)) < 0)
1142         goto out;
1143 
1144     /* read */
1145     if (H5Dread(did, read_type_id, m_sid, sid, H5P_DEFAULT, buf) < 0)
1146         goto out;
1147 
1148     ret_val = 0;
1149 
1150 out:
1151     if (member_name)
1152         H5free_memory(member_name);
1153     if (read_type_id > 0)
1154         if (H5Tclose(read_type_id) < 0)
1155             ret_val = -1;
1156     if (member_type_id > 0)
1157         if (H5Tclose(member_type_id) < 0)
1158             ret_val = -1;
1159     if (nmtype_id > 0)
1160         if (H5Tclose(nmtype_id) < 0)
1161             ret_val = -1;
1162     if (tid > 0)
1163         if (H5Tclose(tid) < 0)
1164             ret_val = -1;
1165     if (m_sid > 0)
1166         if (H5Sclose(m_sid) < 0)
1167             ret_val = -1;
1168     if (sid > 0)
1169         if (H5Sclose(sid) < 0)
1170             ret_val = -1;
1171     if (did > 0)
1172         if (H5Dclose(did) < 0)
1173             ret_val = -1;
1174 
1175     return ret_val;
1176 } /* end H5TBread_fields_index() */
1177 
1178 /*-------------------------------------------------------------------------
1179  *
1180  * Manipulation functions
1181  *
1182  *-------------------------------------------------------------------------
1183  */
1184 
1185 /*-------------------------------------------------------------------------
1186  * Function: H5TBdelete_record
1187  *
1188  * Purpose: Delete records from middle of table ("pulling up" all the records after it)
1189  *
1190  * Return: Success: 0, Failure: -1
1191  *
1192  * Programmer: Pedro Vicente
1193  *
1194  * Date: November 26, 2001
1195  *
1196  *-------------------------------------------------------------------------
1197  */
1198 herr_t
H5TBdelete_record(hid_t loc_id,const char * dset_name,hsize_t start,hsize_t nrecords)1199 H5TBdelete_record(hid_t loc_id, const char *dset_name, hsize_t start, hsize_t nrecords)
1200 {
1201     hid_t          did         = H5I_INVALID_HID;
1202     hid_t          tid         = H5I_INVALID_HID;
1203     hid_t          sid         = H5I_INVALID_HID;
1204     hid_t          m_sid       = H5I_INVALID_HID;
1205     hid_t          mem_type_id = H5I_INVALID_HID;
1206     hsize_t        nfields;
1207     hsize_t        ntotal_records;
1208     hsize_t        read_start;
1209     hsize_t        read_nrecords;
1210     hsize_t        count[1];
1211     hsize_t        offset[1];
1212     hsize_t        mem_size[1];
1213     hsize_t        dims[1];
1214     size_t         src_size;
1215     size_t *       src_offset = NULL;
1216     size_t *       src_sizes  = NULL;
1217     unsigned char *tmp_buf    = NULL;
1218     herr_t         ret_val    = -1;
1219 
1220     /* check the arguments */
1221     if (dset_name == NULL)
1222         goto out;
1223 
1224     /*-------------------------------------------------------------------------
1225      * first we get information about type size and offsets on disk
1226      *-------------------------------------------------------------------------
1227      */
1228 
1229     /* get the number of records and fields  */
1230     if (H5TBget_table_info(loc_id, dset_name, &nfields, &ntotal_records) < 0)
1231         goto out;
1232 
1233     if (NULL == (src_offset = (size_t *)HDmalloc((size_t)nfields * sizeof(size_t))))
1234         goto out;
1235     if (NULL == (src_sizes = (size_t *)HDmalloc((size_t)nfields * sizeof(size_t))))
1236         goto out;
1237 
1238     /* get field info */
1239     if (H5TBget_field_info(loc_id, dset_name, NULL, src_sizes, src_offset, &src_size) < 0)
1240         goto out;
1241 
1242     /* open the dataset. */
1243     if ((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
1244         goto out;
1245 
1246     /*-------------------------------------------------------------------------
1247      * read the records after the deleted one(s)
1248      *-------------------------------------------------------------------------
1249      */
1250 
1251     read_start    = start + nrecords;
1252     read_nrecords = ntotal_records - read_start;
1253 
1254     if (read_nrecords) {
1255         if (NULL == (tmp_buf = (unsigned char *)HDcalloc((size_t)read_nrecords, src_size)))
1256             goto out;
1257 
1258         /* read the records after the deleted one(s) */
1259         if (H5TBread_records(loc_id, dset_name, read_start, read_nrecords, src_size, src_offset, src_sizes,
1260                              tmp_buf) < 0)
1261             goto out;
1262 
1263         /*-------------------------------------------------------------------------
1264          * write the records in another position
1265          *-------------------------------------------------------------------------
1266          */
1267 
1268         /* get the datatype */
1269         if ((tid = H5Dget_type(did)) < 0)
1270             goto out;
1271 
1272         /* get the dataspace handle */
1273         if ((sid = H5Dget_space(did)) < 0)
1274             goto out;
1275 
1276         /* create the memory data type. */
1277         if ((mem_type_id = H5TB_create_type(loc_id, dset_name, src_size, src_offset, src_sizes, tid)) < 0)
1278             goto out;
1279 
1280         /* define a hyperslab in the dataset of the size of the records */
1281         offset[0] = start;
1282         count[0]  = read_nrecords;
1283         if (H5Sselect_hyperslab(sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0)
1284             goto out;
1285 
1286         /* create a memory dataspace handle */
1287         mem_size[0] = count[0];
1288         if ((m_sid = H5Screate_simple(1, mem_size, NULL)) < 0)
1289             goto out;
1290 
1291         if (H5Dwrite(did, mem_type_id, m_sid, sid, H5P_DEFAULT, tmp_buf) < 0)
1292             goto out;
1293 
1294         /* close */
1295         if (H5Sclose(m_sid) < 0)
1296             goto out;
1297         m_sid = H5I_INVALID_HID;
1298         if (H5Tclose(mem_type_id) < 0)
1299             goto out;
1300         mem_type_id = H5I_INVALID_HID;
1301         if (H5Sclose(sid) < 0)
1302             goto out;
1303         sid = H5I_INVALID_HID;
1304         if (H5Tclose(tid) < 0)
1305             goto out;
1306         tid = H5I_INVALID_HID;
1307     } /* read_nrecords */
1308 
1309     /*-------------------------------------------------------------------------
1310      * change the dataset dimension
1311      *-------------------------------------------------------------------------
1312      */
1313     dims[0] = ntotal_records - nrecords;
1314     if (H5Dset_extent(did, dims) < 0)
1315         goto out;
1316 
1317     ret_val = 0;
1318 
1319 out:
1320     if (tmp_buf)
1321         HDfree(tmp_buf);
1322     if (src_offset)
1323         HDfree(src_offset);
1324     if (src_sizes)
1325         HDfree(src_sizes);
1326     if (mem_type_id > 0)
1327         if (H5Tclose(mem_type_id) < 0)
1328             ret_val = -1;
1329     if (tid > 0)
1330         if (H5Tclose(tid) < 0)
1331             ret_val = -1;
1332     if (m_sid > 0)
1333         if (H5Sclose(m_sid) < 0)
1334             ret_val = -1;
1335     if (sid > 0)
1336         if (H5Sclose(sid) < 0)
1337             ret_val = -1;
1338     if (did > 0)
1339         if (H5Dclose(did) < 0)
1340             ret_val = -1;
1341 
1342     return ret_val;
1343 } /* end H5TBdelete_record() */
1344 
1345 /*-------------------------------------------------------------------------
1346  * Function: H5TBinsert_record
1347  *
1348  * Purpose: Inserts records into middle of table ("pushing down" all the records after it)
1349  *
1350  * Return: Success: 0, Failure: -1
1351  *
1352  * Programmer: Pedro Vicente
1353  *
1354  * Date: November 26, 2001
1355  *
1356  * Comments: Uses memory offsets
1357  *
1358  *-------------------------------------------------------------------------
1359  */
1360 herr_t
H5TBinsert_record(hid_t loc_id,const char * dset_name,hsize_t start,hsize_t nrecords,size_t type_size,const size_t * field_offset,const size_t * field_sizes,void * buf)1361 H5TBinsert_record(hid_t loc_id, const char *dset_name, hsize_t start, hsize_t nrecords, size_t type_size,
1362                   const size_t *field_offset, const size_t *field_sizes, void *buf)
1363 {
1364     hid_t          did         = H5I_INVALID_HID;
1365     hid_t          tid         = H5I_INVALID_HID;
1366     hid_t          mem_type_id = H5I_INVALID_HID;
1367     hid_t          sid         = H5I_INVALID_HID;
1368     hid_t          m_sid       = H5I_INVALID_HID;
1369     hsize_t        nfields;
1370     hsize_t        ntotal_records;
1371     hsize_t        read_nrecords;
1372     hsize_t        count[1];
1373     hsize_t        offset[1];
1374     hsize_t        dims[1];
1375     hsize_t        mem_dims[1];
1376     unsigned char *tmp_buf = NULL;
1377     herr_t         ret_val = -1;
1378 
1379     /* check the arguments */
1380     if (dset_name == NULL)
1381         goto out;
1382 
1383     /*-------------------------------------------------------------------------
1384      * read the records after the inserted one(s)
1385      *-------------------------------------------------------------------------
1386      */
1387 
1388     /* get the dimensions  */
1389     if (H5TBget_table_info(loc_id, dset_name, &nfields, &ntotal_records) < 0)
1390         goto out;
1391 
1392     /* open the dataset. */
1393     if ((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
1394         goto out;
1395 
1396     /* get the datatype */
1397     if ((tid = H5Dget_type(did)) < 0)
1398         goto out;
1399 
1400     /* create the memory data type. */
1401     if ((mem_type_id = H5TB_create_type(loc_id, dset_name, type_size, field_offset, field_sizes, tid)) < 0)
1402         goto out;
1403 
1404     read_nrecords = ntotal_records - start;
1405     if (NULL == (tmp_buf = (unsigned char *)HDcalloc((size_t)read_nrecords, type_size)))
1406         goto out;
1407 
1408     /* read the records after the inserted one(s) */
1409     if (H5TBread_records(loc_id, dset_name, start, read_nrecords, type_size, field_offset, field_sizes,
1410                          tmp_buf) < 0)
1411         goto out;
1412 
1413     /* extend the dataset */
1414     dims[0] = ntotal_records + nrecords;
1415 
1416     if (H5Dset_extent(did, dims) < 0)
1417         goto out;
1418 
1419     /*-------------------------------------------------------------------------
1420      * write the inserted records
1421      *-------------------------------------------------------------------------
1422      */
1423 
1424     /* create a simple memory data space */
1425     mem_dims[0] = nrecords;
1426     if ((m_sid = H5Screate_simple(1, mem_dims, NULL)) < 0)
1427         goto out;
1428 
1429     /* get the file data space */
1430     if ((sid = H5Dget_space(did)) < 0)
1431         goto out;
1432 
1433     /* define a hyperslab in the dataset to write the new data */
1434     offset[0] = start;
1435     count[0]  = nrecords;
1436     if (H5Sselect_hyperslab(sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0)
1437         goto out;
1438 
1439     if (H5Dwrite(did, mem_type_id, m_sid, sid, H5P_DEFAULT, buf) < 0)
1440         goto out;
1441 
1442     /* terminate access to the dataspace */
1443     if (H5Sclose(m_sid) < 0)
1444         goto out;
1445     m_sid = H5I_INVALID_HID;
1446     if (H5Sclose(sid) < 0)
1447         goto out;
1448     sid = H5I_INVALID_HID;
1449 
1450     /*-------------------------------------------------------------------------
1451      * write the "pushed down" records
1452      *-------------------------------------------------------------------------
1453      */
1454 
1455     /* create a simple memory data space */
1456     mem_dims[0] = read_nrecords;
1457     if ((m_sid = H5Screate_simple(1, mem_dims, NULL)) < 0)
1458         goto out;
1459 
1460     /* get the file data space */
1461     if ((sid = H5Dget_space(did)) < 0)
1462         goto out;
1463 
1464     /* define a hyperslab in the dataset to write the new data */
1465     offset[0] = start + nrecords;
1466     count[0]  = read_nrecords;
1467     if (H5Sselect_hyperslab(sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0)
1468         goto out;
1469 
1470     if (H5Dwrite(did, mem_type_id, m_sid, sid, H5P_DEFAULT, tmp_buf) < 0)
1471         goto out;
1472 
1473     ret_val = 0;
1474 
1475 out:
1476     if (tmp_buf)
1477         HDfree(tmp_buf);
1478     if (sid > 0)
1479         if (H5Sclose(sid) < 0)
1480             ret_val = -1;
1481     if (m_sid > 0)
1482         if (H5Sclose(m_sid) < 0)
1483             ret_val = -1;
1484     if (mem_type_id > 0)
1485         if (H5Tclose(mem_type_id) < 0)
1486             ret_val = -1;
1487     if (tid > 0)
1488         if (H5Tclose(tid) < 0)
1489             ret_val = -1;
1490     if (did > 0)
1491         if (H5Dclose(did) < 0)
1492             ret_val = -1;
1493 
1494     return ret_val;
1495 } /* end H5TBinsert_record() */
1496 
1497 /*-------------------------------------------------------------------------
1498  * Function: H5TBadd_records_from
1499  *
1500  * Purpose: Add records from first table to second table
1501  *
1502  * Return: Success: 0, Failure: -1
1503  *
1504  * Programmer: Pedro Vicente
1505  *
1506  * Date: December 5, 2001
1507  *
1508  * Comments:
1509  *
1510  *-------------------------------------------------------------------------
1511  */
1512 herr_t
H5TBadd_records_from(hid_t loc_id,const char * dset_name1,hsize_t start1,hsize_t nrecords,const char * dset_name2,hsize_t start2)1513 H5TBadd_records_from(hid_t loc_id, const char *dset_name1, hsize_t start1, hsize_t nrecords,
1514                      const char *dset_name2, hsize_t start2)
1515 {
1516     hid_t          did   = H5I_INVALID_HID;
1517     hid_t          tid   = H5I_INVALID_HID;
1518     hid_t          sid   = H5I_INVALID_HID;
1519     hid_t          m_sid = H5I_INVALID_HID;
1520     hsize_t        count[1];
1521     hsize_t        offset[1];
1522     hsize_t        mem_size[1];
1523     hsize_t        nfields;
1524     hsize_t        ntotal_records;
1525     size_t         type_size1;
1526     size_t         src_size;
1527     size_t *       src_offset = NULL;
1528     size_t *       src_sizes  = NULL;
1529     unsigned char *tmp_buf    = NULL;
1530     herr_t         ret_val    = -1;
1531 
1532     /* check the arguments */
1533     if (dset_name1 == NULL)
1534         goto out;
1535     if (dset_name2 == NULL)
1536         goto out;
1537 
1538     /*-------------------------------------------------------------------------
1539      * first we get information about type size and offsets on disk
1540      *-------------------------------------------------------------------------
1541      */
1542 
1543     /* get the number of records and fields  */
1544     if (H5TBget_table_info(loc_id, dset_name1, &nfields, &ntotal_records) < 0)
1545         goto out;
1546 
1547     if (NULL == (src_offset = (size_t *)HDmalloc((size_t)nfields * sizeof(size_t))))
1548         goto out;
1549     if (NULL == (src_sizes = (size_t *)HDmalloc((size_t)nfields * sizeof(size_t))))
1550         goto out;
1551 
1552     /* get field info */
1553     if (H5TBget_field_info(loc_id, dset_name1, NULL, src_sizes, src_offset, &src_size) < 0)
1554         goto out;
1555 
1556     /*-------------------------------------------------------------------------
1557      * Get information about the first table and read it
1558      *-------------------------------------------------------------------------
1559      */
1560 
1561     /* open the 1st dataset. */
1562     if ((did = H5Dopen2(loc_id, dset_name1, H5P_DEFAULT)) < 0)
1563         goto out;
1564 
1565     /* get the datatype */
1566     if ((tid = H5Dget_type(did)) < 0)
1567         goto out;
1568 
1569     /* get the dataspace handle */
1570     if ((sid = H5Dget_space(did)) < 0)
1571         goto out;
1572 
1573     /* get the size of the datatype */
1574     if (0 == (type_size1 = H5Tget_size(tid)))
1575         goto out;
1576 
1577     if (NULL == (tmp_buf = (unsigned char *)HDcalloc((size_t)nrecords, type_size1)))
1578         goto out;
1579 
1580     /* define a hyperslab in the dataset of the size of the records */
1581     offset[0] = start1;
1582     count[0]  = nrecords;
1583     if (H5Sselect_hyperslab(sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0)
1584         goto out;
1585 
1586     /* create a memory dataspace handle */
1587     mem_size[0] = count[0];
1588     if ((m_sid = H5Screate_simple(1, mem_size, NULL)) < 0)
1589         goto out;
1590 
1591     if (H5Dread(did, tid, m_sid, sid, H5P_DEFAULT, tmp_buf) < 0)
1592         goto out;
1593 
1594     /*-------------------------------------------------------------------------
1595      * add to the second table
1596      *-------------------------------------------------------------------------
1597      */
1598     if (H5TBinsert_record(loc_id, dset_name2, start2, nrecords, src_size, src_offset, src_sizes, tmp_buf) < 0)
1599         goto out;
1600 
1601     ret_val = 0;
1602 
1603 out:
1604     if (tmp_buf)
1605         HDfree(tmp_buf);
1606     if (src_offset)
1607         HDfree(src_offset);
1608     if (src_sizes)
1609         HDfree(src_sizes);
1610     if (tid > 0)
1611         if (H5Tclose(tid) < 0)
1612             ret_val = -1;
1613     if (sid > 0)
1614         if (H5Sclose(sid) < 0)
1615             ret_val = -1;
1616     if (m_sid > 0)
1617         if (H5Sclose(m_sid) < 0)
1618             ret_val = -1;
1619     if (did > 0)
1620         if (H5Dclose(did) < 0)
1621             ret_val = -1;
1622 
1623     return ret_val;
1624 } /* end H5TBadd_records_from() */
1625 
1626 /*-------------------------------------------------------------------------
1627  * Function: H5TBcombine_tables
1628  *
1629  * Purpose: Combine records from two tables into a third
1630  *
1631  * Return: Success: 0, Failure: -1
1632  *
1633  * Programmer: Pedro Vicente
1634  *
1635  * Date: December 10, 2001
1636  *
1637  * Comments:
1638  *
1639  *-------------------------------------------------------------------------
1640  */
1641 herr_t
H5TBcombine_tables(hid_t loc_id1,const char * dset_name1,hid_t loc_id2,const char * dset_name2,const char * dset_name3)1642 H5TBcombine_tables(hid_t loc_id1, const char *dset_name1, hid_t loc_id2, const char *dset_name2,
1643                    const char *dset_name3)
1644 {
1645     /* identifiers for the 1st dataset. */
1646     hid_t did_1 = H5I_INVALID_HID;
1647     hid_t tid_1 = H5I_INVALID_HID;
1648     hid_t sid_1 = H5I_INVALID_HID;
1649     hid_t pid_1 = H5I_INVALID_HID;
1650     /* identifiers for the 2nd dataset. */
1651     hid_t did_2 = H5I_INVALID_HID;
1652     hid_t tid_2 = H5I_INVALID_HID;
1653     hid_t sid_2 = H5I_INVALID_HID;
1654     hid_t pid_2 = H5I_INVALID_HID;
1655     /* identifiers for the 3rd dataset. */
1656     hid_t          did_3          = H5I_INVALID_HID;
1657     hid_t          tid_3          = H5I_INVALID_HID;
1658     hid_t          sid_3          = H5I_INVALID_HID;
1659     hid_t          pid_3          = H5I_INVALID_HID;
1660     hid_t          sid            = H5I_INVALID_HID;
1661     hid_t          m_sid          = H5I_INVALID_HID;
1662     hid_t          member_type_id = H5I_INVALID_HID;
1663     hid_t          attr_id        = H5I_INVALID_HID;
1664     hsize_t        count[1];
1665     hsize_t        offset[1];
1666     hsize_t        mem_size[1];
1667     hsize_t        nfields;
1668     hsize_t        nrecords;
1669     hsize_t        dims[1];
1670     hsize_t        maxdims[1] = {H5S_UNLIMITED};
1671     hsize_t        i;
1672     size_t         type_size;
1673     size_t         member_offset;
1674     size_t         src_size;
1675     size_t *       src_offset = NULL;
1676     size_t *       src_sizes  = NULL;
1677     char           attr_name[255];
1678     unsigned char *tmp_buf      = NULL;
1679     unsigned char *tmp_fill_buf = NULL;
1680     htri_t         has_fill;
1681     herr_t         ret_val = -1;
1682 
1683     /* check the arguments */
1684     if (dset_name1 == NULL)
1685         goto out;
1686     if (dset_name2 == NULL)
1687         goto out;
1688     if (dset_name3 == NULL)
1689         goto out;
1690 
1691     /*-------------------------------------------------------------------------
1692      * first we get information about type size and offsets on disk
1693      *-------------------------------------------------------------------------
1694      */
1695 
1696     /* get the number of records and fields  */
1697     if (H5TBget_table_info(loc_id1, dset_name1, &nfields, &nrecords) < 0)
1698         goto out;
1699 
1700     if (NULL == (src_offset = (size_t *)HDmalloc((size_t)nfields * sizeof(size_t))))
1701         goto out;
1702     if (NULL == (src_sizes = (size_t *)HDmalloc((size_t)nfields * sizeof(size_t))))
1703         goto out;
1704 
1705     /* get field info */
1706     if (H5TBget_field_info(loc_id1, dset_name1, NULL, src_sizes, src_offset, &src_size) < 0)
1707         goto out;
1708 
1709     /*-------------------------------------------------------------------------
1710      * get information about the first table
1711      *-------------------------------------------------------------------------
1712      */
1713 
1714     /* open the 1st dataset. */
1715     if ((did_1 = H5Dopen2(loc_id1, dset_name1, H5P_DEFAULT)) < 0)
1716         goto out;
1717 
1718     /* get the datatype */
1719     if ((tid_1 = H5Dget_type(did_1)) < 0)
1720         goto out;
1721 
1722     /* get the dataspace handle */
1723     if ((sid_1 = H5Dget_space(did_1)) < 0)
1724         goto out;
1725 
1726     /* get creation properties list */
1727     if ((pid_1 = H5Dget_create_plist(did_1)) < 0)
1728         goto out;
1729 
1730     /* get the dimensions  */
1731     if (H5TBget_table_info(loc_id1, dset_name1, &nfields, &nrecords) < 0)
1732         goto out;
1733 
1734     /*-------------------------------------------------------------------------
1735      * make the merged table with no data originally
1736      *-------------------------------------------------------------------------
1737      */
1738 
1739     /* clone the property list */
1740     if ((pid_3 = H5Pcopy(pid_1)) < 0)
1741         goto out;
1742 
1743     /* clone the type id */
1744     if ((tid_3 = H5Tcopy(tid_1)) < 0)
1745         goto out;
1746 
1747     /*-------------------------------------------------------------------------
1748      * here we do not clone the file space from the 1st dataset, because we want to create
1749      * an empty table. Instead we create a new dataspace with zero records and expandable.
1750      *-------------------------------------------------------------------------
1751      */
1752     dims[0] = 0;
1753 
1754     /* create a simple data space with unlimited size */
1755     if ((sid_3 = H5Screate_simple(1, dims, maxdims)) < 0)
1756         goto out;
1757 
1758     /* create the dataset */
1759     if ((did_3 = H5Dcreate2(loc_id1, dset_name3, tid_3, sid_3, H5P_DEFAULT, pid_3, H5P_DEFAULT)) < 0)
1760         goto out;
1761 
1762     /*-------------------------------------------------------------------------
1763      * attach the conforming table attributes
1764      *-------------------------------------------------------------------------
1765      */
1766     if (H5TB_attach_attributes("Merge table", loc_id1, dset_name3, nfields, tid_3) < 0)
1767         goto out;
1768 
1769     /*-------------------------------------------------------------------------
1770      * get attributes
1771      *-------------------------------------------------------------------------
1772      */
1773     if (0 == (type_size = H5Tget_size(tid_3)))
1774         goto out;
1775 
1776     /* alloc fill value attribute buffer */
1777     if (NULL == (tmp_fill_buf = (unsigned char *)HDmalloc(type_size)))
1778         goto out;
1779 
1780     /* get the fill value attributes */
1781     if ((has_fill = H5TBAget_fill(loc_id1, dset_name1, did_1, tmp_fill_buf)) < 0)
1782         goto out;
1783 
1784     /*-------------------------------------------------------------------------
1785      * attach the fill attributes from previous table
1786      *-------------------------------------------------------------------------
1787      */
1788     if (has_fill) {
1789         if ((sid = H5Screate(H5S_SCALAR)) < 0)
1790             goto out;
1791 
1792         for (i = 0; i < nfields; i++) {
1793             /* get the member type */
1794             if ((member_type_id = H5Tget_member_type(tid_3, (unsigned)i)) < 0)
1795                 goto out;
1796 
1797             /* get the member offset */
1798             member_offset = H5Tget_member_offset(tid_3, (unsigned)i);
1799 
1800             HDsnprintf(attr_name, sizeof(attr_name), "FIELD_%d_FILL", (int)i);
1801 
1802             if ((attr_id = H5Acreate2(did_3, attr_name, member_type_id, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0)
1803                 goto out;
1804 
1805             if (H5Awrite(attr_id, member_type_id, tmp_fill_buf + member_offset) < 0)
1806                 goto out;
1807 
1808             if (H5Aclose(attr_id) < 0)
1809                 goto out;
1810             attr_id = H5I_INVALID_HID;
1811 
1812             if (H5Tclose(member_type_id) < 0)
1813                 goto out;
1814             member_type_id = H5I_INVALID_HID;
1815         } /* end for */
1816 
1817         /* close data space. */
1818         if (H5Sclose(sid) < 0)
1819             goto out;
1820         sid = H5I_INVALID_HID;
1821     } /* end if */
1822 
1823     /*-------------------------------------------------------------------------
1824      * read data from 1st table
1825      *-------------------------------------------------------------------------
1826      */
1827     if (NULL == (tmp_buf = (unsigned char *)HDcalloc((size_t)nrecords, type_size)))
1828         goto out;
1829 
1830     /* define a hyperslab in the dataset of the size of the records */
1831     offset[0] = 0;
1832     count[0]  = nrecords;
1833     if (H5Sselect_hyperslab(sid_1, H5S_SELECT_SET, offset, NULL, count, NULL) < 0)
1834         goto out;
1835 
1836     /* create a memory dataspace handle */
1837     mem_size[0] = count[0];
1838     if ((m_sid = H5Screate_simple(1, mem_size, NULL)) < 0)
1839         goto out;
1840 
1841     if (H5Dread(did_1, tid_1, m_sid, sid_1, H5P_DEFAULT, tmp_buf) < 0)
1842         goto out;
1843 
1844     /*-------------------------------------------------------------------------
1845      * save data from 1st table into new table
1846      *-------------------------------------------------------------------------
1847      */
1848 
1849     /* append the records to the new table */
1850     if (H5TBappend_records(loc_id1, dset_name3, nrecords, src_size, src_offset, src_sizes, tmp_buf) < 0)
1851         goto out;
1852 
1853     /*-------------------------------------------------------------------------
1854      * release temporary resources
1855      *-------------------------------------------------------------------------
1856      */
1857     if (H5Sclose(m_sid) < 0)
1858         goto out;
1859     m_sid = H5I_INVALID_HID;
1860     HDfree(tmp_buf);
1861     tmp_buf = NULL;
1862 
1863     /*-------------------------------------------------------------------------
1864      * get information about the 2nd table
1865      *-------------------------------------------------------------------------
1866      */
1867 
1868     /* open the dataset. */
1869     if ((did_2 = H5Dopen2(loc_id2, dset_name2, H5P_DEFAULT)) < 0)
1870         goto out;
1871 
1872     /* get the datatype */
1873     if ((tid_2 = H5Dget_type(did_2)) < 0)
1874         goto out;
1875 
1876     /* get the dataspace handle */
1877     if ((sid_2 = H5Dget_space(did_2)) < 0)
1878         goto out;
1879 
1880     /* get the property list handle */
1881     if ((pid_2 = H5Dget_create_plist(did_2)) < 0)
1882         goto out;
1883 
1884     /* get the dimensions  */
1885     if (H5TBget_table_info(loc_id2, dset_name2, &nfields, &nrecords) < 0)
1886         goto out;
1887 
1888     /*-------------------------------------------------------------------------
1889      * read data from 2nd table
1890      *-------------------------------------------------------------------------
1891      */
1892 
1893     if (NULL == (tmp_buf = (unsigned char *)HDcalloc((size_t)nrecords, type_size)))
1894         goto out;
1895 
1896     /* define a hyperslab in the dataset of the size of the records */
1897     offset[0] = 0;
1898     count[0]  = nrecords;
1899     if (H5Sselect_hyperslab(sid_2, H5S_SELECT_SET, offset, NULL, count, NULL) < 0)
1900         goto out;
1901 
1902     /* create a memory dataspace handle */
1903     mem_size[0] = count[0];
1904     if ((m_sid = H5Screate_simple(1, mem_size, NULL)) < 0)
1905         goto out;
1906 
1907     if (H5Dread(did_2, tid_2, m_sid, sid_2, H5P_DEFAULT, tmp_buf) < 0)
1908         goto out;
1909 
1910     /*-------------------------------------------------------------------------
1911      * save data from 2nd table into new table
1912      *-------------------------------------------------------------------------
1913      */
1914 
1915     /* append the records to the new table */
1916     if (H5TBappend_records(loc_id1, dset_name3, nrecords, src_size, src_offset, src_sizes, tmp_buf) < 0)
1917         goto out;
1918 
1919     ret_val = 0;
1920 
1921 out:
1922     if (tmp_buf)
1923         HDfree(tmp_buf);
1924     if (tmp_fill_buf)
1925         HDfree(tmp_fill_buf);
1926     if (src_offset)
1927         HDfree(src_offset);
1928     if (src_sizes)
1929         HDfree(src_sizes);
1930     if (member_type_id > 0)
1931         if (H5Tclose(member_type_id) < 0)
1932             ret_val = -1;
1933     if (attr_id > 0)
1934         if (H5Aclose(attr_id) < 0)
1935             ret_val = -1;
1936     if (sid > 0)
1937         if (H5Sclose(sid) < 0)
1938             ret_val = -1;
1939     if (m_sid > 0)
1940         if (H5Sclose(m_sid) < 0)
1941             ret_val = -1;
1942     if (sid_1 > 0)
1943         if (H5Sclose(sid_1) < 0)
1944             ret_val = -1;
1945     if (tid_1 > 0)
1946         if (H5Tclose(tid_1) < 0)
1947             ret_val = -1;
1948     if (pid_1 > 0)
1949         if (H5Pclose(pid_1) < 0)
1950             ret_val = -1;
1951     if (did_1 > 0)
1952         if (H5Dclose(did_1) < 0)
1953             ret_val = -1;
1954     if (sid_2 > 0)
1955         if (H5Sclose(sid_2) < 0)
1956             ret_val = -1;
1957     if (tid_2 > 0)
1958         if (H5Tclose(tid_2) < 0)
1959             ret_val = -1;
1960     if (pid_2 > 0)
1961         if (H5Pclose(pid_2) < 0)
1962             ret_val = -1;
1963     if (did_2 > 0)
1964         if (H5Dclose(did_2) < 0)
1965             ret_val = -1;
1966     if (sid_3 > 0)
1967         if (H5Sclose(sid_3) < 0)
1968             ret_val = -1;
1969     if (tid_3 > 0)
1970         if (H5Tclose(tid_3) < 0)
1971             ret_val = -1;
1972     if (pid_3 > 0)
1973         if (H5Pclose(pid_3) < 0)
1974             ret_val = -1;
1975     if (did_3 > 0)
1976         if (H5Dclose(did_3) < 0)
1977             ret_val = -1;
1978 
1979     return ret_val;
1980 } /* end H5TBcombine_tables() */
1981 
1982 /*-------------------------------------------------------------------------
1983  * Function: H5TBinsert_field
1984  *
1985  * Purpose: Inserts a field
1986  *
1987  * Return: Success: 0, Failure: -1
1988  *
1989  * Programmer: Pedro Vicente
1990  *
1991  * Date: January 30, 2002
1992  *
1993  * Comments:
1994  *
1995  *-------------------------------------------------------------------------
1996  */
1997 herr_t
H5TBinsert_field(hid_t loc_id,const char * dset_name,const char * field_name,hid_t field_type,hsize_t position,const void * fill_data,const void * buf)1998 H5TBinsert_field(hid_t loc_id, const char *dset_name, const char *field_name, hid_t field_type,
1999                  hsize_t position, const void *fill_data, const void *buf)
2000 {
2001     /* identifiers for the 1st, original dataset */
2002     hid_t did_1  = H5I_INVALID_HID;
2003     hid_t tid_1  = H5I_INVALID_HID;
2004     hid_t sid_1  = H5I_INVALID_HID;
2005     hid_t pid_1  = H5I_INVALID_HID;
2006     hid_t msid_1 = H5I_INVALID_HID;
2007     /* identifiers for the 2nd, new dataset */
2008     hid_t did_2  = H5I_INVALID_HID;
2009     hid_t tid_2  = H5I_INVALID_HID;
2010     hid_t sid_2  = H5I_INVALID_HID;
2011     hid_t pid_2  = H5I_INVALID_HID;
2012     hid_t msid_2 = H5I_INVALID_HID;
2013     /* identifiers for the 3rd, final dataset */
2014     hid_t          did_3          = H5I_INVALID_HID;
2015     hid_t          tid_3          = H5I_INVALID_HID;
2016     hid_t          sid_3          = H5I_INVALID_HID;
2017     hid_t          member_type_id = H5I_INVALID_HID;
2018     hid_t          write_type_id  = H5I_INVALID_HID;
2019     hid_t          preserve_id    = H5I_INVALID_HID;
2020     hid_t          attr_id        = H5I_INVALID_HID;
2021     size_t         member_size;
2022     size_t         new_member_size = 0;
2023     size_t         total_size;
2024     size_t         curr_offset;
2025     hsize_t        nfields;
2026     hsize_t        nrecords;
2027     hsize_t        dims_chunk[1];
2028     hsize_t        dims[1];
2029     hsize_t        maxdims[1] = {H5S_UNLIMITED};
2030     hsize_t        count[1];
2031     hsize_t        offset[1];
2032     hsize_t        mem_size[1];
2033     hsize_t        i;
2034     char           table_title[255];
2035     char           attr_name[255];
2036     char *         member_name  = NULL;
2037     unsigned char *tmp_buf      = NULL;
2038     unsigned char *tmp_fill_buf = NULL;
2039     hbool_t        inserted;
2040     herr_t         ret_val = -1;
2041 
2042     /* check the arguments */
2043     if (dset_name == NULL)
2044         goto out;
2045     if (field_name == NULL)
2046         goto out;
2047 
2048     /* get the number of records and fields  */
2049     if (H5TBget_table_info(loc_id, dset_name, &nfields, &nrecords) < 0)
2050         goto out;
2051 
2052     /*-------------------------------------------------------------------------
2053      * get information about the old data type
2054      *-------------------------------------------------------------------------
2055      */
2056 
2057     /* open the dataset. */
2058     if ((did_1 = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
2059         goto out;
2060 
2061     /* get creation properties list */
2062     if ((pid_1 = H5Dget_create_plist(did_1)) < 0)
2063         goto out;
2064 
2065     /* get the datatype */
2066     if ((tid_1 = H5Dget_type(did_1)) < 0)
2067         goto out;
2068 
2069     /* get the size of the datatype */
2070     if (0 == (total_size = H5Tget_size(tid_1)))
2071         goto out;
2072 
2073     /* get the dataspace handle */
2074     if ((sid_1 = H5Dget_space(did_1)) < 0)
2075         goto out;
2076 
2077     /* get dimension */
2078     if (H5Sget_simple_extent_dims(sid_1, dims, NULL) < 0)
2079         goto out;
2080 
2081     /*-------------------------------------------------------------------------
2082      * get attributes
2083      *-------------------------------------------------------------------------
2084      */
2085 
2086     /* get the table title */
2087     if ((H5TBAget_title(did_1, table_title)) < 0)
2088         goto out;
2089 
2090     /* alloc fill value attribute buffer */
2091     if (NULL == (tmp_fill_buf = (unsigned char *)HDmalloc(total_size)))
2092         goto out;
2093 
2094     /* get the fill value attributes */
2095     if ((H5TBAget_fill(loc_id, dset_name, did_1, tmp_fill_buf)) < 0)
2096         goto out;
2097 
2098     /*-------------------------------------------------------------------------
2099      * create a new data type
2100      *-------------------------------------------------------------------------
2101      */
2102 
2103     /* get the new member size */
2104     if (0 == (member_size = H5Tget_size(field_type)))
2105         goto out;
2106 
2107     /* create the data type. */
2108     if ((tid_2 = H5Tcreate(H5T_COMPOUND, (size_t)(total_size + member_size))) < 0)
2109         goto out;
2110 
2111     curr_offset = 0;
2112     inserted    = FALSE;
2113 
2114     /* insert the old fields, counting with the new one */
2115     for (i = 0; i < nfields + 1; i++) {
2116         hsize_t idx;
2117 
2118         idx = i;
2119         if (inserted)
2120             idx = i - 1;
2121 
2122         if (i == position) {
2123             /* get the new member size */
2124             if (0 == (new_member_size = H5Tget_size(field_type)))
2125                 goto out;
2126 
2127             /* insert the new field type */
2128             if (H5Tinsert(tid_2, field_name, curr_offset, field_type) < 0)
2129                 goto out;
2130 
2131             curr_offset += new_member_size;
2132 
2133             inserted = TRUE;
2134         } /* end if */
2135         else {
2136             /* get the member name */
2137             if (NULL == (member_name = H5Tget_member_name(tid_1, (unsigned)idx)))
2138                 goto out;
2139 
2140             /* get the member type */
2141             if ((member_type_id = H5Tget_member_type(tid_1, (unsigned)idx)) < 0)
2142                 goto out;
2143 
2144             /* get the member size */
2145             if (0 == (member_size = H5Tget_size(member_type_id)))
2146                 goto out;
2147 
2148             /* insert it into the new type */
2149             if (H5Tinsert(tid_2, member_name, curr_offset, member_type_id) < 0)
2150                 goto out;
2151 
2152             curr_offset += member_size;
2153 
2154             H5free_memory(member_name);
2155             member_name = NULL;
2156 
2157             /* close the member type */
2158             if (H5Tclose(member_type_id) < 0)
2159                 goto out;
2160             member_type_id = H5I_INVALID_HID;
2161         } /* end else */
2162     }     /* end for */
2163 
2164     /*-------------------------------------------------------------------------
2165      * create a new temporary dataset
2166      *-------------------------------------------------------------------------
2167      */
2168 
2169     /* retrieve the size of chunk */
2170     if (H5Pget_chunk(pid_1, 1, dims_chunk) < 0)
2171         goto out;
2172 
2173     /* create a new simple data space with unlimited size, using the dimension */
2174     if ((sid_2 = H5Screate_simple(1, dims, maxdims)) < 0)
2175         goto out;
2176 
2177     /* modify dataset creation properties, i.e. enable chunking  */
2178     if ((pid_2 = H5Pcreate(H5P_DATASET_CREATE)) < 0)
2179         goto out;
2180     if (H5Pset_chunk(pid_2, 1, dims_chunk) < 0)
2181         goto out;
2182 
2183     /* create the dataset. */
2184     if ((did_2 = H5Dcreate2(loc_id, "new", tid_2, sid_2, H5P_DEFAULT, pid_2, H5P_DEFAULT)) < 0)
2185         goto out;
2186 
2187     /*-------------------------------------------------------------------------
2188      * read data from 1st table
2189      *-------------------------------------------------------------------------
2190      */
2191 
2192     if (NULL == (tmp_buf = (unsigned char *)HDcalloc((size_t)nrecords, (size_t)total_size)))
2193         goto out;
2194 
2195     /* define a hyperslab in the dataset of the size of the records */
2196     offset[0] = 0;
2197     count[0]  = nrecords;
2198     if (H5Sselect_hyperslab(sid_1, H5S_SELECT_SET, offset, NULL, count, NULL) < 0)
2199         goto out;
2200 
2201     /* create a memory dataspace handle */
2202     mem_size[0] = count[0];
2203     if ((msid_1 = H5Screate_simple(1, mem_size, NULL)) < 0)
2204         goto out;
2205 
2206     if (H5Dread(did_1, tid_1, msid_1, H5S_ALL, H5P_DEFAULT, tmp_buf) < 0)
2207         goto out;
2208 
2209     /*-------------------------------------------------------------------------
2210      * save data from 1st table into new table, using the 1st type id
2211      *-------------------------------------------------------------------------
2212      */
2213 
2214     /* write */
2215     if (H5Dwrite(did_2, tid_1, msid_1, H5S_ALL, H5P_DEFAULT, tmp_buf) < 0)
2216         goto out;
2217 
2218     /*-------------------------------------------------------------------------
2219      * save the function supplied data of the new field
2220      *-------------------------------------------------------------------------
2221      */
2222 
2223     /* create a write id */
2224     if ((write_type_id = H5Tcreate(H5T_COMPOUND, (size_t)new_member_size)) < 0)
2225         goto out;
2226 
2227     /* the field in the file is found by its name */
2228     if (H5Tinsert(write_type_id, field_name, (size_t)0, field_type) < 0)
2229         goto out;
2230 
2231     /* create xfer properties to preserve initialized data */
2232     if ((preserve_id = H5Pcreate(H5P_DATASET_XFER)) < 0)
2233         goto out;
2234     if (H5Pset_preserve(preserve_id, 1) < 0)
2235         goto out;
2236 
2237     /* only write if there is something to write */
2238     if (buf) {
2239         /* create a memory dataspace handle */
2240         if ((msid_2 = H5Screate_simple(1, mem_size, NULL)) < 0)
2241             goto out;
2242 
2243         /* write */
2244         if (H5Dwrite(did_2, write_type_id, msid_2, sid_2, preserve_id, buf) < 0)
2245             goto out;
2246     } /* end if */
2247 
2248     /*-------------------------------------------------------------------------
2249      * delete 1st table
2250      *-------------------------------------------------------------------------
2251      */
2252     if (H5Ldelete(loc_id, dset_name, H5P_DEFAULT) < 0)
2253         goto out;
2254 
2255     /*-------------------------------------------------------------------------
2256      * rename 2nd table
2257      *-------------------------------------------------------------------------
2258      */
2259     if (H5Lmove(loc_id, "new", H5L_SAME_LOC, dset_name, H5P_DEFAULT, H5P_DEFAULT) < 0)
2260         goto out;
2261 
2262     /*-------------------------------------------------------------------------
2263      * attach the conforming table attributes
2264      *-------------------------------------------------------------------------
2265      */
2266 
2267     /* get the number of records and fields  */
2268     if (H5TBget_table_info(loc_id, dset_name, &nfields, &nrecords) < 0)
2269         goto out;
2270 
2271     /* open the dataset. */
2272     if ((did_3 = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
2273         goto out;
2274 
2275     /* get the datatype */
2276     if ((tid_3 = H5Dget_type(did_3)) < 0)
2277         goto out;
2278 
2279     /* set the attributes */
2280     if (H5TB_attach_attributes(table_title, loc_id, dset_name, (hsize_t)nfields, tid_3) < 0)
2281         goto out;
2282 
2283     /*-------------------------------------------------------------------------
2284      * attach the fill attributes from previous table
2285      *-------------------------------------------------------------------------
2286      */
2287     if ((sid_3 = H5Screate(H5S_SCALAR)) < 0)
2288         goto out;
2289 
2290     for (i = 0; i < (nfields - 1); i++) {
2291         size_t member_offset;
2292 
2293         /* get the member type */
2294         if ((member_type_id = H5Tget_member_type(tid_3, (unsigned)i)) < 0)
2295             goto out;
2296 
2297         /* get the member offset */
2298         member_offset = H5Tget_member_offset(tid_3, (unsigned)i);
2299 
2300         HDsnprintf(attr_name, sizeof(attr_name), "FIELD_%d_FILL", (int)i);
2301 
2302         if ((attr_id = H5Acreate2(did_3, attr_name, member_type_id, sid_3, H5P_DEFAULT, H5P_DEFAULT)) < 0)
2303             goto out;
2304 
2305         if (H5Awrite(attr_id, member_type_id, tmp_fill_buf + member_offset) < 0)
2306             goto out;
2307 
2308         if (H5Aclose(attr_id) < 0)
2309             goto out;
2310         attr_id = H5I_INVALID_HID;
2311 
2312         /* close the member type */
2313         if (H5Tclose(member_type_id) < 0)
2314             goto out;
2315         member_type_id = H5I_INVALID_HID;
2316     } /* end for */
2317 
2318     /*-------------------------------------------------------------------------
2319      * attach the fill attribute from the new field, if present
2320      *-------------------------------------------------------------------------
2321      */
2322     if (fill_data) {
2323         HDsnprintf(attr_name, sizeof(attr_name), "FIELD_%d_FILL", (int)(nfields - 1));
2324 
2325         /* get the member type */
2326         if ((member_type_id = H5Tget_member_type(tid_3, (unsigned)nfields - 1)) < 0)
2327             goto out;
2328 
2329         if ((attr_id = H5Acreate2(did_3, attr_name, member_type_id, sid_3, H5P_DEFAULT, H5P_DEFAULT)) < 0)
2330             goto out;
2331 
2332         if (H5Awrite(attr_id, member_type_id, fill_data) < 0)
2333             goto out;
2334 
2335         if (H5Aclose(attr_id) < 0)
2336             goto out;
2337         attr_id = H5I_INVALID_HID;
2338 
2339         if (H5Tclose(member_type_id) < 0)
2340             goto out;
2341         member_type_id = H5I_INVALID_HID;
2342     } /* end fill_data */
2343 
2344     ret_val = 0;
2345 
2346 out:
2347     if (member_name)
2348         H5free_memory(member_name);
2349     if (tmp_buf)
2350         HDfree(tmp_buf);
2351     if (tmp_fill_buf)
2352         HDfree(tmp_fill_buf);
2353     if (preserve_id > 0)
2354         if (H5Pclose(preserve_id) < 0)
2355             ret_val = -1;
2356     if (msid_1 > 0)
2357         if (H5Sclose(msid_1) < 0)
2358             ret_val = -1;
2359     if (tid_1 > 0)
2360         if (H5Tclose(tid_1) < 0)
2361             ret_val = -1;
2362     if (pid_1 > 0)
2363         if (H5Pclose(pid_1) < 0)
2364             ret_val = -1;
2365     if (sid_1 > 0)
2366         if (H5Sclose(sid_1) < 0)
2367             ret_val = -1;
2368     if (did_1 > 0)
2369         if (H5Dclose(did_1) < 0)
2370             ret_val = -1;
2371     if (msid_2 > 0)
2372         if (H5Sclose(msid_2) < 0)
2373             ret_val = -1;
2374     if (sid_2 > 0)
2375         if (H5Sclose(sid_2) < 0)
2376             ret_val = -1;
2377     if (tid_2 > 0)
2378         if (H5Tclose(tid_2) < 0)
2379             ret_val = -1;
2380     if (pid_2 > 0)
2381         if (H5Pclose(pid_2) < 0)
2382             ret_val = -1;
2383     if (did_2 > 0)
2384         if (H5Dclose(did_2) < 0)
2385             ret_val = -1;
2386     if (sid_3 > 0)
2387         if (H5Sclose(sid_3) < 0)
2388             ret_val = -1;
2389     if (tid_3 > 0)
2390         if (H5Tclose(tid_3) < 0)
2391             ret_val = -1;
2392     if (did_3 > 0)
2393         if (H5Dclose(did_3) < 0)
2394             ret_val = -1;
2395 
2396     return ret_val;
2397 } /* end H5TBinsert_field() */
2398 
2399 /*-------------------------------------------------------------------------
2400  * Function: H5TBdelete_field
2401  *
2402  * Purpose: Deletes a field
2403  *
2404  * Return: Success: 0, Failure: -1
2405  *
2406  * Programmer: Pedro Vicente
2407  *
2408  * Date: January 30, 2002
2409  *
2410  * Comments:
2411  *
2412  *-------------------------------------------------------------------------
2413  */
2414 herr_t
H5TBdelete_field(hid_t loc_id,const char * dset_name,const char * field_name)2415 H5TBdelete_field(hid_t loc_id, const char *dset_name, const char *field_name)
2416 {
2417     /* identifiers for the 1st original dataset */
2418     hid_t did_1 = H5I_INVALID_HID;
2419     hid_t tid_1 = H5I_INVALID_HID;
2420     hid_t sid_1 = H5I_INVALID_HID;
2421     hid_t pid_1 = H5I_INVALID_HID;
2422     /* identifiers for the 2nd new dataset */
2423     hid_t did_2 = H5I_INVALID_HID;
2424     hid_t tid_2 = H5I_INVALID_HID;
2425     hid_t sid_2 = H5I_INVALID_HID;
2426     hid_t pid_2 = H5I_INVALID_HID;
2427     /* identifiers for the 3rd final dataset */
2428     hid_t          did_3          = H5I_INVALID_HID;
2429     hid_t          tid_3          = H5I_INVALID_HID;
2430     hid_t          member_type_id = H5I_INVALID_HID;
2431     hid_t          preserve_id    = H5I_INVALID_HID;
2432     hid_t          read_type_id   = H5I_INVALID_HID;
2433     hid_t          write_type_id  = H5I_INVALID_HID;
2434     hid_t          attr_id        = H5I_INVALID_HID;
2435     size_t         member_size;
2436     size_t         type_size1;
2437     size_t         type_size2;
2438     size_t         curr_offset;
2439     size_t         delete_member_size = 0;
2440     size_t         member_offset;
2441     hsize_t        nfields;
2442     hsize_t        nrecords;
2443     hsize_t        dims_chunk[1];
2444     hsize_t        dims[1];
2445     hsize_t        maxdims[1] = {H5S_UNLIMITED};
2446     hsize_t        i;
2447     char           attr_name[255];
2448     char           table_title[255];
2449     char *         member_name  = NULL;
2450     unsigned char *tmp_buf      = NULL;
2451     unsigned char *tmp_fill_buf = NULL;
2452     htri_t         has_fill     = FALSE;
2453     herr_t         ret_val      = -1;
2454 
2455     /* check the arguments */
2456     if (dset_name == NULL)
2457         goto out;
2458     if (field_name == NULL)
2459         goto out;
2460 
2461     /* get the number of records and fields  */
2462     if (H5TBget_table_info(loc_id, dset_name, &nfields, &nrecords) < 0)
2463         goto out;
2464 
2465     /*-------------------------------------------------------------------------
2466      * get information about the old data type
2467      *-------------------------------------------------------------------------
2468      */
2469 
2470     /* open the dataset. */
2471     if ((did_1 = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
2472         goto out;
2473 
2474     /* get creation properties list */
2475     if ((pid_1 = H5Dget_create_plist(did_1)) < 0)
2476         goto out;
2477 
2478     /* get the datatype */
2479     if ((tid_1 = H5Dget_type(did_1)) < 0)
2480         goto out;
2481 
2482     /* get the size of the datatype */
2483     if (0 == (type_size1 = H5Tget_size(tid_1)))
2484         goto out;
2485 
2486     /* get the dataspace handle */
2487     if ((sid_1 = H5Dget_space(did_1)) < 0)
2488         goto out;
2489 
2490     /* get dimension */
2491     if (H5Sget_simple_extent_dims(sid_1, dims, NULL) < 0)
2492         goto out;
2493 
2494     /*-------------------------------------------------------------------------
2495      * create a new data type; first we find the size of the datatype to delete
2496      *-------------------------------------------------------------------------
2497      */
2498 
2499     /* check out the field */
2500     for (i = 0; i < nfields; i++) {
2501         /* get the member name */
2502         if (NULL == (member_name = H5Tget_member_name(tid_1, (unsigned)i)))
2503             goto out;
2504 
2505         /* we want to find the field to delete */
2506         if (H5TB_find_field(member_name, field_name)) {
2507             /* get the member type */
2508             if ((member_type_id = H5Tget_member_type(tid_1, (unsigned)i)) < 0)
2509                 goto out;
2510 
2511             /* get the member size */
2512             if (0 == (delete_member_size = H5Tget_size(member_type_id)))
2513                 goto out;
2514 
2515             /* close the member type */
2516             if (H5Tclose(member_type_id) < 0)
2517                 goto out;
2518             member_type_id = H5I_INVALID_HID;
2519 
2520             H5free_memory(member_name);
2521             member_name = NULL;
2522 
2523             break;
2524         } /* end if */
2525 
2526         H5free_memory(member_name);
2527         member_name = NULL;
2528     } /* end for */
2529 
2530     /* no field to delete was found */
2531     if (delete_member_size == 0)
2532         goto out;
2533 
2534     /*-------------------------------------------------------------------------
2535      * create a new data type; we now insert all the fields into the new type
2536      *-------------------------------------------------------------------------
2537      */
2538 
2539     type_size2 = type_size1 - delete_member_size;
2540 
2541     /* create the data type. */
2542     if ((tid_2 = H5Tcreate(H5T_COMPOUND, type_size2)) < 0)
2543         goto out;
2544 
2545     curr_offset = 0;
2546 
2547     /* alloc fill value attribute buffer */
2548     if (NULL == (tmp_fill_buf = (unsigned char *)HDmalloc((size_t)type_size2)))
2549         goto out;
2550 
2551     /*-------------------------------------------------------------------------
2552      * get attributes from previous table in the process
2553      *-------------------------------------------------------------------------
2554      */
2555 
2556     /* get the table title */
2557     if ((H5TBAget_title(did_1, table_title)) < 0)
2558         goto out;
2559 
2560     /* insert the old fields except the one to delete */
2561     for (i = 0; i < nfields; i++) {
2562         /* get the member name */
2563         if (NULL == (member_name = H5Tget_member_name(tid_1, (unsigned)i)))
2564             goto out;
2565 
2566         /* we want to skip the field to delete */
2567         if (!H5TB_find_field(member_name, field_name)) {
2568             /* get the member type */
2569             if ((member_type_id = H5Tget_member_type(tid_1, (unsigned)i)) < 0)
2570                 goto out;
2571 
2572             /* get the member size */
2573             if (0 == (member_size = H5Tget_size(member_type_id)))
2574                 goto out;
2575 
2576             /* insert it into the new type */
2577             if (H5Tinsert(tid_2, member_name, curr_offset, member_type_id) < 0)
2578                 goto out;
2579 
2580             /*-------------------------------------------------------------------------
2581              * get the fill value information
2582              *-------------------------------------------------------------------------
2583              */
2584 
2585             HDsnprintf(attr_name, sizeof(attr_name), "FIELD_%d_FILL", (int)i);
2586 
2587             /* check if we have the _FILL attribute */
2588             if ((has_fill = H5LT_find_attribute(did_1, attr_name)) < 0)
2589                 goto out;
2590 
2591             /* get it */
2592             if (has_fill)
2593                 if (H5LT_get_attribute_disk(did_1, attr_name, tmp_fill_buf + curr_offset) < 0)
2594                     goto out;
2595 
2596             curr_offset += member_size;
2597 
2598             /* close the member type */
2599             if (H5Tclose(member_type_id) < 0)
2600                 goto out;
2601             member_type_id = H5I_INVALID_HID;
2602         } /* end if */
2603 
2604         H5free_memory(member_name);
2605         member_name = NULL;
2606     } /* end for */
2607 
2608     /*-------------------------------------------------------------------------
2609      * create a new temporary dataset
2610      *-------------------------------------------------------------------------
2611      */
2612 
2613     /* retrieve the size of chunk */
2614     if (H5Pget_chunk(pid_1, 1, dims_chunk) < 0)
2615         goto out;
2616 
2617     /* create a new simple data space with unlimited size, using the dimension */
2618     if ((sid_2 = H5Screate_simple(1, dims, maxdims)) < 0)
2619         goto out;
2620 
2621     /* modify dataset creation properties, i.e. enable chunking  */
2622     pid_2 = H5Pcreate(H5P_DATASET_CREATE);
2623     if (H5Pset_chunk(pid_2, 1, dims_chunk) < 0)
2624         goto out;
2625 
2626     /* create the dataset. */
2627     if ((did_2 = H5Dcreate2(loc_id, "new", tid_2, sid_2, H5P_DEFAULT, pid_2, H5P_DEFAULT)) < 0)
2628         goto out;
2629 
2630     /*-------------------------------------------------------------------------
2631      * we have to read field by field of the old dataset and save it into the new one
2632      *-------------------------------------------------------------------------
2633      */
2634     for (i = 0; i < nfields; i++) {
2635         /* get the member name */
2636         if (NULL == (member_name = H5Tget_member_name(tid_1, (unsigned)i)))
2637             goto out;
2638 
2639         /* skip the field to delete */
2640         if (!H5TB_find_field(member_name, field_name)) {
2641             /* get the member type */
2642             if ((member_type_id = H5Tget_member_type(tid_1, (unsigned)i)) < 0)
2643                 goto out;
2644 
2645             /* get the member size */
2646             if (0 == (member_size = H5Tget_size(member_type_id)))
2647                 goto out;
2648 
2649             /* create a read id */
2650             if ((read_type_id = H5Tcreate(H5T_COMPOUND, member_size)) < 0)
2651                 goto out;
2652 
2653             /* insert it into the new type */
2654             if (H5Tinsert(read_type_id, member_name, (size_t)0, member_type_id) < 0)
2655                 goto out;
2656 
2657             if (NULL == (tmp_buf = (unsigned char *)HDcalloc((size_t)nrecords, member_size)))
2658                 goto out;
2659 
2660             /* read */
2661             if (H5Dread(did_1, read_type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, tmp_buf) < 0)
2662                 goto out;
2663 
2664             /* create a write id */
2665             if ((write_type_id = H5Tcreate(H5T_COMPOUND, member_size)) < 0)
2666                 goto out;
2667 
2668             /* the field in the file is found by its name */
2669             if (H5Tinsert(write_type_id, member_name, (size_t)0, member_type_id) < 0)
2670                 goto out;
2671 
2672             /* create xfer properties to preserve initialized data */
2673             if ((preserve_id = H5Pcreate(H5P_DATASET_XFER)) < 0)
2674                 goto out;
2675             if (H5Pset_preserve(preserve_id, 1) < 0)
2676                 goto out;
2677 
2678             /* write */
2679             if (H5Dwrite(did_2, write_type_id, H5S_ALL, H5S_ALL, preserve_id, tmp_buf) < 0)
2680                 goto out;
2681 
2682             /* end access to the property list */
2683             if (H5Pclose(preserve_id) < 0)
2684                 goto out;
2685             preserve_id = H5I_INVALID_HID;
2686 
2687             /* close the member type */
2688             if (H5Tclose(member_type_id) < 0)
2689                 goto out;
2690             member_type_id = H5I_INVALID_HID;
2691 
2692             /* close the read type */
2693             if (H5Tclose(read_type_id) < 0)
2694                 goto out;
2695             read_type_id = H5I_INVALID_HID;
2696 
2697             /* close the write type */
2698             if (H5Tclose(write_type_id) < 0)
2699                 goto out;
2700             write_type_id = H5I_INVALID_HID;
2701 
2702             HDfree(tmp_buf);
2703             tmp_buf = NULL;
2704         } /* end if */
2705 
2706         /* release resources. */
2707         H5free_memory(member_name);
2708         member_name = NULL;
2709     } /* end for */
2710 
2711     /*-------------------------------------------------------------------------
2712      * delete 1st table
2713      *-------------------------------------------------------------------------
2714      */
2715     if (H5Ldelete(loc_id, dset_name, H5P_DEFAULT) < 0)
2716         goto out;
2717 
2718     /*-------------------------------------------------------------------------
2719      * rename 2nd table
2720      *-------------------------------------------------------------------------
2721      */
2722     if (H5Lmove(loc_id, "new", H5L_SAME_LOC, dset_name, H5P_DEFAULT, H5P_DEFAULT) < 0)
2723         goto out;
2724 
2725     /*-------------------------------------------------------------------------
2726      * attach the conforming table attributes
2727      *-------------------------------------------------------------------------
2728      */
2729 
2730     /* get the number of records and fields  */
2731     if (H5TBget_table_info(loc_id, dset_name, &nfields, &nrecords) < 0)
2732         goto out;
2733 
2734     /* open the dataset. */
2735     if ((did_3 = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
2736         goto out;
2737 
2738     /* get the datatype */
2739     if ((tid_3 = H5Dget_type(did_3)) < 0)
2740         goto out;
2741 
2742     /* set the attributes */
2743     if (H5TB_attach_attributes(table_title, loc_id, dset_name, nfields, tid_3) < 0)
2744         goto out;
2745 
2746     /*-------------------------------------------------------------------------
2747      * attach the fill attributes from previous table
2748      *-------------------------------------------------------------------------
2749      */
2750     if (has_fill) {
2751         if ((sid_1 = H5Screate(H5S_SCALAR)) < 0)
2752             goto out;
2753 
2754         for (i = 0; i < nfields; i++) {
2755             /* get the member type */
2756             if ((member_type_id = H5Tget_member_type(tid_3, (unsigned)i)) < 0)
2757                 goto out;
2758 
2759             /* get the member offset */
2760             member_offset = H5Tget_member_offset(tid_3, (unsigned)i);
2761 
2762             HDsnprintf(attr_name, sizeof(attr_name), "FIELD_%d_FILL", (int)i);
2763 
2764             if ((attr_id = H5Acreate2(did_3, attr_name, member_type_id, sid_1, H5P_DEFAULT, H5P_DEFAULT)) < 0)
2765                 goto out;
2766 
2767             if (H5Awrite(attr_id, member_type_id, tmp_fill_buf + member_offset) < 0)
2768                 goto out;
2769 
2770             if (H5Aclose(attr_id) < 0)
2771                 goto out;
2772             attr_id = H5I_INVALID_HID;
2773 
2774             /* close the member type */
2775             if (H5Tclose(member_type_id) < 0)
2776                 goto out;
2777             member_type_id = H5I_INVALID_HID;
2778         } /* end for */
2779 
2780         /* close data space. */
2781         if (H5Sclose(sid_1) < 0)
2782             goto out;
2783         sid_1 = H5I_INVALID_HID;
2784     } /* end if */
2785 
2786     ret_val = 0;
2787 
2788 out:
2789     if (member_name)
2790         H5free_memory(member_name);
2791     if (tmp_fill_buf)
2792         HDfree(tmp_fill_buf);
2793     if (tmp_buf)
2794         HDfree(tmp_buf);
2795     if (attr_id > 0)
2796         if (H5Aclose(attr_id) < 0)
2797             ret_val = -1;
2798     if (preserve_id > 0)
2799         if (H5Pclose(preserve_id) < 0)
2800             ret_val = -1;
2801     if (member_type_id > 0)
2802         if (H5Tclose(member_type_id) < 0)
2803             ret_val = -1;
2804     if (read_type_id > 0)
2805         if (H5Tclose(read_type_id) < 0)
2806             ret_val = -1;
2807     if (write_type_id > 0)
2808         if (H5Tclose(write_type_id) < 0)
2809             ret_val = -1;
2810     if (tid_1 > 0)
2811         if (H5Tclose(tid_1) < 0)
2812             ret_val = -1;
2813     if (pid_1 > 0)
2814         if (H5Pclose(pid_1) < 0)
2815             ret_val = -1;
2816     if (sid_1 > 0)
2817         if (H5Sclose(sid_1) < 0)
2818             ret_val = -1;
2819     if (did_1 > 0)
2820         if (H5Dclose(did_1) < 0)
2821             ret_val = -1;
2822     if (sid_2 > 0)
2823         if (H5Sclose(sid_2) < 0)
2824             ret_val = -1;
2825     if (tid_2 > 0)
2826         if (H5Tclose(tid_2) < 0)
2827             ret_val = -1;
2828     if (pid_2 > 0)
2829         if (H5Pclose(pid_2) < 0)
2830             ret_val = -1;
2831     if (did_2 > 0)
2832         if (H5Dclose(did_2) < 0)
2833             ret_val = -1;
2834     if (tid_3 > 0)
2835         if (H5Tclose(tid_3) < 0)
2836             ret_val = -1;
2837     if (did_3 > 0)
2838         if (H5Dclose(did_3) < 0)
2839             ret_val = -1;
2840 
2841     return ret_val;
2842 } /* end H5TBdelete_field() */
2843 
2844 /*-------------------------------------------------------------------------
2845  *
2846  * Table attribute functions
2847  *
2848  *-------------------------------------------------------------------------
2849  */
2850 
2851 /*-------------------------------------------------------------------------
2852  * Function: H5TBAget_title
2853  *
2854  * Purpose: Read the table title
2855  *
2856  * Return: Success: 0, Failure: -1
2857  *
2858  * Programmer: Pedro Vicente
2859  *
2860  * Date: January 30, 2001
2861  *
2862  * Comments:
2863  *
2864  *-------------------------------------------------------------------------
2865  */
2866 herr_t
H5TBAget_title(hid_t loc_id,char * table_title)2867 H5TBAget_title(hid_t loc_id, char *table_title)
2868 {
2869 
2870     /* Get the TITLE attribute */
2871     if (H5LT_get_attribute_disk(loc_id, "TITLE", table_title) < 0)
2872         return -1;
2873 
2874     return 0;
2875 }
2876 
2877 /*-------------------------------------------------------------------------
2878  * Function: H5TBAget_fill
2879  *
2880  * Purpose: Read the table attribute fill values
2881  *
2882  * Return: Success: TRUE/FALSE, Failure: -1
2883  *
2884  * Programmer: Pedro Vicente
2885  *
2886  * Date: January 30, 2002
2887  *
2888  * Comments:
2889  *
2890  *-------------------------------------------------------------------------
2891  */
2892 htri_t
H5TBAget_fill(hid_t loc_id,const char * dset_name,hid_t dset_id,unsigned char * dst_buf)2893 H5TBAget_fill(hid_t loc_id, const char *dset_name, hid_t dset_id, unsigned char *dst_buf)
2894 {
2895     hsize_t nfields;
2896     hsize_t nrecords;
2897     hsize_t i;
2898     size_t *src_offset = NULL;
2899     char    attr_name[255];
2900     htri_t  has_fill = FALSE;
2901     htri_t  ret_val  = -1;
2902 
2903     /* check the arguments */
2904     if (dset_name == NULL)
2905         goto out;
2906 
2907     /* get the number of records and fields  */
2908     if (H5TBget_table_info(loc_id, dset_name, &nfields, &nrecords) < 0)
2909         goto out;
2910 
2911     if (NULL == (src_offset = (size_t *)HDmalloc((size_t)nfields * sizeof(size_t))))
2912         goto out;
2913 
2914     /* get field info */
2915     if (H5TBget_field_info(loc_id, dset_name, NULL, NULL, src_offset, NULL) < 0)
2916         goto out;
2917 
2918     for (i = 0; i < nfields; i++) {
2919         HDsnprintf(attr_name, sizeof(attr_name), "FIELD_%d_FILL", (int)i);
2920 
2921         /* check if we have the _FILL attribute */
2922         if ((has_fill = H5LT_find_attribute(dset_id, attr_name)) < 0)
2923             goto out;
2924 
2925         /* get it */
2926         if (has_fill)
2927             if (H5LT_get_attribute_disk(dset_id, attr_name, dst_buf + src_offset[i]) < 0)
2928                 goto out;
2929     } /* end for */
2930 
2931     ret_val = has_fill;
2932 
2933 out:
2934     if (src_offset)
2935         HDfree(src_offset);
2936 
2937     return ret_val;
2938 } /* end H5TBAget_fill() */
2939 
2940 /*-------------------------------------------------------------------------
2941  *
2942  * Inquiry functions
2943  *
2944  *-------------------------------------------------------------------------
2945  */
2946 
2947 /*-------------------------------------------------------------------------
2948  * Function: H5TBget_table_info
2949  *
2950  * Purpose: Gets the number of records and fields of a table
2951  *
2952  * Return: Success: 0, Failure: -1
2953  *
2954  * Programmer: Pedro Vicente
2955  *
2956  * Date: November 19, 2001
2957  *
2958  * Comments:
2959  *
2960  *-------------------------------------------------------------------------
2961  */
2962 herr_t
H5TBget_table_info(hid_t loc_id,const char * dset_name,hsize_t * nfields,hsize_t * nrecords)2963 H5TBget_table_info(hid_t loc_id, const char *dset_name, hsize_t *nfields, hsize_t *nrecords)
2964 {
2965     hid_t   tid = H5I_INVALID_HID;
2966     hid_t   sid = H5I_INVALID_HID;
2967     hid_t   did = H5I_INVALID_HID;
2968     hsize_t dims[1];
2969     int     num_members;
2970     herr_t  ret_val = -1;
2971 
2972     /* check the arguments */
2973     if (dset_name == NULL)
2974         goto out;
2975 
2976     /* open the dataset. */
2977     if ((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
2978         goto out;
2979 
2980     /* get the datatype */
2981     if ((tid = H5Dget_type(did)) < 0)
2982         goto out;
2983 
2984     /* get the number of members */
2985     if ((num_members = H5Tget_nmembers(tid)) < 0)
2986         goto out;
2987 
2988     /*-------------------------------------------------------------------------
2989      * get number of nfields
2990      *-------------------------------------------------------------------------
2991      */
2992     if (nfields)
2993         *nfields = (hsize_t)num_members;
2994 
2995     /*-------------------------------------------------------------------------
2996      * get number of records
2997      *-------------------------------------------------------------------------
2998      */
2999     if (nrecords) {
3000         /* get the dataspace handle */
3001         if ((sid = H5Dget_space(did)) < 0)
3002             goto out;
3003 
3004         /* get dimension */
3005         if (H5Sget_simple_extent_dims(sid, dims, NULL) < 0)
3006             goto out;
3007 
3008         /* terminate access to the dataspace */
3009         if (H5Sclose(sid) < 0)
3010             goto out;
3011         sid = H5I_INVALID_HID;
3012 
3013         *nrecords = dims[0];
3014     } /* end if */
3015 
3016     ret_val = 0;
3017 
3018 out:
3019     if (sid > 0)
3020         if (H5Sclose(sid) < 0)
3021             ret_val = -1;
3022     if (tid > 0)
3023         if (H5Tclose(tid) < 0)
3024             ret_val = -1;
3025     if (did > 0)
3026         if (H5Dclose(did) < 0)
3027             ret_val = -1;
3028 
3029     return ret_val;
3030 } /* end H5TBget_table_info() */
3031 
3032 /*-------------------------------------------------------------------------
3033  * Function: H5TBget_field_info
3034  *
3035  * Purpose: Get information about fields
3036  *
3037  * Return: Success: 0, Failure: -1
3038  *
3039  * Programmer: Pedro Vicente
3040  *
3041  * Date: November 19, 2001
3042  *
3043  * Comments:
3044  *
3045  *-------------------------------------------------------------------------
3046  */
3047 herr_t
H5TBget_field_info(hid_t loc_id,const char * dset_name,char * field_names[],size_t * field_sizes,size_t * field_offsets,size_t * type_size)3048 H5TBget_field_info(hid_t loc_id, const char *dset_name, char *field_names[], size_t *field_sizes,
3049                    size_t *field_offsets, size_t *type_size)
3050 {
3051     hid_t    did    = H5I_INVALID_HID; /* dataset ID */
3052     hid_t    tid    = H5I_INVALID_HID; /* file type ID */
3053     hid_t    n_tid  = H5I_INVALID_HID; /* native type ID */
3054     hid_t    m_tid  = H5I_INVALID_HID; /* member type ID */
3055     hid_t    nm_tid = H5I_INVALID_HID; /* native member ID */
3056     hssize_t nfields;
3057     hssize_t i;
3058     herr_t   ret_val = -1;
3059 
3060     /* check the arguments */
3061     if (dset_name == NULL)
3062         goto out;
3063 
3064     /* open the dataset. */
3065     if ((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
3066         goto out;
3067 
3068     /* get the datatype */
3069     if ((tid = H5Dget_type(did)) < 0)
3070         goto out;
3071 
3072     if ((n_tid = H5Tget_native_type(tid, H5T_DIR_DEFAULT)) < 0)
3073         goto out;
3074 
3075     /* get the type size */
3076     if (type_size)
3077         if (0 == (*type_size = H5Tget_size(n_tid)))
3078             goto out;
3079 
3080     /* get the number of members */
3081     if ((nfields = H5Tget_nmembers(tid)) < 0)
3082         goto out;
3083 
3084     /* iterate tru the members */
3085     for (i = 0; i < nfields; i++) {
3086         /* get the member name */
3087         if (field_names) {
3088             char *member_name;
3089 
3090             if (NULL == (member_name = H5Tget_member_name(tid, (unsigned)i)))
3091                 goto out;
3092             strcpy(field_names[i], member_name);
3093             H5free_memory(member_name);
3094         } /* end if */
3095 
3096         /* get the member type */
3097         if ((m_tid = H5Tget_member_type(tid, (unsigned)i)) < 0)
3098             goto out;
3099         if ((nm_tid = H5Tget_native_type(m_tid, H5T_DIR_DEFAULT)) < 0)
3100             goto out;
3101 
3102         /* get the member size */
3103         if (field_sizes)
3104             if (0 == (field_sizes[i] = H5Tget_size(nm_tid)))
3105                 goto out;
3106 
3107         /* get the member offset */
3108         if (field_offsets)
3109             field_offsets[i] = H5Tget_member_offset(n_tid, (unsigned)i);
3110 
3111         /* close the member types */
3112         if (H5Tclose(m_tid) < 0)
3113             goto out;
3114         m_tid = H5I_INVALID_HID;
3115         if (H5Tclose(nm_tid) < 0)
3116             goto out;
3117         nm_tid = H5I_INVALID_HID;
3118     } /* end for */
3119 
3120     ret_val = 0;
3121 
3122 out:
3123     if (tid > 0)
3124         if (H5Tclose(tid) < 0)
3125             ret_val = -1;
3126     if (n_tid > 0)
3127         if (H5Tclose(n_tid) < 0)
3128             ret_val = -1;
3129     if (m_tid > 0)
3130         if (H5Tclose(m_tid) < 0)
3131             ret_val = -1;
3132     if (nm_tid > 0)
3133         if (H5Tclose(nm_tid) < 0)
3134             ret_val = -1;
3135     if (did > 0)
3136         if (H5Dclose(did) < 0)
3137             ret_val = -1;
3138 
3139     return ret_val;
3140 } /* end H5TBget_field_info() */
3141 
3142 /*-------------------------------------------------------------------------
3143  *
3144  * internal functions
3145  *
3146  *-------------------------------------------------------------------------
3147  */
3148 
3149 /*-------------------------------------------------------------------------
3150  * Function: H5TB_find_field
3151  *
3152  * Purpose: Find a string field
3153  *
3154  * Return: Success: TRUE/FALSE, Failure: N/A
3155  *
3156  * Programmer: Pedro Vicente
3157  *
3158  * Date: November 19, 2001
3159  *
3160  *-------------------------------------------------------------------------
3161  */
3162 H5_ATTR_PURE static hbool_t
H5TB_find_field(const char * field,const char * field_list)3163 H5TB_find_field(const char *field, const char *field_list)
3164 {
3165     const char *start = field_list;
3166     const char *end;
3167 
3168     /* check the arguments */
3169     if (field == NULL)
3170         return FALSE;
3171     if (field_list == NULL)
3172         return FALSE;
3173 
3174     while ((end = HDstrstr(start, ",")) != 0) {
3175         ptrdiff_t count = end - start;
3176 
3177         if (HDstrncmp(start, field, (size_t)count) == 0 && (size_t)count == HDstrlen(field))
3178             return TRUE;
3179         start = end + 1;
3180     } /* end while */
3181 
3182     if (HDstrncmp(start, field, HDstrlen(field)) == 0)
3183         return TRUE;
3184 
3185     return FALSE;
3186 } /* end H5TB_find_field() */
3187 
3188 /*-------------------------------------------------------------------------
3189  * Function: H5TB_attach_attributes
3190  *
3191  * Purpose: Private function that creates the conforming table attributes;
3192  *          Used by H5TBcombine_tables; not used by H5TBmake_table, which does not read
3193  *          the fill value attributes from an existing table
3194  *
3195  * Return: Success: 0, Failure: -1
3196  *
3197  * Programmer: Pedro Vicente
3198  *
3199  * Date: December 6, 2001
3200  *
3201  * Comments:
3202  *
3203  *-------------------------------------------------------------------------
3204  */
3205 static herr_t
H5TB_attach_attributes(const char * table_title,hid_t loc_id,const char * dset_name,hsize_t nfields,hid_t tid)3206 H5TB_attach_attributes(const char *table_title, hid_t loc_id, const char *dset_name, hsize_t nfields,
3207                        hid_t tid)
3208 {
3209     char    attr_name[255];
3210     char *  member_name = NULL;
3211     hsize_t i;
3212     herr_t  ret_val = -1;
3213 
3214     /* attach the CLASS attribute */
3215     if (H5LTset_attribute_string(loc_id, dset_name, "CLASS", TABLE_CLASS) < 0)
3216         goto out;
3217 
3218     /* attach the VERSION attribute */
3219     if (H5LTset_attribute_string(loc_id, dset_name, "VERSION", TABLE_VERSION) < 0)
3220         goto out;
3221 
3222     /* attach the TITLE attribute */
3223     if (H5LTset_attribute_string(loc_id, dset_name, "TITLE", table_title) < 0)
3224         goto out;
3225 
3226     /* attach the FIELD_ name attribute */
3227     for (i = 0; i < nfields; i++) {
3228         /* get the member name */
3229         if (NULL == (member_name = H5Tget_member_name(tid, (unsigned)i)))
3230             goto out;
3231 
3232         HDsnprintf(attr_name, sizeof(attr_name), "FIELD_%d_NAME", (int)i);
3233 
3234         /* attach the attribute */
3235         if (H5LTset_attribute_string(loc_id, dset_name, attr_name, member_name) < 0)
3236             goto out;
3237 
3238         H5free_memory(member_name);
3239         member_name = NULL;
3240     } /* end for */
3241 
3242     ret_val = 0;
3243 
3244 out:
3245     if (member_name)
3246         H5free_memory(member_name);
3247 
3248     return ret_val;
3249 } /* end H5TB_attach_attributes() */
3250 
3251 /*-------------------------------------------------------------------------
3252  * Function: H5TB_create_type
3253  *
3254  * Purpose: Private function that creates a memory type ID
3255  *
3256  * Return: Success: the memory type ID, Failure: -1
3257  *
3258  * Programmer: Pedro Vicente
3259  *
3260  * Date: March 31, 2004
3261  *
3262  * Comments:
3263  *
3264  *-------------------------------------------------------------------------
3265  */
3266 static hid_t
H5TB_create_type(hid_t loc_id,const char * dset_name,size_t type_size,const size_t * field_offset,const size_t * field_sizes,hid_t ftype_id)3267 H5TB_create_type(hid_t loc_id, const char *dset_name, size_t type_size, const size_t *field_offset,
3268                  const size_t *field_sizes, hid_t ftype_id)
3269 {
3270     hid_t    mem_type_id = H5I_INVALID_HID;
3271     hid_t    mtype_id    = H5I_INVALID_HID;
3272     hid_t    nmtype_id   = H5I_INVALID_HID;
3273     size_t   size_native;
3274     hsize_t  nfields = 0;
3275     char **  fnames  = NULL;
3276     unsigned i;
3277     hid_t    ret_val = -1;
3278 
3279     /* get the number of fields  */
3280     if (H5TBget_table_info(loc_id, dset_name, &nfields, NULL) < 0)
3281         goto out;
3282 
3283     if (NULL == (fnames = (char **)HDcalloc(sizeof(char *), (size_t)nfields)))
3284         goto out;
3285 
3286     for (i = 0; i < nfields; i++)
3287         if (NULL == (fnames[i] = (char *)HDmalloc(HLTB_MAX_FIELD_LEN)))
3288             goto out;
3289 
3290     /* get field info */
3291     if (H5TBget_field_info(loc_id, dset_name, fnames, NULL, NULL, NULL) < 0)
3292         goto out;
3293 
3294     /* create the memory data type */
3295     if ((mem_type_id = H5Tcreate(H5T_COMPOUND, type_size)) < 0)
3296         goto out;
3297 
3298     /* get each field ID and adjust its size, if necessary */
3299     for (i = 0; i < nfields; i++) {
3300         if ((mtype_id = H5Tget_member_type(ftype_id, i)) < 0)
3301             goto out;
3302         if ((nmtype_id = H5Tget_native_type(mtype_id, H5T_DIR_DEFAULT)) < 0)
3303             goto out;
3304         if (0 == (size_native = H5Tget_size(nmtype_id)))
3305             goto out;
3306         if (field_sizes[i] != size_native)
3307             if (H5Tset_size(nmtype_id, field_sizes[i]) < 0)
3308                 goto out;
3309         if (H5Tinsert(mem_type_id, fnames[i], field_offset[i], nmtype_id) < 0)
3310             goto out;
3311         if (H5Tclose(mtype_id) < 0)
3312             goto out;
3313         mtype_id = H5I_INVALID_HID;
3314         if (H5Tclose(nmtype_id) < 0)
3315             goto out;
3316         nmtype_id = H5I_INVALID_HID;
3317     } /* end for */
3318 
3319     ret_val = mem_type_id;
3320 
3321 out:
3322     if (fnames) {
3323         for (i = 0; i < nfields; i++)
3324             if (fnames[i])
3325                 HDfree(fnames[i]);
3326         HDfree(fnames);
3327     } /* end if */
3328     if (mtype_id > 0)
3329         if (H5Tclose(mtype_id) < 0)
3330             ret_val = -1;
3331     if (nmtype_id > 0)
3332         if (H5Tclose(nmtype_id) < 0)
3333             ret_val = -1;
3334     if (ret_val < 0 && mem_type_id > 0)
3335         H5Tclose(mem_type_id);
3336 
3337     return ret_val;
3338 } /* end H5TB_create_type() */
3339 
3340 /*-------------------------------------------------------------------------
3341  *
3342  * Functions shared between H5TB and H5PT
3343  *
3344  *-------------------------------------------------------------------------
3345  */
3346 
3347 /*-------------------------------------------------------------------------
3348  * Function: H5TB_common_append_records
3349  *
3350  * Purpose: Common code for reading records shared between H5PT and H5TB
3351  *
3352  * Return: Success: 0, Failure: -1
3353  *
3354  * Programmer: Nat Furrer
3355  *             James Laird
3356  *
3357  * Date: March 8, 2004
3358  *
3359  * Comments: Called by H5TBappend_records and H5PTappend_records
3360  *
3361  *-------------------------------------------------------------------------
3362  */
3363 herr_t
H5TB_common_append_records(hid_t dataset_id,hid_t mem_type_id,size_t nrecords,hsize_t orig_table_size,const void * buf)3364 H5TB_common_append_records(hid_t dataset_id, hid_t mem_type_id, size_t nrecords, hsize_t orig_table_size,
3365                            const void *buf)
3366 {
3367     hid_t   sid   = H5I_INVALID_HID;
3368     hid_t   m_sid = H5I_INVALID_HID;
3369     hsize_t count[1];
3370     hsize_t offset[1];
3371     hsize_t dims[1];
3372     hsize_t mem_dims[1];
3373     herr_t  ret_val = -1;
3374 
3375     /* extend the dataset */
3376     dims[0] = nrecords + orig_table_size;
3377     if (H5Dset_extent(dataset_id, dims) < 0)
3378         goto out;
3379 
3380     /* create a simple memory data space */
3381     mem_dims[0] = nrecords;
3382     if ((m_sid = H5Screate_simple(1, mem_dims, NULL)) < 0)
3383         goto out;
3384 
3385     /* get a copy of the new file data space for writing */
3386     if ((sid = H5Dget_space(dataset_id)) < 0)
3387         goto out;
3388 
3389     /* define a hyperslab in the dataset */
3390     offset[0] = orig_table_size;
3391     count[0]  = nrecords;
3392     if (H5Sselect_hyperslab(sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0)
3393         goto out;
3394 
3395     /* write the records */
3396     if (H5Dwrite(dataset_id, mem_type_id, m_sid, sid, H5P_DEFAULT, buf) < 0)
3397         goto out;
3398 
3399     ret_val = 0;
3400 
3401 out:
3402     if (m_sid > 0)
3403         if (H5Sclose(m_sid) < 0)
3404             ret_val = -1;
3405     if (sid > 0)
3406         if (H5Sclose(sid) < 0)
3407             ret_val = -1;
3408 
3409     return ret_val;
3410 } /* end H5TB_common_append_records() */
3411 
3412 /*-------------------------------------------------------------------------
3413  * Function: H5TB_common_read_records
3414  *
3415  * Purpose: Common code for reading records shared between H5PT and H5TB
3416  *
3417  * Return: Success: 0, Failure: -1
3418  *
3419  * Programmer: Nat Furrer
3420  *             James Laird
3421  *
3422  * Date: March 8, 2004
3423  *
3424  * Comments: Called by H5TBread_records and H5PTread_records
3425  *
3426  *-------------------------------------------------------------------------
3427  */
3428 herr_t
H5TB_common_read_records(hid_t dataset_id,hid_t mem_type_id,hsize_t start,size_t nrecords,hsize_t table_size,void * buf)3429 H5TB_common_read_records(hid_t dataset_id, hid_t mem_type_id, hsize_t start, size_t nrecords,
3430                          hsize_t table_size, void *buf)
3431 {
3432     hid_t   sid   = H5I_INVALID_HID;
3433     hid_t   m_sid = H5I_INVALID_HID;
3434     hsize_t count[1];
3435     hsize_t offset[1];
3436     hsize_t mem_size[1];
3437     herr_t  ret_val = -1;
3438 
3439     /* make sure the read request is in bounds */
3440     if (start + nrecords > table_size)
3441         goto out;
3442 
3443     /* get the dataspace handle */
3444     if ((sid = H5Dget_space(dataset_id)) < 0)
3445         goto out;
3446 
3447     /* define a hyperslab in the dataset of the size of the records */
3448     offset[0] = start;
3449     count[0]  = nrecords;
3450     if (H5Sselect_hyperslab(sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0)
3451         goto out;
3452 
3453     /* create a memory dataspace handle */
3454     mem_size[0] = count[0];
3455     if ((m_sid = H5Screate_simple(1, mem_size, NULL)) < 0)
3456         goto out;
3457     if ((H5Dread(dataset_id, mem_type_id, m_sid, sid, H5P_DEFAULT, buf)) < 0)
3458         goto out;
3459 
3460     ret_val = 0;
3461 
3462 out:
3463     if (m_sid > 0)
3464         if (H5Sclose(m_sid) < 0)
3465             ret_val = -1;
3466     if (sid > 0)
3467         if (H5Sclose(sid) < 0)
3468             ret_val = -1;
3469 
3470     return ret_val;
3471 } /* end H5TB_common_read_records() */
3472