Branch data Line data Source code
1 : : /**
2 : : * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3 : : * storing and accessing finite element mesh data.
4 : : *
5 : : * Copyright 2004 Sandia Corporation. Under the terms of Contract
6 : : * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7 : : * retains certain rights in this software.
8 : : *
9 : : * This library is free software; you can redistribute it and/or
10 : : * modify it under the terms of the GNU Lesser General Public
11 : : * License as published by the Free Software Foundation; either
12 : : * version 2.1 of the License, or (at your option) any later version.
13 : : *
14 : : */
15 : :
16 : : #include <stdlib.h>
17 : : #include <string.h>
18 : : #include <assert.h>
19 : : #include <ctype.h>
20 : : #include <hdf5.h>
21 : : #include "util.h"
22 : : #include "status.h"
23 : : #include "names-and-paths.h"
24 : :
25 : : #ifdef VALGRIND
26 : : #include <valgrind/memcheck.h>
27 : : #else
28 : : #define VALGRIND_CHECK_MEM_IS_DEFINED( A, B )
29 : : #define VALGRIND_MAKE_MEM_UNDEFINED( A, B )
30 : : #endif
31 : :
32 : 7513 : void* mhdf_malloc( size_t size, mhdf_Status* status )
33 : : {
34 : : void* result;
35 : 7513 : result = malloc( size );
36 [ - + ]: 7513 : if( !result ) mhdf_setFail( status, "Allocation of %d bytes failed.\n", (int)size );
37 : 7513 : return result;
38 : : }
39 : :
40 : 0 : void* mhdf_realloc( void* ptr, size_t size, mhdf_Status* status )
41 : : {
42 : : void* result;
43 : 0 : result = realloc( ptr, size );
44 [ # # ]: 0 : if( !result ) mhdf_setFail( status, "Allocation of %d bytes failed.\n", (int)size );
45 : 0 : return result;
46 : : }
47 : :
48 : 12882 : size_t mhdf_name_to_path( const char* name, char* path, size_t path_len )
49 : : {
50 : 12882 : size_t length = 1;
51 : : unsigned char* iter;
52 : :
53 [ - + ]: 12882 : if( 0 == strcmp( name, "." ) )
54 : : {
55 [ # # ]: 0 : if( path_len >= 4 ) sprintf( path, "\\%02X", (int)*name );
56 : 0 : return 4;
57 : : }
58 : :
59 [ + + ]: 141627 : for( iter = (unsigned char*)name; *iter; ++iter )
60 : : {
61 [ + - ][ + - ]: 128745 : if( iscntrl( *iter ) || *iter == '/' || *iter == '\\' || *iter > 127 )
[ + - ][ - + ]
62 : 0 : length += 3;
63 : : else
64 : 128745 : length += 1;
65 : : }
66 [ + + ]: 12882 : if( path_len < length ) return length;
67 : :
68 [ + + ]: 70662 : for( iter = (unsigned char*)name; *iter; ++iter )
69 : : {
70 [ + - ][ + - ]: 64247 : if( iscntrl( *iter ) || *iter == '/' || *iter == '\\' || *iter > 127 )
[ + - ][ - + ]
71 : : {
72 : 0 : sprintf( path, "\\%02X", (int)( *iter ) );
73 : 0 : path += 3;
74 : : }
75 : : else
76 : : {
77 : 64247 : *( path++ ) = *iter;
78 : : }
79 : : }
80 : :
81 : 6415 : *path = '\0';
82 : 6415 : return length;
83 : : }
84 : :
85 : 0 : static int mhdf_hex_char( int c )
86 : : {
87 [ # # ]: 0 : if( isdigit( c ) )
88 : 0 : return c - '0';
89 : : else
90 : 0 : return toupper( c ) - ( 'A' - 10 );
91 : : }
92 : :
93 : 799 : int mhdf_path_to_name( const char* path, char* name )
94 : : {
95 : : const char* iter;
96 : : char c1, c2;
97 : :
98 [ + + ]: 9333 : for( iter = path; *iter; ++iter, ++name )
99 : : {
100 [ - + ]: 8534 : if( *iter == '\\' )
101 : : {
102 : 0 : c1 = *++iter;
103 : 0 : c2 = *++iter;
104 [ # # ][ # # ]: 0 : if( !isxdigit( c1 ) || !isxdigit( c2 ) ) return 0;
105 : :
106 : 0 : *name = (char)( 16 * mhdf_hex_char( c1 ) + mhdf_hex_char( c2 ) );
107 : : }
108 : : else
109 : : {
110 : 8534 : *name = *iter;
111 : : }
112 : : }
113 : :
114 : 799 : *name = '\0';
115 : 799 : return 1;
116 : : }
117 : :
118 : 4153 : char* mhdf_name_to_path_copy( const char* name, mhdf_Status* status )
119 : : {
120 : : size_t size;
121 : : char* buffer;
122 : :
123 : 4153 : size = mhdf_name_to_path( name, NULL, 0 );
124 : 4153 : buffer = (char*)mhdf_malloc( size, status );
125 [ - + ]: 4153 : if( !buffer ) return NULL;
126 : :
127 : 4153 : mhdf_name_to_path( name, buffer, size );
128 : 4153 : return buffer;
129 : : }
130 : :
131 : 1872 : char* mhdf_name_to_path_cat( const char* prefix, const char* name, mhdf_Status* status )
132 : : {
133 : : size_t size, plen;
134 : : char* buffer;
135 : :
136 : 1872 : plen = strlen( prefix );
137 : 1872 : size = mhdf_name_to_path( name, NULL, 0 ) + 1;
138 : 1872 : buffer = (char*)mhdf_malloc( size + plen, status );
139 [ - + ]: 1872 : if( !buffer ) return NULL;
140 : :
141 : 1872 : memcpy( buffer, prefix, plen );
142 : 1872 : mhdf_name_to_path( name, buffer + plen, size );
143 : 1872 : return buffer;
144 : : }
145 : :
146 : 1872 : hid_t mhdf_elem_group_from_handle( FileHandle* file_ptr, const char* elem_handle, mhdf_Status* status )
147 : : {
148 : : char* path;
149 : : hid_t result;
150 : :
151 : 1872 : path = mhdf_name_to_path_cat( ELEMENT_GROUP, elem_handle, status );
152 [ - + ]: 1872 : if( NULL == path ) return -1;
153 : :
154 : : #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
155 : 1872 : result = H5Gopen2( file_ptr->hdf_handle, path, H5P_DEFAULT );
156 : : #else
157 : : result = H5Gopen( file_ptr->hdf_handle, path );
158 : : #endif
159 : 1872 : free( path );
160 [ - + ]: 1872 : if( result < 0 ) mhdf_setFail( status, "Failed to open element group: \"%s\"", elem_handle );
161 : 1872 : return result;
162 : : }
163 : :
164 : 1086 : int mhdf_create_scalar_attrib( hid_t object, const char* name, hid_t type, const void* value, mhdf_Status* status )
165 : : {
166 : : hid_t dspace_id, attr_id;
167 : : herr_t rval;
168 : :
169 : 1086 : dspace_id = H5Screate( H5S_SCALAR );
170 [ - + ]: 1086 : if( dspace_id < 0 )
171 : : {
172 : 0 : mhdf_setFail( status, "Internal error calling H5Screate_simple." );
173 : 0 : return 0;
174 : : }
175 : :
176 : : #if defined( H5Acreate_vers ) && H5Acreate_vers > 1
177 : 1086 : attr_id = H5Acreate2( object, name, type, dspace_id, H5P_DEFAULT, H5P_DEFAULT );
178 : : #else
179 : : attr_id = H5Acreate( object, name, type, dspace_id, H5P_DEFAULT );
180 : : #endif
181 : 1086 : H5Sclose( dspace_id );
182 [ - + ]: 1086 : if( attr_id < 0 )
183 : : {
184 : 0 : mhdf_setFail( status, "Failed to create \"%s\" attrib.", name );
185 : 0 : return 0;
186 : : }
187 : :
188 : : VALGRIND_CHECK_MEM_IS_DEFINED( value, H5Tget_size( type ) );
189 : 1086 : rval = H5Awrite( attr_id, type, value );
190 : 1086 : H5Aclose( attr_id );
191 [ - + ]: 1086 : if( rval < 0 )
192 : : {
193 : 0 : mhdf_setFail( status, "Failed to write \"%s\" attrib.", name );
194 : 0 : return 0;
195 : : }
196 : :
197 : 1086 : return 1;
198 : : }
199 : :
200 : 1704 : int mhdf_read_scalar_attrib( hid_t object, const char* name, hid_t type, void* value, mhdf_Status* status )
201 : : {
202 : : hid_t attr_id, type_id;
203 : : herr_t rval;
204 : :
205 : 1704 : attr_id = H5Aopen_name( object, name );
206 [ - + ]: 1704 : if( attr_id < 0 )
207 : : {
208 : 0 : mhdf_setFail( status, "Failed to create \"%s\" attrib.", name );
209 : 0 : return 0;
210 : : }
211 : :
212 [ + - ]: 1704 : if( type > 0 ) { type_id = type; }
213 : : else
214 : : {
215 : 0 : type_id = H5Aget_type( attr_id );
216 [ # # ]: 0 : if( type_id < 0 )
217 : : {
218 : 0 : H5Aclose( attr_id );
219 : 0 : return 0;
220 : : }
221 : : }
222 : :
223 : 1704 : rval = H5Aread( attr_id, type_id, value );
224 : 1704 : H5Aclose( attr_id );
225 [ - + ]: 1704 : if( type < 1 ) H5Tclose( type_id );
226 [ - + ]: 1704 : if( rval < 0 )
227 : : {
228 : 0 : mhdf_setFail( status, "Failed to read \"%s\" attrib.", name );
229 : 0 : return 0;
230 : : }
231 : :
232 : 1704 : return 1;
233 : : }
234 : :
235 : : #if defined( H5Aiterate_vers ) && H5Aiterate_vers > 1
236 : 17392 : static herr_t find_attr_by_name( hid_t handle, const char* name, const H5A_info_t* info, void* mydata )
237 : : {
238 : : /* empty statement to remove compiler warning */
239 : : if( info ) {}
240 : : #else
241 : : static herr_t find_attr_by_name( hid_t handle, const char* name, void* mydata )
242 : : {
243 : : #endif
244 : : /* empty statement to remove compiler warning */
245 : : if( handle ) {}
246 : 8696 : return !strcmp( name, (const char*)mydata );
247 : : }
248 : :
249 : 3882 : int mhdf_find_attribute( hid_t object, const char* attrib_name, unsigned int* index_out, mhdf_Status* status )
250 : : {
251 : : herr_t rval;
252 : : #if defined( H5Aiterate_vers ) && H5Aiterate_vers > 1
253 : 3882 : hsize_t idx = 0;
254 : 3882 : rval = H5Aiterate2( object, H5_INDEX_CRT_ORDER, H5_ITER_NATIVE, &idx, &find_attr_by_name, (void*)attrib_name );
255 : 3882 : *index_out = (unsigned int)idx;
256 : : #else
257 : : *index_out = 0;
258 : : rval = H5Aiterate( object, index_out, &find_attr_by_name, (void*)attrib_name );
259 : : #endif
260 [ - + ]: 3882 : if( rval < 0 ) mhdf_setFail( status, "Internal error calling H5Aiterate." );
261 : 3882 : return (int)rval;
262 : : }
263 : :
264 : 21416 : static herr_t find_link_by_name( hid_t handle, const char* name, void* mydata )
265 : : {
266 : : /* empty statement to remove compiler warning */
267 : : if( handle ) {}
268 : 10708 : return !strcmp( name, (const char*)mydata );
269 : : }
270 : :
271 : 6085 : int mhdf_is_in_group( hid_t group, const char* name, mhdf_Status* status )
272 : : {
273 : : int rval;
274 : 6085 : rval = H5Giterate( group, ".", NULL, &find_link_by_name, (void*)name );
275 [ - + ]: 6085 : if( rval < 0 ) mhdf_setFail( status, "Internal error in H5Giterate." );
276 : 6085 : return rval;
277 : : }
278 : :
279 : 545 : static int mhdf_readwrite( hid_t data_id, int read, long offset, long count, hid_t type, void* array, hid_t io_prop,
280 : : mhdf_Status* status )
281 : : {
282 : : hid_t slab_id, mem_id;
283 : 545 : hsize_t offsets[ 2 ], counts[ 2 ] = { 1, 1 };
284 : : herr_t rval;
285 : : int dims;
286 : : /*#if (1000 * H5_VERS_MAJOR + H5_VERS_MINOR) < 1008*/
287 : 545 : const hsize_t one = 1;
288 : : /*#endif*/
289 : :
290 [ + - ][ - + ]: 545 : if( offset < 0 || count < 0 )
291 : : {
292 [ # # ]: 0 : mhdf_setFail( status,
293 : : "Invalid input for %s: "
294 : : "offset = %ld, count = %ld\n",
295 : : read ? "read" : "write", offset, count );
296 : 0 : return 0;
297 : : }
298 : :
299 : 545 : slab_id = H5Dget_space( data_id );
300 [ - + ]: 545 : if( slab_id < 0 )
301 : : {
302 : 0 : mhdf_setFail( status, "Internal error calling H5Dget_space." );
303 : 0 : return 0;
304 : : }
305 : :
306 : 545 : dims = H5Sget_simple_extent_ndims( slab_id );
307 [ + - ][ - + ]: 545 : if( dims < 1 || dims > 2 )
308 : : {
309 : 0 : H5Sclose( slab_id );
310 : 0 : mhdf_setFail( status, "Internal error: unexpected dataset rank: %d.", dims );
311 : 0 : return 0;
312 : : }
313 : :
314 : 545 : dims = H5Sget_simple_extent_dims( slab_id, counts, NULL );
315 [ - + ]: 545 : if( dims < 0 )
316 : : {
317 : 0 : H5Sclose( slab_id );
318 : 0 : mhdf_setFail( status, "Internal error calling H5Sget_simple_extend_dims." );
319 : 0 : return 0;
320 : : }
321 : :
322 [ - + ]: 545 : if( (unsigned long)( offset + count ) > counts[ 0 ] )
323 : : {
324 : 0 : H5Sclose( slab_id );
325 [ # # ]: 0 : mhdf_setFail( status, "Requested %s of rows %ld to %ld of a %ld row table.\n", read ? "read" : "write", offset,
326 : 0 : offset + count - 1, (long)counts[ dims - 1 ] );
327 : 0 : return 0;
328 : : }
329 : :
330 : 545 : counts[ 0 ] = (hsize_t)count;
331 : 545 : offsets[ 0 ] = (hsize_t)offset;
332 : 545 : offsets[ 1 ] = 0;
333 [ + - ]: 545 : if( count )
334 : 545 : rval = H5Sselect_hyperslab( slab_id, H5S_SELECT_SET, offsets, NULL, counts, NULL );
335 : : else
336 : 0 : rval = H5Sselect_none( slab_id );
337 [ - + ]: 545 : if( rval < 0 )
338 : : {
339 : 0 : H5Sclose( slab_id );
340 : 0 : mhdf_setFail( status, "Internal error calling H5Sselect_hyperslab." );
341 : 0 : return 0;
342 : : }
343 : :
344 [ + - ]: 545 : if( count )
345 : 545 : mem_id = H5Screate_simple( dims, counts, NULL );
346 : : else
347 : : {
348 : : /*#if H5_VERS_MAJOR > 1 || H5_VERS_MINOR >= 8
349 : : mem_id = H5Screate(H5S_NULL);
350 : : #else*/
351 : 0 : mem_id = H5Screate_simple( 1, &one, NULL );
352 [ # # ][ # # ]: 0 : if( mem_id && 0 > H5Sselect_none( mem_id ) )
353 : : {
354 : 0 : H5Sclose( mem_id );
355 : 0 : mem_id = -1;
356 : : }
357 : : /*#endif*/
358 : : }
359 : :
360 [ - + ]: 545 : if( mem_id < 0 )
361 : : {
362 : 0 : H5Sclose( slab_id );
363 : 0 : mhdf_setFail( status, "Internal error calling H5Screate_simple." );
364 : 0 : return 0;
365 : : }
366 : :
367 [ + + ]: 545 : if( read )
368 : 19 : rval = H5Dread( data_id, type, mem_id, slab_id, io_prop, array );
369 : : else
370 : : {
371 : : VALGRIND_CHECK_MEM_IS_DEFINED( array, counts[ 0 ] * counts[ 1 ] * H5Tget_size( type ) );
372 : 526 : rval = H5Dwrite( data_id, type, mem_id, slab_id, io_prop, array );
373 : : }
374 : 545 : H5Sclose( slab_id );
375 : 545 : H5Sclose( mem_id );
376 [ - + ]: 545 : if( rval < 0 )
377 : : {
378 [ # # ]: 0 : mhdf_setFail( status, "Internal error calling H5D%s.", read ? "read" : "write" );
379 : 0 : return 0;
380 : : }
381 : :
382 : 545 : mhdf_setOkay( status );
383 : 545 : return 1;
384 : : }
385 : :
386 : 0 : static int mhdf_readwrite_column( hid_t data_id, int read, int column, long offset, long count, hid_t type, void* array,
387 : : hid_t io_prop, mhdf_Status* status )
388 : : {
389 : : hid_t slab_id, mem_id;
390 : : hsize_t offsets[ 2 ], counts[ 2 ];
391 : : herr_t rval;
392 : : int dims;
393 : : /*#if (1000 * H5_VERS_MAJOR + H5_VERS_MINOR) < 1008*/
394 : 0 : const hsize_t one = 1;
395 : : /*#endif*/
396 : :
397 [ # # ][ # # ]: 0 : if( column < 0 || offset < 0 || count < 0 )
[ # # ]
398 : : {
399 [ # # ]: 0 : mhdf_setFail( status,
400 : : "Invalid input for %s: "
401 : : "column = %d, offset = %ld, count = %ld\n",
402 : : read ? "read" : "write", column, offset, count );
403 : 0 : return 0;
404 : : }
405 : :
406 : 0 : slab_id = H5Dget_space( data_id );
407 [ # # ]: 0 : if( slab_id < 0 )
408 : : {
409 : 0 : mhdf_setFail( status, "Internal error calling H5Dget_space." );
410 : 0 : return 0;
411 : : }
412 : :
413 : 0 : dims = H5Sget_simple_extent_ndims( slab_id );
414 [ # # ][ # # ]: 0 : if( dims < 1 || dims > 2 )
415 : : {
416 : 0 : H5Sclose( slab_id );
417 : 0 : mhdf_setFail( status, "Internal error: unexpected dataset rank: %d.", dims );
418 : 0 : return 0;
419 : : }
420 : :
421 : 0 : dims = H5Sget_simple_extent_dims( slab_id, counts, NULL );
422 [ # # ]: 0 : if( dims < 0 )
423 : : {
424 : 0 : H5Sclose( slab_id );
425 : 0 : mhdf_setFail( status, "Internal error calling H5Sget_simple_extend_dims." );
426 : 0 : return 0;
427 : : }
428 : :
429 [ # # ][ # # ]: 0 : if( (unsigned long)( offset + count ) > counts[ 0 ] || (unsigned long)column > counts[ 1 ] )
430 : : {
431 : 0 : H5Sclose( slab_id );
432 [ # # ]: 0 : mhdf_setFail( status, "Requested %s of (%ld,%d)->(%ld,%ld) of (%ld, %ld) table.\n", read ? "read" : "write",
433 : 0 : offset, column, offset + count - 1, column, (long)counts[ 0 ], (long)counts[ 1 ] );
434 : 0 : return 0;
435 : : }
436 : :
437 : 0 : counts[ 0 ] = (hsize_t)count;
438 : 0 : offsets[ 0 ] = (hsize_t)offset;
439 : 0 : counts[ 1 ] = 1;
440 : 0 : offsets[ 1 ] = column;
441 [ # # ]: 0 : if( count )
442 : 0 : rval = H5Sselect_hyperslab( slab_id, H5S_SELECT_SET, offsets, NULL, counts, NULL );
443 : : else
444 : 0 : rval = H5Sselect_none( slab_id );
445 [ # # ]: 0 : if( rval < 0 )
446 : : {
447 : 0 : H5Sclose( slab_id );
448 : 0 : mhdf_setFail( status, "Internal error calling H5Sselect_hyperslab." );
449 : 0 : return 0;
450 : : }
451 : :
452 [ # # ]: 0 : if( count )
453 : 0 : mem_id = H5Screate_simple( dims, counts, NULL );
454 : : else
455 : : {
456 : : /*#if H5_VERS_MAJOR > 1 || H5_VERS_MINOR >= 8
457 : : mem_id = H5Screate(H5S_NULL);
458 : : #else*/
459 : 0 : mem_id = H5Screate_simple( 1, &one, NULL );
460 [ # # ][ # # ]: 0 : if( mem_id && 0 > H5Sselect_none( mem_id ) )
461 : : {
462 : 0 : H5Sclose( mem_id );
463 : 0 : mem_id = -1;
464 : : }
465 : : /*#endif*/
466 : : }
467 : :
468 [ # # ]: 0 : if( mem_id < 0 )
469 : : {
470 : 0 : H5Sclose( slab_id );
471 : 0 : mhdf_setFail( status, "Internal error calling H5Screate_simple." );
472 : 0 : return 0;
473 : : }
474 : :
475 [ # # ]: 0 : if( read )
476 : 0 : rval = H5Dread( data_id, type, mem_id, slab_id, io_prop, array );
477 : : else
478 : : {
479 : : VALGRIND_CHECK_MEM_IS_DEFINED( array, count * H5Tget_size( type ) );
480 : 0 : rval = H5Dwrite( data_id, type, mem_id, slab_id, io_prop, array );
481 : : VALGRIND_MAKE_MEM_UNDEFINED( array, count * H5Tget_size( type ) );
482 : : }
483 : 0 : H5Sclose( slab_id );
484 : 0 : H5Sclose( mem_id );
485 [ # # ]: 0 : if( rval < 0 )
486 : : {
487 [ # # ]: 0 : mhdf_setFail( status, "Internal error calling H5D%s.", read ? "read" : "write" );
488 : 0 : return 0;
489 : : }
490 : :
491 : 0 : mhdf_setOkay( status );
492 : 0 : return 1;
493 : : }
494 : :
495 : 526 : int mhdf_write_data( hid_t data_id, long offset, long count, hid_t type_id, const void* array, hid_t prop,
496 : : mhdf_Status* status )
497 : : {
498 : 526 : return mhdf_readwrite( data_id, 0, offset, count, type_id, (void*)array, prop, status );
499 : : }
500 : :
501 : 19 : int mhdf_read_data( hid_t data_id, long offset, long count, hid_t type_id, void* array, hid_t prop,
502 : : mhdf_Status* status )
503 : : {
504 : 19 : return mhdf_readwrite( data_id, 1, offset, count, type_id, array, prop, status );
505 : : }
506 : :
507 : 0 : int mhdf_read_column( hid_t data_id, int column, long offset, long count, hid_t type, void* array, hid_t prop,
508 : : mhdf_Status* status )
509 : : {
510 : 0 : return mhdf_readwrite_column( data_id, 1, column, offset, count, type, array, prop, status );
511 : : }
512 : :
513 : 0 : int mhdf_write_column( hid_t data_id, int column, long offset, long count, hid_t type, const void* array, hid_t prop,
514 : : mhdf_Status* status )
515 : : {
516 : 0 : return mhdf_readwrite_column( data_id, 0, column, offset, count, type, (void*)array, prop, status );
517 : : }
518 : :
519 : 565 : hid_t mhdf_create_table( hid_t group_id, const char* path, hid_t type, int rank, hsize_t* dims, mhdf_Status* status )
520 : : {
521 : 565 : return mhdf_create_table_with_prop( group_id, path, type, rank, dims, H5P_DEFAULT, status );
522 : : }
523 : :
524 : 565 : hid_t mhdf_create_table_with_prop( hid_t group_id, const char* path, hid_t type, int rank, hsize_t* dims,
525 : : hid_t create_prop, mhdf_Status* status )
526 : : {
527 : : hid_t space_id, table_id;
528 : :
529 : 565 : space_id = H5Screate_simple( rank, dims, NULL );
530 [ - + ]: 565 : if( space_id < 0 )
531 : : {
532 : 0 : mhdf_setFail( status, "Internal error calling H5Screate_simple." );
533 : 0 : return -1;
534 : : }
535 : :
536 : : #if defined( H5Dcreate_vers ) && H5Dcreate_vers > 1
537 : 565 : table_id = H5Dcreate2( group_id, path, type, space_id, H5P_DEFAULT, create_prop, H5P_DEFAULT );
538 : : #else
539 : : table_id = H5Dcreate( group_id, path, type, space_id, create_prop );
540 : : #endif
541 : 565 : H5Sclose( space_id );
542 [ - + ]: 565 : if( table_id < 0 )
543 : : {
544 : 0 : mhdf_setFail( status, "HDF5 DataSet creation failed." );
545 : 0 : return -1;
546 : : }
547 : :
548 : 565 : mhdf_setOkay( status );
549 : 565 : return table_id;
550 : : }
551 : :
552 : 1322 : hid_t mhdf_open_table( hid_t group_id, const char* path, int columns, hsize_t* rows_out, mhdf_Status* status )
553 : : {
554 : : hid_t table_id, space_id;
555 : : hsize_t dims[ 2 ];
556 : : int rank;
557 : :
558 : : #if defined( H5Dopen_vers ) && H5Dopen_vers > 1
559 : 1322 : table_id = H5Dopen2( group_id, path, H5P_DEFAULT );
560 : : #else
561 : : table_id = H5Dopen( group_id, path );
562 : : #endif
563 [ - + ]: 1322 : if( table_id < 0 )
564 : : {
565 : 0 : mhdf_setFail( status, "HDF5 DataSet creation failed." );
566 : 0 : return -1;
567 : : }
568 : :
569 : 1322 : space_id = H5Dget_space( table_id );
570 [ - + ]: 1322 : if( space_id < 0 )
571 : : {
572 : 0 : mhdf_setFail( status, "Internal error in H5Dget_space." );
573 : 0 : H5Dclose( table_id );
574 : 0 : return -1;
575 : : }
576 : :
577 : 1322 : rank = H5Sget_simple_extent_ndims( space_id );
578 [ + - ][ - + ]: 1322 : if( rank != ( columns ? 1 : 2 ) )
579 : : {
580 : 0 : mhdf_setFail( status, "Incorrect DataSpace for DataSet." );
581 : 0 : H5Sclose( space_id );
582 : 0 : H5Dclose( table_id );
583 : 0 : return -1;
584 : : }
585 : :
586 : 1322 : rank = H5Sget_simple_extent_dims( space_id, dims, NULL );
587 : 1322 : H5Sclose( space_id );
588 [ - + ]: 1322 : if( rank < 0 )
589 : : {
590 : 0 : mhdf_setFail( status, "Internal error calling H5Sget_simple_extent_dims." );
591 : 0 : H5Dclose( table_id );
592 : 0 : return -1;
593 : : }
594 : :
595 : 1322 : *rows_out = dims[ 0 ];
596 : 1322 : mhdf_setOkay( status );
597 : 1322 : return table_id;
598 : : }
599 : :
600 : 373 : hid_t mhdf_open_table2( hid_t group_id, const char* path, int rank, hsize_t* dims_out, long* start_id_out,
601 : : mhdf_Status* status )
602 : : {
603 : : hid_t table_id, space_id;
604 : :
605 : : #if defined( H5Dopen_vers ) && H5Dopen_vers > 1
606 : 373 : table_id = H5Dopen2( group_id, path, H5P_DEFAULT );
607 : : #else
608 : : table_id = H5Dopen( group_id, path );
609 : : #endif
610 [ - + ]: 373 : if( table_id < 0 )
611 : : {
612 : 0 : mhdf_setFail( status, "HDF5 DataSet creation failed." );
613 : 0 : return -1;
614 : : }
615 : :
616 : 373 : space_id = H5Dget_space( table_id );
617 [ - + ]: 373 : if( space_id < 0 )
618 : : {
619 : 0 : mhdf_setFail( status, "Internal error in H5Dget_space." );
620 : 0 : H5Dclose( table_id );
621 : 0 : return -1;
622 : : }
623 : :
624 [ - + ]: 373 : if( H5Sget_simple_extent_ndims( space_id ) != rank )
625 : : {
626 : 0 : mhdf_setFail( status, "Incorrect DataSpace for DataSet." );
627 : 0 : H5Sclose( space_id );
628 : 0 : H5Dclose( table_id );
629 : 0 : return -1;
630 : : }
631 : :
632 : 373 : rank = H5Sget_simple_extent_dims( space_id, dims_out, NULL );
633 : 373 : H5Sclose( space_id );
634 [ - + ]: 373 : if( rank < 0 )
635 : : {
636 : 0 : mhdf_setFail( status, "Internal error calling H5Sget_simple_extent_dims." );
637 : 0 : H5Dclose( table_id );
638 : 0 : return -1;
639 : : }
640 : :
641 [ - + ]: 373 : if( !mhdf_read_scalar_attrib( table_id, START_ID_ATTRIB, H5T_NATIVE_LONG, start_id_out, status ) )
642 : : {
643 : 0 : mhdf_setFail( status, "File format error. Failed to retreive ID offset." );
644 : 0 : H5Dclose( table_id );
645 : 0 : return -1;
646 : : }
647 : :
648 : 373 : mhdf_setOkay( status );
649 : 373 : return table_id;
650 : : }
651 : :
652 : 236 : hid_t mhdf_open_table_simple( hid_t group_id, const char* path, mhdf_Status* status )
653 : : {
654 : : hid_t table_id;
655 : :
656 : : #if defined( H5Dopen_vers ) && H5Dopen_vers > 1
657 : 236 : table_id = H5Dopen2( group_id, path, H5P_DEFAULT );
658 : : #else
659 : : table_id = H5Dopen( group_id, path );
660 : : #endif
661 [ - + ]: 236 : if( table_id < 0 ) { mhdf_setFail( status, "HDF5 DataSet creation failed." ); }
662 : : else
663 : : {
664 : 236 : mhdf_setOkay( status );
665 : : }
666 : :
667 : 236 : return table_id;
668 : : }
669 : :
670 : 0 : static int qs_comp_int( const void* ptr1, const void* ptr2 )
671 : : {
672 : 0 : const int* left = (const int*)ptr1;
673 : 0 : const int* right = (const int*)ptr2;
674 [ # # ]: 0 : return *left < *right ? -1 : *left > *right ? 1 : 0;
675 : : }
676 : :
677 : 0 : int mhdf_compact_to_ranges( int* length, int* ids, int ordered )
678 : : {
679 : 0 : int new_length = 0;
680 : : int * iter, *end;
681 : : int prev, count;
682 : 0 : int need_copy = 0;
683 : 0 : int * copy_ptr = 0, *w_iter;
684 : : size_t blen;
685 : :
686 [ # # ]: 0 : if( !ordered ) qsort( ids, *length, sizeof( int ), &qs_comp_int );
687 : :
688 : 0 : iter = ids;
689 : 0 : end = ids + *length;
690 [ # # ]: 0 : while( iter != end )
691 : : {
692 : 0 : prev = *( iter++ );
693 [ # # ][ # # ]: 0 : while( iter < end && *( iter++ ) == ++prev )
694 : : ;
695 : 0 : new_length += 2;
696 [ # # ]: 0 : if( new_length > ( iter - ids ) ) need_copy = 1;
697 : : }
698 : :
699 [ # # ]: 0 : if( new_length > *length ) return 0;
700 : :
701 [ # # ]: 0 : if( need_copy )
702 : : {
703 : 0 : blen = sizeof( int ) * *length;
704 : 0 : copy_ptr = (int*)malloc( blen );
705 : 0 : memcpy( copy_ptr, ids, blen );
706 : 0 : iter = copy_ptr;
707 : : }
708 : : else
709 : : {
710 : 0 : iter = ids;
711 : : }
712 : :
713 : 0 : end = iter + *length;
714 : 0 : w_iter = ids;
715 [ # # ]: 0 : while( iter != end )
716 : : {
717 : 0 : prev = *( iter++ );
718 : 0 : count = 1;
719 [ # # ][ # # ]: 0 : while( iter < end && *( iter++ ) == ++prev )
720 : : ;
721 : 0 : *( w_iter++ ) = prev - count;
722 : 0 : *( w_iter++ ) = count;
723 : : }
724 : :
725 : 0 : *length = new_length;
726 [ # # ]: 0 : if( need_copy ) free( copy_ptr );
727 : 0 : return 1;
728 : : }
729 : :
730 : 52 : hid_t get_elem_type_enum( FileHandle* file_ptr, mhdf_Status* status )
731 : : {
732 : : hid_t result;
733 : : #if defined( H5Topen_vers ) && H5Topen_vers > 1
734 : 52 : result = H5Topen2( file_ptr->hdf_handle, TYPE_ENUM_PATH, H5P_DEFAULT );
735 : : #else
736 : : result = H5Topen( file_ptr->hdf_handle, TYPE_ENUM_PATH );
737 : : #endif
738 [ - + ]: 52 : if( result < 0 ) mhdf_setFail( status, "Element type enum does not exist in file. Invalid file." );
739 : 52 : return result;
740 : : }
741 : :
742 : 129 : int mhdf_write_max_id( FileHandle* file_ptr, mhdf_Status* status )
743 : : {
744 : : hid_t group_id, attr_id, space_id;
745 : : herr_t rval;
746 : :
747 : : #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
748 : 129 : group_id = H5Gopen2( file_ptr->hdf_handle, ROOT_GROUP, H5P_DEFAULT );
749 : : #else
750 : : group_id = H5Gopen( file_ptr->hdf_handle, ROOT_GROUP );
751 : : #endif
752 [ - + ]: 129 : if( group_id < 0 )
753 : : {
754 : 0 : mhdf_setFail( status, "Internal error -- file invalid." );
755 : 0 : return 0;
756 : : }
757 : :
758 : 129 : attr_id = H5Aopen_name( group_id, MAX_ID_ATTRIB );
759 [ - + ]: 129 : if( attr_id < 0 )
760 : : {
761 : 0 : space_id = H5Screate( H5S_SCALAR );
762 : : #if defined( H5Acreate_vers ) && H5Acreate_vers > 1
763 : 0 : attr_id = H5Acreate2( group_id, MAX_ID_ATTRIB, H5T_NATIVE_ULONG, space_id, H5P_DEFAULT, H5P_DEFAULT );
764 : : #else
765 : : attr_id = H5Acreate( group_id, MAX_ID_ATTRIB, H5T_NATIVE_ULONG, space_id, H5P_DEFAULT );
766 : : #endif
767 : 0 : H5Sclose( space_id );
768 : : }
769 : 129 : H5Gclose( group_id );
770 [ - + ]: 129 : if( attr_id < 0 )
771 : : {
772 : 0 : mhdf_setFail( status, "Failed to create attribute \"%s\" on \"%s\"", MAX_ID_ATTRIB, ROOT_GROUP );
773 : 0 : return 0;
774 : : }
775 : :
776 : 129 : rval = H5Awrite( attr_id, H5T_NATIVE_ULONG, &file_ptr->max_id );
777 : 129 : H5Aclose( attr_id );
778 [ - + ]: 129 : if( rval < 0 )
779 : : {
780 : 0 : mhdf_setFail( status, "Failed to write \"%s\" attrib.", MAX_ID_ATTRIB );
781 : 0 : return 0;
782 : : }
783 : :
784 : 129 : return 1;
785 : : }
786 : :
787 : : static int mhdf_api_handle_count = 0;
788 : :
789 : 0 : static int num_open( )
790 : : {
791 : : hid_t list[ 64 ];
792 : 0 : int nf, rval, i, count = 0;
793 : :
794 : 0 : nf = H5Fget_obj_ids( H5F_OBJ_ALL, H5F_OBJ_FILE, sizeof( list ) / sizeof( hid_t ), list );
795 [ # # ][ # # ]: 0 : if( nf <= 0 || nf > 64 ) return 0;
796 : :
797 [ # # ]: 0 : for( i = 0; i < nf; i++ )
798 : : {
799 : 0 : rval = H5Fget_obj_count( list[ i ], H5F_OBJ_ALL );
800 [ # # ]: 0 : if( rval > 0 ) count += rval;
801 : : }
802 : :
803 : 0 : return count;
804 : : }
805 : :
806 : 0 : void mhdf_api_begin_internal( )
807 : : {
808 : : /* HDF5 docs are incorrect. Passing H5F_OBJ_ALL as the first
809 : : arg to H5Fget_obj_count returns the total number of open
810 : : handles, not just those in files (i.e. temporary types and such.)
811 : : mhdf_api_handle_count = H5Fget_obj_count( H5F_OBJ_ALL, H5F_OBJ_ALL );
812 : : Need to loop to get actual file handles:
813 : : */
814 : 0 : mhdf_api_handle_count = num_open( );
815 : 0 : }
816 : :
817 : 0 : void mhdf_api_end_internal( int expected_diff, const char* filename, int linenumber )
818 : : {
819 [ # # ]: 0 : if( mhdf_api_handle_count + expected_diff != num_open( ) )
820 : : {
821 : 0 : fprintf( stderr, "Unclosed handles at end of mhdf API call.\n" );
822 : 0 : fprintf( stderr, "Entered with %d, expected %d change, got %d.\n", mhdf_api_handle_count, expected_diff,
823 : : num_open( ) );
824 : 0 : fprintf( stderr, "%s:%d\n", filename, linenumber );
825 : 0 : abort( );
826 : : }
827 : :
828 : 0 : mhdf_api_handle_count = 0;
829 : 0 : }
|