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 files COPYING and Copyright.html.  COPYING can be found at the root   *
9  * of the source code distribution tree; Copyright.html can be found at the  *
10  * root level of an installed copy of the electronic HDF5 document set and   *
11  * is linked from the top-level documents page.  It can also be found at     *
12  * http://hdfgroup.org/HDF5/doc/Copyright.html.  If you do not have          *
13  * access to either file, you may request a copy from help@hdfgroup.org.     *
14  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /*
17  * Module Info: This module contains the functionality for compound datatypes
18  *      in the H5T interface.
19  */
20 
21 /****************/
22 /* Module Setup */
23 /****************/
24 
25 #define H5T_PACKAGE		/*suppress error about including H5Tpkg	  */
26 
27 /* Interface initialization */
28 #define H5_INTERFACE_INIT_FUNC	H5T_init_compound_interface
29 
30 
31 /***********/
32 /* Headers */
33 /***********/
34 #include "H5private.h"		/*generic functions			  */
35 #include "H5Eprivate.h"		/*error handling			  */
36 #include "H5Iprivate.h"		/*ID functions		   		  */
37 #include "H5MMprivate.h"	/*memory management			  */
38 #include "H5Tpkg.h"		/*data-type functions			  */
39 
40 /****************/
41 /* Local Macros */
42 /****************/
43 
44 
45 /******************/
46 /* Local Typedefs */
47 /******************/
48 
49 
50 /********************/
51 /* Package Typedefs */
52 /********************/
53 
54 
55 /********************/
56 /* Local Prototypes */
57 /********************/
58 static herr_t H5T_pack(const H5T_t *dt);
59 static htri_t H5T_is_packed(const H5T_t *dt);
60 
61 
62 /*********************/
63 /* Public Variables */
64 /*********************/
65 
66 
67 /*********************/
68 /* Package Variables */
69 /*********************/
70 
71 
72 /*****************************/
73 /* Library Private Variables */
74 /*****************************/
75 
76 
77 /*******************/
78 /* Local Variables */
79 /*******************/
80 
81 
82 
83 /*--------------------------------------------------------------------------
84 NAME
85    H5T_init_compound_interface -- Initialize interface-specific information
86 USAGE
87     herr_t H5T_init_compound_interface()
88 RETURNS
89     Non-negative on success/Negative on failure
90 DESCRIPTION
91     Initializes any interface-specific data or routines.  (Just calls
92     H5T_init() currently).
93 --------------------------------------------------------------------------*/
94 static herr_t
H5T_init_compound_interface(void)95 H5T_init_compound_interface(void)
96 {
97     FUNC_ENTER_NOAPI_NOINIT_NOERR
98 
99     FUNC_LEAVE_NOAPI(H5T_init())
100 } /* H5T_init_compound_interface() */
101 
102 
103 /*-------------------------------------------------------------------------
104  * Function:	H5Tget_member_offset
105  *
106  * Purpose:	Returns the byte offset of the beginning of a member with
107  *		respect to the beginning of the compound datatype datum.
108  *
109  * Return:	Success:	Byte offset.
110  *
111  *		Failure:	Zero. Zero is a valid offset, but this
112  *				function will fail only if a call to
113  *				H5Tget_member_dims() fails with the same
114  *				arguments.
115  *
116  * Programmer:	Robb Matzke
117  *		Wednesday, January  7, 1998
118  *
119  * Modifications:
120  *
121  *-------------------------------------------------------------------------
122  */
123 size_t
H5Tget_member_offset(hid_t type_id,unsigned membno)124 H5Tget_member_offset(hid_t type_id, unsigned membno)
125 {
126     H5T_t	*dt;            /* Datatype to query */
127     size_t	ret_value;      /* Return value */
128 
129     FUNC_ENTER_API(0)
130     H5TRACE2("z", "iIu", type_id, membno);
131 
132     /* Check args */
133     if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)) || H5T_COMPOUND != dt->shared->type)
134 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a compound datatype")
135     if(membno >= dt->shared->u.compnd.nmembs)
136 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid member number")
137 
138     /* Value */
139     ret_value = H5T_GET_MEMBER_OFFSET(dt->shared, membno);
140 
141 done:
142     FUNC_LEAVE_API(ret_value)
143 } /* end H5Tget_member_offset() */
144 
145 
146 /*-------------------------------------------------------------------------
147  * Function:	H5T_get_member_offset
148  *
149  * Purpose:	Private function for H5Tget_member_offset.  Returns the byte
150  *              offset of the beginning of a member with respect to the
151  *              beginning of the compound datatype datum.
152  *
153  * Return:	Success:	Byte offset.
154  *
155  *		Failure:	Zero. Zero is a valid offset, but this
156  *				function will fail only if a call to
157  *				H5Tget_member_dims() fails with the same
158  *				arguments.
159  *
160  * Programmer:	Raymond Lu
161  *		October 8, 2002
162  *
163  *-------------------------------------------------------------------------
164  */
165 size_t
H5T_get_member_offset(const H5T_t * dt,unsigned membno)166 H5T_get_member_offset(const H5T_t *dt, unsigned membno)
167 {
168     FUNC_ENTER_NOAPI_NOINIT_NOERR
169 
170     HDassert(dt);
171     HDassert(membno < dt->shared->u.compnd.nmembs);
172 
173     FUNC_LEAVE_NOAPI(dt->shared->u.compnd.memb[membno].offset)
174 } /* end H5T_get_member_offset() */
175 
176 
177 /*-------------------------------------------------------------------------
178  * Function:	H5Tget_member_class
179  *
180  * Purpose:	Returns the datatype class of a member of a compound datatype.
181  *
182  * Return:	Success: Non-negative
183  *
184  *		Failure: H5T_NO_CLASS
185  *
186  * Programmer:	Quincey Koziol
187  *		Thursday, November  9, 2000
188  *
189  * Modifications:
190  *
191  *-------------------------------------------------------------------------
192  */
193 H5T_class_t
H5Tget_member_class(hid_t type_id,unsigned membno)194 H5Tget_member_class(hid_t type_id, unsigned membno)
195 {
196     H5T_t	*dt;            /* Datatype to query */
197     H5T_class_t	ret_value;      /* Return value */
198 
199     FUNC_ENTER_API(H5T_NO_CLASS)
200     H5TRACE2("Tt", "iIu", type_id, membno);
201 
202     /* Check args */
203     if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)) || H5T_COMPOUND != dt->shared->type)
204         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5T_NO_CLASS, "not a compound datatype")
205     if(membno >= dt->shared->u.compnd.nmembs)
206         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5T_NO_CLASS, "invalid member number")
207 
208     /* Get the type's class.  We have to use this function to get type class
209      *  because of the concern of variable-length string.
210      */
211     ret_value = H5T_GET_CLASS(dt->shared->u.compnd.memb[membno].type->shared, FALSE);
212 
213 done:
214     FUNC_LEAVE_API(ret_value)
215 } /* end H5Tget_member_class() */
216 
217 
218 /*-------------------------------------------------------------------------
219  * Function:	H5Tget_member_type
220  *
221  * Purpose:	Returns the datatype of the specified member.	The caller
222  *		should invoke H5Tclose() to release resources associated with
223  *		the type.
224  *
225  * Return:	Success:	An OID of a copy of the member datatype;
226  *				modifying the returned datatype does not
227  *				modify the member type.
228  *
229  *		Failure:	Negative
230  *
231  * Programmer:	Robb Matzke
232  *		Wednesday, January  7, 1998
233  *
234  *-------------------------------------------------------------------------
235  */
236 hid_t
H5Tget_member_type(hid_t type_id,unsigned membno)237 H5Tget_member_type(hid_t type_id, unsigned membno)
238 {
239     H5T_t	*dt;                    /* Datatype to query */
240     H5T_t	*memb_dt = NULL;        /* Member datatype */
241     hid_t	ret_value;              /* Return value */
242 
243     FUNC_ENTER_API(FAIL)
244     H5TRACE2("i", "iIu", type_id, membno);
245 
246     /* Check args */
247     if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)) || H5T_COMPOUND != dt->shared->type)
248 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound datatype")
249     if(membno >= dt->shared->u.compnd.nmembs)
250 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid member number")
251     if(NULL == (memb_dt = H5T_get_member_type(dt, membno, H5T_COPY_REOPEN)))
252 	HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to retrieve member type")
253     if((ret_value = H5I_register(H5I_DATATYPE, memb_dt, TRUE)) < 0)
254 	HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable register datatype atom")
255 
256 done:
257     if(ret_value < 0)
258         if(memb_dt && H5T_close(memb_dt) < 0)
259             HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "can't close datatype")
260 
261     FUNC_LEAVE_API(ret_value)
262 } /* end H5Tget_member_type() */
263 
264 
265 /*-------------------------------------------------------------------------
266  * Function:	H5T_get_member_type
267  *
268  * Purpose:	Private function for H5Tget_member_type.  Returns the data
269  *              type of the specified member.
270  *
271  * Return:	Success:	A copy of the member datatype;
272  *				modifying the returned datatype does not
273  *				modify the member type.
274  *
275  *		Failure:        NULL
276  *
277  * Programmer:	Raymond Lu
278  *	        October 8, 2002
279  *
280  *-------------------------------------------------------------------------
281  */
282 H5T_t *
H5T_get_member_type(const H5T_t * dt,unsigned membno,H5T_copy_t method)283 H5T_get_member_type(const H5T_t *dt, unsigned membno, H5T_copy_t method)
284 {
285     H5T_t	*ret_value;     /* Return value */
286 
287     FUNC_ENTER_NOAPI(NULL)
288 
289     HDassert(dt);
290     HDassert(membno < dt->shared->u.compnd.nmembs);
291 
292     /* Copy datatype into an atom */
293     if(NULL == (ret_value = H5T_copy(dt->shared->u.compnd.memb[membno].type, method)))
294 	HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy member datatype")
295 
296 done:
297     FUNC_LEAVE_NOAPI(ret_value)
298 } /* end H5T_get_member_type() */
299 
300 
301 /*-------------------------------------------------------------------------
302  * Function:	H5T__get_member_size
303  *
304  * Purpose:	Returns the size of the specified member.
305  *
306  * Return:	Success:	The size in bytes of the member's datatype.
307  *		Failure:        0
308  *
309  * Programmer:	Quincey Koziol
310  *	        October 4, 2004
311  *
312  *-------------------------------------------------------------------------
313  */
314 size_t
H5T__get_member_size(const H5T_t * dt,unsigned membno)315 H5T__get_member_size(const H5T_t *dt, unsigned membno)
316 {
317     FUNC_ENTER_PACKAGE_NOERR
318 
319     HDassert(dt);
320     HDassert(membno < dt->shared->u.compnd.nmembs);
321 
322     FUNC_LEAVE_NOAPI(dt->shared->u.compnd.memb[membno].type->shared->size)
323 } /* end H5T__get_member_size() */
324 
325 
326 /*-------------------------------------------------------------------------
327  * Function:	H5Tinsert
328  *
329  * Purpose:	Adds another member to the compound datatype PARENT_ID.  The
330  *		new member has a NAME which must be unique within the
331  *		compound datatype. The OFFSET argument defines the start of
332  *		the member in an instance of the compound datatype, and
333  *		MEMBER_ID is the type of the new member.
334  *
335  * Return:	Success:	Non-negative, the PARENT_ID compound data
336  *				type is modified to include a copy of the
337  *				member type MEMBER_ID.
338  *
339  *		Failure:	Negative
340  *
341  * Errors:
342  *
343  * Programmer:	Robb Matzke
344  *		Monday, December  8, 1997
345  *
346  * Modifications:
347  *
348  *-------------------------------------------------------------------------
349  */
350 herr_t
H5Tinsert(hid_t parent_id,const char * name,size_t offset,hid_t member_id)351 H5Tinsert(hid_t parent_id, const char *name, size_t offset, hid_t member_id)
352 {
353     H5T_t	*parent;		/* The compound parent datatype */
354     H5T_t	*member;		/* The member datatype	*/
355     herr_t      ret_value = SUCCEED;    /* Return value */
356 
357     FUNC_ENTER_API(FAIL)
358     H5TRACE4("e", "i*szi", parent_id, name, offset, member_id);
359 
360     /* Check args */
361     if(parent_id == member_id)
362 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "can't insert compound datatype within itself")
363     if(NULL == (parent = (H5T_t *)H5I_object_verify(parent_id, H5I_DATATYPE)) || H5T_COMPOUND != parent->shared->type)
364 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound datatype")
365     if(H5T_STATE_TRANSIENT != parent->shared->state)
366 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent type read-only")
367     if(!name || !*name)
368 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no member name")
369     if(NULL == (member = (H5T_t *)H5I_object_verify(member_id, H5I_DATATYPE)))
370 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
371 
372     /* Insert */
373     if(H5T__insert(parent, name, offset, member) < 0)
374         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "unable to insert member")
375 
376 done:
377     FUNC_LEAVE_API(ret_value)
378 } /* end H5Tinsert() */
379 
380 
381 /*-------------------------------------------------------------------------
382  * Function:	H5Tpack
383  *
384  * Purpose:	Recursively removes padding from within a compound datatype
385  *		to make it more efficient (space-wise) to store that data.
386  *
387  * Return:	Non-negative on success/Negative on failure
388  *
389  * Programmer:	Robb Matzke
390  *		Wednesday, January  7, 1998
391  *
392  * Modifications:
393  *
394  *-------------------------------------------------------------------------
395  */
396 herr_t
H5Tpack(hid_t type_id)397 H5Tpack(hid_t type_id)
398 {
399     H5T_t	*dt;                    /* Datatype to modify */
400     herr_t      ret_value = SUCCEED;    /* Return value */
401 
402     FUNC_ENTER_API(FAIL)
403     H5TRACE1("e", "i", type_id);
404 
405     /* Check args */
406     if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)) || H5T_detect_class(dt, H5T_COMPOUND, TRUE) <= 0)
407 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a compound datatype")
408 
409     /* Pack */
410     if(H5T_pack(dt) < 0)
411 	HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack compound datatype")
412 
413 done:
414     FUNC_LEAVE_API(ret_value)
415 } /* end H5Tpack() */
416 
417 
418 /*-------------------------------------------------------------------------
419  * Function:	H5T__insert
420  *
421  * Purpose:	Adds a new MEMBER to the compound datatype PARENT.  The new
422  *		member will have a NAME that is unique within PARENT and an
423  *		instance of PARENT will have the member begin at byte offset
424  *		OFFSET from the beginning.
425  *
426  * Return:	Non-negative on success/Negative on failure
427  *
428  * Programmer:	Robb Matzke
429  *		Monday, December  8, 1997
430  *
431  *-------------------------------------------------------------------------
432  */
433 herr_t
H5T__insert(H5T_t * parent,const char * name,size_t offset,const H5T_t * member)434 H5T__insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member)
435 {
436     unsigned	idx;                        /* Index of member to insert */
437     size_t	total_size;
438     unsigned	i;                          /* Local index variable */
439     herr_t      ret_value = SUCCEED;        /* Return value */
440 
441     FUNC_ENTER_PACKAGE
442 
443     /* check args */
444     HDassert(parent && H5T_COMPOUND == parent->shared->type);
445     HDassert(H5T_STATE_TRANSIENT == parent->shared->state);
446     HDassert(member);
447     HDassert(name && *name);
448 
449     /* Does NAME already exist in PARENT? */
450     for(i = 0; i < parent->shared->u.compnd.nmembs; i++)
451 	if(!HDstrcmp(parent->shared->u.compnd.memb[i].name, name))
452 	    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member name is not unique")
453 
454     /* Does the new member overlap any existing member ? */
455     total_size = member->shared->size;
456     for(i = 0; i < parent->shared->u.compnd.nmembs; i++)
457         if((offset <= parent->shared->u.compnd.memb[i].offset &&
458                  (offset + total_size) > parent->shared->u.compnd.memb[i].offset) ||
459                 (parent->shared->u.compnd.memb[i].offset <= offset &&
460                  (parent->shared->u.compnd.memb[i].offset +
461                  parent->shared->u.compnd.memb[i].size) > offset))
462             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member overlaps with another member")
463 
464     /* Does the new member overlap the end of the compound type? */
465     if((offset + total_size) > parent->shared->size)
466         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "member extends past end of compound type")
467 
468     /* Increase member array if necessary */
469     if(parent->shared->u.compnd.nmembs >= parent->shared->u.compnd.nalloc) {
470         unsigned na = MAX(1, parent->shared->u.compnd.nalloc * 2);
471         H5T_cmemb_t *x = (H5T_cmemb_t *)H5MM_realloc(parent->shared->u.compnd.memb, na * sizeof(H5T_cmemb_t));
472 
473         if(!x)
474             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "memory allocation failed")
475         parent->shared->u.compnd.nalloc = na;
476         parent->shared->u.compnd.memb = x;
477     } /* end if */
478 
479     /* Add member to end of member array */
480     idx = parent->shared->u.compnd.nmembs;
481     parent->shared->u.compnd.memb[idx].name = H5MM_xstrdup(name);
482     parent->shared->u.compnd.memb[idx].offset = offset;
483     parent->shared->u.compnd.memb[idx].size = total_size;
484     parent->shared->u.compnd.memb[idx].type = H5T_copy(member, H5T_COPY_ALL);
485 
486     parent->shared->u.compnd.sorted = H5T_SORT_NONE;
487     parent->shared->u.compnd.nmembs++;
488     parent->shared->u.compnd.memb_size+=total_size;
489 
490     /* It should not be possible to get this far if the type is already packed
491      * - the new member would overlap something */
492     HDassert(!(parent->shared->u.compnd.packed));
493 
494     /* Determine if the compound datatype becomes packed */
495     H5T__update_packed(parent);
496 
497     /* Set the "force conversion" flag if the field's datatype indicates */
498     if(member->shared->force_conv == TRUE)
499         parent->shared->force_conv = TRUE;
500 
501     /* Check for member having a later version than the parent */
502     if(parent->shared->version < member->shared->version)
503         /* Upgrade parent datatype (and all other members also) */
504         /* (can't use a partial datatype and later versions of the format are
505          *  more efficient, so might as well upgrade all members also... -QAK)
506          */
507         if(H5T__upgrade_version(parent, member->shared->version) < 0)
508 	    HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't upgrade member encoding version")
509 
510 done:
511     FUNC_LEAVE_NOAPI(ret_value)
512 } /* end H5T__insert() */
513 
514 
515 /*-------------------------------------------------------------------------
516  * Function:	H5T_pack
517  *
518  * Purpose:	Recursively packs a compound datatype by removing padding
519  *		bytes. This is done in place (that is, destructively).
520  *
521  * Return:	Non-negative on success/Negative on failure
522  *
523  * Programmer:	Robb Matzke
524  *		Wednesday, January  7, 1998
525  *
526  *-------------------------------------------------------------------------
527  */
528 static herr_t
H5T_pack(const H5T_t * dt)529 H5T_pack(const H5T_t *dt)
530 {
531     herr_t      ret_value = SUCCEED;    /* Return value */
532 
533     FUNC_ENTER_NOAPI_NOINIT
534 
535     HDassert(dt);
536 
537     if(H5T_detect_class(dt, H5T_COMPOUND, FALSE) > 0) {
538         /* If datatype has been packed, skip packing it and indicate success */
539         if(TRUE == H5T_is_packed(dt))
540             HGOTO_DONE(SUCCEED)
541 
542         /* Check for packing unmodifiable datatype */
543         if(H5T_STATE_TRANSIENT != dt->shared->state)
544             HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "datatype is read-only")
545 
546         if(dt->shared->parent) {
547             if (H5T_pack(dt->shared->parent) < 0)
548                 HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack parent of datatype")
549 
550             /* Adjust size of datatype appropriately */
551             if(dt->shared->type == H5T_ARRAY)
552                 dt->shared->size = dt->shared->parent->shared->size * dt->shared->u.array.nelem;
553             else if(dt->shared->type != H5T_VLEN)
554                 dt->shared->size = dt->shared->parent->shared->size;
555         } /* end if */
556         else if(dt->shared->type == H5T_COMPOUND) {
557             size_t	offset;                 /* Offset of member */
558             unsigned i;                     /* Local index variable */
559 
560             /* Recursively pack the members */
561             for(i = 0; i < dt->shared->u.compnd.nmembs; i++) {
562                 if(H5T_pack(dt->shared->u.compnd.memb[i].type) < 0)
563                     HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to pack part of a compound datatype")
564 
565                 /* Update the member size */
566                 dt->shared->u.compnd.memb[i].size = (dt->shared->u.compnd.memb[i].type)->shared->size;
567             } /* end for */
568 
569             /* Remove padding between members */
570             if(H5T__sort_value(dt, NULL) < 0)
571 		HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOMPARE, FAIL, "value sort failed")
572             for(i = 0, offset = 0; i < dt->shared->u.compnd.nmembs; i++) {
573                 dt->shared->u.compnd.memb[i].offset = offset;
574                 offset += dt->shared->u.compnd.memb[i].size;
575             }
576 
577             /* Change total size */
578             dt->shared->size = MAX(1, offset);
579 
580             /* Mark the type as packed now */
581             dt->shared->u.compnd.packed = TRUE;
582         } /* end if */
583     } /* end if */
584 
585 done:
586     FUNC_LEAVE_NOAPI(ret_value)
587 } /* end H5T_pack() */
588 
589 
590 /*-------------------------------------------------------------------------
591  * Function:	H5T_is_packed
592  *
593  * Purpose:	Checks whether a datatype which is compound (or has compound
594  *              components) is packed.
595  *
596  * Return:	Non-negative on success/Negative on failure
597  *
598  * Programmer:	Quincey Koziol
599  *		Thursday, September 11, 2003
600  *
601  * Modifications:
602  *
603  *-------------------------------------------------------------------------
604  */
605 static htri_t
H5T_is_packed(const H5T_t * dt)606 H5T_is_packed(const H5T_t *dt)
607 {
608     htri_t      ret_value = TRUE;       /* Return value */
609 
610     FUNC_ENTER_NOAPI_NOINIT_NOERR
611 
612     HDassert(dt);
613 
614     /* Go up the chain as far as possible */
615     while(dt->shared->parent)
616         dt = dt->shared->parent;
617 
618     /* If this is a compound datatype, check if it is packed */
619     if(dt->shared->type == H5T_COMPOUND) {
620         ret_value = (htri_t)(dt->shared->u.compnd.packed);
621     } /* end if */
622 
623     FUNC_LEAVE_NOAPI(ret_value)
624 } /* end H5T_is_packed() */
625 
626 
627 /*-------------------------------------------------------------------------
628  * Function:	H5T__update_packed
629  *
630  * Purpose:	Checks whether a datatype which is compound became packed
631  *              after recent changes.  This function does not assume that
632  *              the status of the "packed" field is correct, and sets
633  *              this field to the correct value.
634  *
635  * Return:	void
636  *
637  * Programmer:	Neil Fortner
638  *		Monday, October 19, 2009
639  *
640  * Modifications:
641  *
642  *-------------------------------------------------------------------------
643  */
644 void
H5T__update_packed(const H5T_t * dt)645 H5T__update_packed(const H5T_t *dt)
646 {
647     unsigned    i;                      /* Index */
648 
649     FUNC_ENTER_PACKAGE_NOERR
650 
651     HDassert(dt);
652     HDassert(dt->shared->type == H5T_COMPOUND);
653 
654     /* First check if all space is used in the "top level" type */
655     if(dt->shared->size == dt->shared->u.compnd.memb_size) {
656         /* Set the packed flag to TRUE */
657         dt->shared->u.compnd.packed = TRUE;
658 
659         /* Now check if all members are packed */
660         for(i = 0; i < dt->shared->u.compnd.nmembs; i++)
661             if(!H5T_is_packed(dt->shared->u.compnd.memb[i].type)) {
662                 dt->shared->u.compnd.packed = FALSE;
663                 break;
664             } /* end if */
665     } /* end if */
666     else
667         dt->shared->u.compnd.packed = FALSE;
668 
669     FUNC_LEAVE_NOAPI_VOID
670 } /* end H5T__update_packed() */
671 
672