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