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