1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * All rights reserved.                                                      *
4  *                                                                           *
5  * This file is part of HDF.  The full HDF copyright notice, including       *
6  * terms governing use, modification, and redistribution, is contained in    *
7  * the COPYING file, which can be found at the root of the source code       *
8  * distribution tree, or in https://support.hdfgroup.org/ftp/HDF/releases/.  *
9  * If you do not have access to either file, you may request a copy from     *
10  * help@hdfgroup.org.                                                        *
11  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12 
13 /* NOTE: this file and other "datainfo" related files will be configured so
14          that this feature will not be built by default. -BMR
15    Update: THG and NASA had decided to include all features developed for the
16            HDF Mapping Project in the library -BMR (~Jan 2011) */
17 
18 /**********************************************************************
19 FILE
20   hdatainfo.c
21   HDF data information routines - added to support the HDF4 Mapping project
22 
23   This file contains the multi-file HDF interface functions that provide
24   information about location and size of raw data.  This type of information
25   will allow applications to extract raw data from an HDF file without the
26   use of HDF4 library.  These features were developed to support the HDF4
27   Mapping project (2010-2011.)
28 
29   As with the rest of the functions in the APIs, these functions have names
30   beginning with VG, VS, GR, and AN, appropriately.
31 
32 EXPORTED ROUTINES
33 -----------------
34   VSgetdatainfo    -- retrieves offset(s) and length(s) of a vdata's data
35   GRgetdatainfo    -- retrieves offset(s) and length(s) of an image's data
36   VSgetattdatainfo -- retrieves offset and length of a vdata attribute's data
37   Vgetattdatainfo  -- retrieves offset and length of a vgroup attribute's data
38   GRgetattdatainfo -- retrieves offset and length of an image attribute's data
39   ANgetdatainfo    -- retrieves offset and length of an annotation's data
40 
41 LOW-LEVEL ROUTINES
42 ------------------
43   HDgetdatainfo -- retrieves offset(s) and length(s) of the data in a data element
44 
45 **********************************************************************/
46 
47 #ifndef MFGR_MASTER
48 #define MFGR_MASTER	/* for GRgetdatainfo and GRgetattdatainfo */
49 #endif			/* mfgr.h had been included in hdf.h */
50 
51 #ifndef MFAN_MASTER
52 #define MFAN_MASTER	/* for ANgetdatainfo */
53 #endif			/* mfan.h is included here */
54 
55 #include "hdf.h"
56 #include "hlimits.h"
57 #include "vgint.h"
58 #include "mfan.h"
59 
60 #ifdef H4_HAVE_LIBSZ	/* we have the szip library */
61 #include "szlib.h"
62 #endif
63 
64 
65 /*-----------------------------------------------------------------------------
66  NAME
67     HDgetdatainfo -- Retrieves offset(s) and length(s) of the data in a
68 		     data element.
69  USAGE
70     intn HDgetdatainfo(file_id, tag, ref, start_block, info_count,
71 			 *offsetarray, *lengtharray)
72 	int32  file_id		IN: file id
73 	uint16 tag		IN: tag of the element
74 	uint16 ref		IN: ref of element
75 	int32 *chk_coord	IN: chunk's coordinates or NULL if not chunked
76 	uintn  start_block	IN: data block to start at, 0 base
77 	uintn  info_count	IN: number of info records
78 	int32 *offsetarray	OUT: array to hold offsets
79 	int32 *lengtharray	OUT: array to hold lengths
80  RETURNS
81     Number of data blocks if successful, or FAIL, otherwise.
82 
83  DESCRIPTION
84     HDgetdatainfo will use low-level functions to get data information
85     of element that is in chunk or linked-block storage.
86 
87     If the given tag/ref point to:
88     - no data then the function will return 0 for number of data blocks,
89     - actual data written then the function will return 1 for number of
90       data blocks and its offset/length if they are requested, or
91     - description record, which means this element is special, then the
92       function will act appropriately depend upon the specialness
93       + compression
94 	* if the compressed data is stored in one block, the function will
95           return 1 and the offset/length if they are requested
96 	* if the compressed data is stored in linked-blocks,
97 	  > read the linked-block special header info
98 	  > call HLgetdatainfo to get data info of the blocks
99       + chunking
100 	* call HMCgetdatainfo to get data info of the requested chunk
101       + linked-block
102 	* read the linked-block special header info
103 	* call HLgetdatainfo to get data info of the blocks
104 
105  NOTES
106     Aug 17, 2010: Tested with SDgetdatainfo and VSgetdatainfo -BMR
107     Sep 7, 2010: Tested with GRgetdatainfo, but not linked-block yet -BMR
108     Oct 5, 2010: Modified to handle compressed/linked-block element -BMR
109 --------------------------------------------------------------------------*/
110 intn
HDgetdatainfo(int32 file_id,uint16 tag,uint16 ref,int32 * chk_coord,uintn start_block,uintn info_count,int32 * offsetarray,int32 * lengtharray)111 HDgetdatainfo(int32 file_id, uint16 tag, uint16 ref, int32 *chk_coord,
112 	uintn start_block, uintn info_count, int32 *offsetarray,
113 	int32 *lengtharray)
114 {
115     CONSTR(FUNC, "HDgetdatainfo");	/* for HGOTO_ERROR */
116     filerec_t  *file_rec;	/* file record */
117     uint16	sp_tag;		/* special tag */
118     uint16	comp_ref = 0;	/* ref for compressed data or comp header */
119     uint16	dtag, dref;	/* description record tag/ref */
120     int32	dlen=0, doff=0;	/* offset/length of the description record */
121     uint8	lbuf[COMP_HEADER_LENGTH],
122 		*p=NULL;	/* desc record buffer and a pointer to it */
123     atom_t	data_id = FAIL;	/* dd ID of existing element */
124     int32	length; /* uncomp data len to check if data had been written */
125     intn	count=0;/* num of data blocks returned by getdatainfo funcs */
126     uint16	spec_code=0;/* special code: SPECIAL_LINKED, SPECIAL_COMP,... */
127     int32	comp_aid=-1;/* compressed element access id */
128     intn	ret_value=SUCCEED;
129 
130     /* Clear error stack */
131     HEclear();
132 
133     /* Validate array size */
134     if (info_count == 0 && offsetarray != NULL && lengtharray != NULL)
135         HGOTO_ERROR(DFE_ARGS, FAIL);
136 
137     /* Getting only offsets or lengths is not allowed */
138     if ((offsetarray != NULL && lengtharray == NULL) ||
139         (offsetarray == NULL && lengtharray != NULL))
140         HGOTO_ERROR(DFE_ARGS, FAIL);
141 
142     /* Convert file id to file rec and check for validity */
143     file_rec = HAatom_object(file_id);
144     if (BADFREC(file_rec))
145 	HGOTO_ERROR(DFE_ARGS, FAIL);
146 
147     /* Get access element from dataset's tag/ref */
148     if ((data_id=HTPselect(file_rec, tag, ref))!=FAIL)
149     {
150 	/* Get the info pointed to by this dd, which could point to data or
151 	   description record */
152 	if (HTPinquire(data_id, &dtag, &dref, &doff, &dlen) == FAIL)
153             HGOTO_ERROR(DFE_INTERNAL, FAIL);
154 
155         /* Return 0 if no data had been written */
156         if (doff == INVALID_OFFSET && dlen == INVALID_LENGTH)
157 	{
158 	    /* End access to the element */
159 	    if (HTPendaccess(data_id) == FAIL)
160 	        HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
161 
162 	    HGOTO_DONE(0);
163 	}
164 
165 	/* If the element is not special, that means dataset's tag/ref
166 	   specifies the actual data that was written to the dataset, get
167 	   the offset and length of the data if they were requested */
168 	if (HTPis_special(data_id)==FALSE)
169         {
170 	    /* Only one data block here, starting offset cannot be > 1 */
171 	    if (start_block > 1)
172 		HGOTO_ERROR(DFE_ARGS, FAIL);
173 
174 	    /* Offset and length are requested by caller */
175 	    if (offsetarray != NULL && lengtharray != NULL)
176 	    {
177 		offsetarray[0] = doff;
178 		lengtharray[0] = dlen;
179 	    }
180 	    count = 1;
181         }
182 
183 	/* If the element is special, get the special info header and decode
184 	   for special tag to detect compression/chunking/linked blocks */
185 	else
186 	{
187 	    if (HPseek(file_rec, doff) == FAIL)
188 		HGOTO_ERROR(DFE_SEEKERROR, FAIL);
189 	    if (HP_read(file_rec, lbuf, (int)2) == FAIL)
190 		HGOTO_ERROR(DFE_READERROR, FAIL);
191 
192 	    /* Decode the special tag */
193 	    p = &lbuf[0];
194 	    INT16DECODE(p, sp_tag);
195 
196 	    /* This is a compressed element */
197 	    if (sp_tag == SPECIAL_COMP)
198 	    {
199 		/* Read compression info header */
200 		if (HP_read(file_rec, lbuf, (int)COMP_HEADER_LENGTH) == FAIL)
201 		HGOTO_ERROR(DFE_READERROR, FAIL);
202 
203 		/* Decode header to get data length */
204 		p = &lbuf[0];
205 		p = p + 2; /* skip 2byte header_version */
206 		INT32DECODE(p, length);	/* get _uncompressed_ data length */
207 
208 		/* No data written */
209 		if (length == 0)
210 		{
211 		    count = 0;
212 		}
213 		/* Data had been written, either in contiguous block or more
214 		   special storage, in which case special code needs to be read */
215 		else
216 		{
217 		    /* Decode for the compression ref# */
218 		    UINT16DECODE(p, comp_ref);
219 
220 		    /* Get access to the compression element */
221 		    if ((comp_aid = HTPselect(file_rec, DFTAG_COMPRESSED, comp_ref)) == FAIL)
222 		        HGOTO_ERROR(DFE_INTERNAL, FAIL);
223 
224 		    /* If data had been written in one contiguous block */
225 		    if (HTPis_special(comp_aid) != TRUE)
226 		    {
227 		        /* Only one data block here, starting offset cannot be > 1*/
228 		        if (start_block > 1)
229 			    HGOTO_ERROR(DFE_ARGS, FAIL);
230 
231 		        /* This element is not further special, only compressed,
232 		           get its offset and length if they are requested */
233 		        if (offsetarray != NULL && lengtharray != NULL)
234 		        {
235 			    int32 off=0, len=0;
236 			    off = Hoffset(file_id, DFTAG_COMPRESSED, comp_ref);
237 			    if (off == FAIL)
238 			        HGOTO_ERROR(DFE_BADOFFSET, FAIL);
239 			    len = Hlength(file_id, DFTAG_COMPRESSED, comp_ref);
240 			    if (len == FAIL)
241 			        HGOTO_ERROR(DFE_BADLEN, FAIL);
242 
243 			    offsetarray[0] = off;
244 			    lengtharray[0] = len;
245 		        }
246 		        count = 1;
247 		    }   /* end if */
248 
249 		    /* This element is further special, read in the special code
250 		       to see what specialness is and process appropriately */
251 		    else
252 		    {
253 			/* Get offset of the special header */
254 		        if(HTPinquire(comp_aid, NULL, NULL, &doff, NULL)==FAIL)
255 		        {
256 			    HTPendaccess(comp_aid);
257 			    HGOTO_ERROR(DFE_INTERNAL, FAIL);
258 		        }
259 			/* Get to and read the special code from the header */
260 		        if (HPseek(file_rec, doff) == FAIL)
261 			    HGOTO_ERROR(DFE_SEEKERROR, FAIL);
262 		        if (HP_read(file_rec, lbuf, (int)2) == FAIL)
263 			    HGOTO_ERROR(DFE_READERROR, FAIL);
264 
265 		        /* Decode special code */
266 		        p = &lbuf[0];
267 		        INT16DECODE(p, spec_code);
268 
269 			/* The element has linked-blocks */
270 		        if (spec_code == SPECIAL_LINKED)
271 		        {
272 			    /* Read the rest of the linked-block info header */
273 			    if (HP_read(file_rec, lbuf, (int)14) == FAIL)
274 			        HGOTO_ERROR(DFE_READERROR, FAIL);
275 
276 			    /* Pass the header info to the linked-block API
277 			       to get the data info if they are requested or the
278 			       info count only, otherwise */
279 			    p = &lbuf[0];
280 			    if (offsetarray != NULL && lengtharray != NULL)
281 			        count = HLgetdatainfo(file_id, p, start_block,
282 					info_count, offsetarray, lengtharray);
283 			    else  /* get number of data blocks only */
284 			        count = HLgetdatainfo(file_id, p, start_block,
285 					0, NULL, NULL);
286 		        } /* this element is also stored in linked blocks */
287 		    } /* this element is further special */
288 
289 		    /* Release the compression element */
290 		    if(HTPendaccess(comp_aid)==FAIL)
291 		        HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
292 
293 		} /* compressed data written */
294 	    } /* element is compressed */
295 
296 	    /* This is a chunked element, hand the task over to the chunking
297 		layer. */
298 	    else if (sp_tag == SPECIAL_CHUNKED)
299 	    {
300 		if (chk_coord != NULL)
301 		    count = HMCgetdatainfo(file_id, tag, ref, chk_coord,
302 			    start_block, info_count, offsetarray, lengtharray);
303 		else /* BMR: check to see what should be done here */
304 		{
305 		    fprintf(stderr, "\nERROR>>> Element with tag/ref %d/%d is a chunked element, the chunk's coordinates must be specified\n", tag, ref);
306 	 	    HGOTO_ERROR(DFE_ARGS, FAIL);
307 		}
308 	    }
309 
310 	    /* Unlimited dimension; extract the number of blocks and the ref #
311 		of the link table then hand over to linked block layer */
312 	    else if (sp_tag == SPECIAL_LINKED)
313 	    {
314 		/* Read the linked-block info header */
315 		if (HP_read(file_rec, lbuf, (int)14) == FAIL)
316 		    HGOTO_ERROR(DFE_READERROR, FAIL);
317 
318 		/* Pass the header info to the linked-block API to get the data
319 		   info if they are requested or the info count only */
320 		p = &lbuf[0];
321 		if (offsetarray != NULL && lengtharray != NULL)
322 		    count = HLgetdatainfo(file_id, p, start_block, info_count,
323 			    offsetarray, lengtharray);
324 		else  /* get data information from the linked blocks */
325 		    count = HLgetdatainfo(file_id, p, start_block, 0, NULL, NULL);
326 	    } /* element is SPECIAL_LINKED */
327 	} /* else, data element is special */
328 
329 	/* End access to the element */
330 	if (HTPendaccess(data_id) == FAIL)
331 	    HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
332     }  /* end if data_id != FAIL */
333 
334     else /* HTPselect failed */
335         HGOTO_ERROR(DFE_CANTACCESS, FAIL);
336 
337     /* Return the number of data blocks */
338     ret_value = count;
339 done:
340     if(ret_value == FAIL)
341     { /* Error condition cleanup */
342     } /* end if */
343 
344     /* Normal function cleanup */
345     return ret_value;
346 } /* HDgetdatainfo */
347 
348 
349 /*------------------------------------------------------
350  NAME
351     VSgetdatainfo - Gets the offset/length of a vdata's data
352  USAGE
353     intn VSgetdatainfo(vsid, start_block, info_count, offsetarray, lengtharray)
354 	int32  vsid		IN: vdata id
355 	uintn  start_block	IN: data block to start at, 0 base
356 	uintn  info_count	IN: number of blocks to be retrieved
357 	int32 *offsetarray	OUT: array to hold offsets
358 	int32 *lengtharray	OUT: array to hold lengths
359  RETURNS
360     The number of data blocks retrieved, if successful and FAIL, otherwise.
361 
362  DESCRIPTION
363     This function uses the low-level function HDgetdatainfo to
364     get the data info when the vdata is stored in linked-blocks.
365 
366  TODO
367     - not tested with start_block and info_count
368  NOTES
369     Aug 17, 2010: Tested some in hdf/test/tdatainfo.c -BMR
370 ----------------------------------------------------------*/
371 intn
VSgetdatainfo(int32 vsid,uintn start_block,uintn info_count,int32 * offsetarray,int32 * lengtharray)372 VSgetdatainfo(int32 vsid, uintn start_block, uintn info_count,
373 	int32 *offsetarray, int32 *lengtharray)
374 {
375     CONSTR(FUNC, "VSgetdatainfo");
376     vsinstance_t *vs_inst = NULL;
377     VDATA        *vs = NULL;
378     accrec_t     *access_rec;
379     intn	  count;
380     intn          ret_value = SUCCEED;
381 
382     /* Clear error stack */
383     HEclear();
384 
385     /* Validate array size */
386     if (info_count == 0 && offsetarray != NULL && lengtharray != NULL)
387         HGOTO_ERROR(DFE_ARGS, FAIL);
388 
389     /* Getting only offsets or lengths is not allowed */
390     if ((offsetarray != NULL && lengtharray == NULL) ||
391         (offsetarray == NULL && lengtharray != NULL))
392         HGOTO_ERROR(DFE_ARGS, FAIL);
393 
394     /* Check key is valid vdata */
395     if (HAatom_group(vsid) != VSIDGROUP)
396         HGOTO_ERROR(DFE_ARGS, FAIL);
397 
398     /* Get vdata instance */
399     if (NULL == (vs_inst = (vsinstance_t *) HAatom_object(vsid)))
400         HGOTO_ERROR(DFE_NOVS, FAIL);
401 
402     /* Get vdata info structure and check it */
403     vs = vs_inst->vs;
404     if (vs == NULL)
405         HGOTO_ERROR(DFE_BADPTR, FAIL);
406 
407     /* Get access record of the vdata */
408     access_rec = HAatom_object(vs->aid);
409     if (access_rec == (accrec_t *) NULL)
410 	HGOTO_ERROR(DFE_ARGS, FAIL);
411 
412     /* If the vdata is empty, return 0 block */
413     if (vs->nvertices <= 0)
414 	HGOTO_DONE(0);
415 
416     /* If the vdata is stored in linked-blocks, let the low-level function
417        handle it */
418     if (access_rec->special == SPECIAL_LINKED)
419     {
420 	/* Application only wants the number of data blocks */
421 	if (offsetarray == NULL && lengtharray == NULL)
422 	{
423 	    count = HDgetdatainfo(vs->f, VSDATATAG, vs->oref, NULL, start_block, info_count, NULL, NULL);
424 	}
425 	/* Application only wants the offset and length of the blocks too */
426 	else
427 	{
428 	    count = HDgetdatainfo(vs->f, VSDATATAG, vs->oref, NULL, start_block, info_count, offsetarray, lengtharray);
429 	}
430 	if (count == FAIL)
431 	    HGOTO_ERROR(DFE_INTERNAL, FAIL);
432     }
433 
434     /* The vdata is stored in contiguous block */
435     else
436     {
437 	if (offsetarray != NULL && lengtharray != NULL)
438 	{
439 	    int32 off=0, len=0;
440 	    if ((off = Hoffset(vs->f, VSDATATAG, vs->oref)) == FAIL)
441 		HGOTO_ERROR(DFE_BADOFFSET, FAIL);
442 	    if ((len = Hlength(vs->f, VSDATATAG, vs->oref)) == FAIL)
443 		HGOTO_ERROR(DFE_BADLEN, FAIL);
444 	    *offsetarray = off;
445 	    *lengtharray = len;
446 	}
447 	count = 1;
448     }
449     /* Return the number of data blocks */
450     ret_value = count;
451 
452 done:
453   if(ret_value == FAIL)
454     { /* Error condition cleanup */
455     } /* end if */
456   /* Normal function cleanup */
457   return ret_value;
458 }   /* VSgetdatainfo */
459 
460 
461 /*-----------------------------------------------------------------------------
462  NAME
463     Vgetattdatainfo - Gets the offset/length of the data of a vgroup's attribute
464  USAGE
465     intn Vgetattdatainfo(vgid, attrindex, *offset, *length)
466 	int32  vgid		IN: vgroup id
467 	intn   attrindex	IN: attribute index
468 	int32 *offset		OUT: buffer for offset
469 	int32 *length		OUT: buffer for length
470  RETURNS
471     The number of data blocks retrieved, which should be 1, if successful
472     and FAIL, otherwise.
473 
474  DESCRIPTION
475     There are two types of attributes for vgroups.  One is the old-style
476     that was created using methods other than the standard attribute API
477     function Vsetattr, which was introduced after HDF Version 4.0 Release
478     2, July 19, 1996.  Without the use of Vsetattr, an application could
479     simulate an attribute for a vgroup by creating and writing a vdata
480     of class _HDF_ATTRIBUTE and adding that vdata to the vgroup via
481     these calls:
482 
483     vdata_ref = VHstoredatam(file_id, ATTR_FIELD_NAME, values, size, type,
484 		 attr_name, _HDF_ATTRIBUTE, order);
485     ret_value = Vaddtagref (vgroup_id, DFTAG_VH, vdata2_ref);
486 
487     While both types of attributes are stored as vdatas, the vdatas of
488     the new-style attributes are saved in a list of attribute tags/refs
489     of the vgroup, and the vdatas of the old-style attributes are saved
490     as elements of the vgroup.  Because of the different storages, the
491     new attribute functions would miss the old-style attributes.
492 
493     Two fields are added to the internal structure VGROUP for holding the
494     number of old-style attributes and their ref#s.  These fields are set
495     by Vnoldattrs when old-style attributes exist in the file.
496 
497     When a vgroup has both type of attributes, the two list will be
498     combined with the old-style attributes preceeding the new ones.
499     The attribute indices will be adjusted accordingly.
500 
501     This function uses the API function VSgetdatainfo to get the data
502     info of the attribute's data.
503     -BMR 2011/3/19
504 ----------------------------------------------------------*/
505 intn
Vgetattdatainfo(int32 vgid,intn attrindex,int32 * offset,int32 * length)506 Vgetattdatainfo(int32 vgid, intn attrindex, int32 *offset, int32 *length)
507 {
508     CONSTR(FUNC, "Vgetattdatainfo");
509     VGROUP *vg;
510     vg_attr_t *vg_alist;
511     vginstance_t *vg_inst;
512     int32 attr_vsid;
513     intn adjusted_index;
514     intn status;
515     intn ret_value = SUCCEED;
516 
517     /* Clear error stack */
518     HEclear();
519 
520     /* Both buffers must be allocated */
521     if (offset == NULL || length == NULL)
522         HGOTO_ERROR(DFE_ARGS, FAIL);
523 
524     /* Validate Vgroup ID */
525     if (HAatom_group(vgid) != VGIDGROUP)
526        HGOTO_ERROR(DFE_ARGS, FAIL);
527 
528     /* Locate vg's index in vgtab */
529     if (NULL == (vg_inst = (vginstance_t *)HAatom_object(vgid)))
530        HGOTO_ERROR(DFE_VTAB, FAIL);
531     if (NULL == (vg = vg_inst->vg))
532         HGOTO_ERROR(DFE_NOVS, FAIL);
533 
534     /* Validate arguments */
535 
536     if (attrindex < 0)
537         HGOTO_ERROR(DFE_BADATTR, FAIL); /* invalid attribute index given */
538 
539     adjusted_index = attrindex;
540     if (adjusted_index < vg->noldattrs) /* index of old-style attribute */
541         vg_alist = vg->old_alist;  /* use old-attr list */
542     else if (adjusted_index >= vg->noldattrs &&
543              adjusted_index < (vg->nattrs+vg->noldattrs))
544                  /* index of new-style attributes */
545     {
546         /* Adjust the index to accommodate for the old-style attributes
547            preceding the new-style attribute list */
548         adjusted_index = adjusted_index - vg->noldattrs;
549         vg_alist = vg->alist;        /* use new-attr list */
550     }
551     else /* not that many attrs */
552         HGOTO_ERROR(DFE_BADATTR, FAIL);
553 
554     if (vg_alist == NULL)
555         /* Bad attr list */
556         HGOTO_ERROR(DFE_BADATTR, FAIL);
557 
558     /* Get vdata holding the attribute */
559     if (FAIL == (attr_vsid = VSattach(vg->f, (int32)vg_alist[adjusted_index].aref, "r")))
560         HGOTO_ERROR(DFE_CANTATTACH, FAIL);
561 
562     /* Get offset and length of attribute's data.  Note that start_block is 0
563        and info_count is 1 because attribute's data is only stored in 1 block */
564     status = VSgetdatainfo(attr_vsid, 0, 1, offset, length);
565     if (status == FAIL)
566         HGOTO_ERROR(DFE_GENAPP, FAIL);
567 
568     /* Close vdata */
569     if (FAIL == VSdetach(attr_vsid))
570         HGOTO_ERROR(DFE_CANTDETACH, FAIL);
571 
572     /* Return the number of data blocks, which should be 1 */
573     ret_value = status;
574 done:
575   if(ret_value == FAIL)
576     { /* Error condition cleanup */
577 
578     } /* end if */
579 
580   /* Normal function cleanup */
581   return ret_value;
582 }   /* Vgetattdatainfo */
583 
584 
585 /*------------------------------------------------------
586  NAME
587     VSgetattdatainfo - Gets the offset/length of the data
588 		      of a vdata's or vdata field's attribute
589  USAGE
590     intn VSgetattdatainfo(vsid, findex, attrindex, *offset, *length)
591 	int32  vsid		IN: vdata id
592 	int32  findex		IN: vdata's field index or _HDF_VDATA
593 	intn   attrindex	IN: attribute index
594 	int32 *offset		OUT: buffer for offset
595 	int32 *length		OUT: buffer for length
596  RETURNS
597     The number of data blocks retrieved, which should be 1, if successful
598     and FAIL, otherwise.
599 
600  DESCRIPTION
601     VSgetattdatainfo retrieves the offset and length of the data that belongs
602     to an attribute.  If findex is _HDF_VDATA (or -1), then the attribute is
603     associated with the vdata vsid.  If findex is an index of the vdata field,
604     then the attribute is one that is associated with the vdata field.  The
605     parameter attrindex specifies the attribute's index within the vdata's
606     or the field's attribute list.  Thus, its valid value must be within
607     [0-nattrs of the associated list].
608 
609     VSgetattdatainfo uses VSgetdatainfo once it locates the vdata that stores
610     the attribute.
611     -BMR 2011/3/19
612 ----------------------------------------------------------*/
613 intn
VSgetattdatainfo(int32 vsid,int32 findex,intn attrindex,int32 * offset,int32 * length)614 VSgetattdatainfo(int32 vsid, int32 findex, intn attrindex, int32 *offset, int32 *length)
615 {
616     CONSTR(FUNC, "VSgetattdatainfo");
617     VDATA *vs;
618     vs_attr_t *vs_alist;
619     vsinstance_t *vs_inst;
620     int32 attr_vsid;
621     intn nattrs, idx, a_index, found;
622     intn status;
623     intn ret_value = SUCCEED;
624 
625     /* Clear error stack */
626     HEclear();
627 
628     /* Both buffers must be allocated */
629     if (offset == NULL || length == NULL)
630         HGOTO_ERROR(DFE_ARGS, FAIL);
631 
632     if (HAatom_group(vsid) != VSIDGROUP)
633         HGOTO_ERROR(DFE_ARGS, FAIL);
634     /* locate vs' index in vstab */
635     if (NULL == (vs_inst = (vsinstance_t *)HAatom_object(vsid)))
636         HGOTO_ERROR(DFE_NOVS, FAIL);
637     if (NULL == (vs = vs_inst->vs))
638         HGOTO_ERROR(DFE_NOVS, FAIL);
639     if ((findex >= vs->wlist.n || findex < 0) && (findex != _HDF_VDATA))
640         HGOTO_ERROR(DFE_BADFIELDS, FAIL);
641     nattrs = vs->nattrs;
642 
643     /* No attrs */
644     if (nattrs == 0) HGOTO_ERROR(DFE_ARGS, FAIL);
645 
646     /* Index must be positive and less than the number of attributes */
647     if (attrindex <0 || attrindex >= nattrs)
648         HGOTO_ERROR(DFE_ARGS, FAIL);
649     vs_alist = vs->alist;
650 
651     /* Bad attr list */
652     if (vs_alist == NULL) HGOTO_ERROR(DFE_ARGS, FAIL);
653 
654     found = 0;
655     a_index = -1;
656     for (idx=0; idx<nattrs && found==0; idx++)
657     {
658 	if (vs_alist->findex == findex)
659 	{
660 	    a_index++;
661 	    if (a_index == attrindex)
662 		found = 1;
663         }
664 	if (!found) vs_alist++;
665     }
666     /* If this happened, it would have been detected by the check for range
667        of attrindex above already, but check it anyway */
668     if (!found)
669         HGOTO_ERROR(DFE_ARGS, FAIL);
670 
671     /* Attribute is found.  Get access to the vdata that stores the attribute's
672        data, retrieve the offset and length of the data, then close access. */
673 
674     /* Get vdata */
675     if (FAIL == (attr_vsid = VSattach(vs->f, (int32)vs_alist->aref, "r")))
676         HGOTO_ERROR(DFE_CANTATTACH, FAIL);
677 
678     /* Get offset and length of attribute's data.  Note that start_block is 0
679        and info_count is 1 because attribute's data is only stored in 1 block */
680     status = VSgetdatainfo(attr_vsid, 0, 1, offset, length);
681     if (status == FAIL)
682         HGOTO_ERROR(DFE_GENAPP, FAIL);
683 
684     /* Close vdata */
685     if (FAIL == VSdetach(attr_vsid))
686         HGOTO_ERROR(DFE_CANTDETACH, FAIL);
687 
688     /* Return the number of data blocks, which should be 1 */
689     ret_value = status;
690 
691 done:
692   if(ret_value == FAIL)
693     { /* Error condition cleanup */
694 
695     } /* end if */
696 
697   /* Normal function cleanup */
698   return ret_value;
699 }   /* VSgetattdatainfo */
700 
701 
702 /*------------------------------------------------------------
703  NAME
704     GRgetattdatainfo - Gets the offset/length of the data of a
705 			GR file's or an image's attribute
706  USAGE
707     intn GRgetattdatainfo(id, attrindex, offset, length)
708         int32 id		IN: either GR ID or RI ID
709         int32 attrindex		IN: index of the attribute being inquired
710         int32 *offset		OUT: buffer for offset
711         int32 *length		OUT: buffer for length
712  RETURNS
713     The number of data blocks retrieved, which should be 1, if successful
714     and FAIL, otherwise.
715 
716  DESCRIPTION
717     GRgetattdatainfo retrieves the location and size of the attribute's data
718     and its length.
719 
720  MODIFICATION
721     Apr 03, 2011: Revised to remove the parameter attrname because, for hmap
722         project, it makes sense to just provide the attribute index. -BMR
723 
724 --------------------------------------------------------------*/
725 intn
GRgetattdatainfo(int32 id,int32 attrindex,int32 * offset,int32 * length)726 GRgetattdatainfo(int32 id, int32 attrindex, int32 *offset, int32 *length)
727 {
728     CONSTR(FUNC, "GRgetattdatainfo");
729     int32      hdf_file_id;	/* file id */
730     int32      attr_vsid;	/* id of vdata that stores the attribute */
731     group_t id_group=BADGROUP;	/* temporary group of id */
732     gr_info_t *gr_ptr;          /* ptr to the GR information for gr id */
733     ri_info_t *ri_ptr;          /* ptr to the image information for ri id */
734     at_info_t *at_ptr=NULL;	/* ptr to the attribute information */
735     void     **aentry;		/* temp. ptr to the image found */
736     TBBT_TREE *search_tree;	/* attribute tree to search through */
737     int        found = FALSE;	/* TRUE when the searched attribute is found */
738     intn       status = 0;
739     intn       ret_value = SUCCEED;
740 
741     /* Clear error stack */
742     HEclear();
743 
744     /* Validate index */
745     if (attrindex < 0)
746         HGOTO_ERROR(DFE_ARGS, FAIL);
747 
748     /* Both buffers must be allocated */
749     if (offset == NULL || length == NULL)
750         HGOTO_ERROR(DFE_ARGS, FAIL);
751 
752     /* Validate ID */
753     id_group = HAatom_group(id);
754     if (id_group != RIIDGROUP && id_group != GRIDGROUP)
755         HGOTO_ERROR(DFE_ARGS, FAIL);
756 
757     /* Get attribute info and validate index */
758 
759     /* When file ID is given, check index against file's attribute count */
760     if (id_group == GRIDGROUP)
761       {
762           /* locate GR's object in hash table */
763           if (NULL == (gr_ptr = (gr_info_t *) HAatom_object(id)))
764               HGOTO_ERROR(DFE_GRNOTFOUND, FAIL);
765 
766 	  /* Check index against file's attribute count */
767           if(attrindex >= gr_ptr->gattr_count)
768               HGOTO_ERROR(DFE_ARGS, FAIL);
769 
770           search_tree = gr_ptr->gattree;
771 	  hdf_file_id = gr_ptr->hdf_file_id;
772       } /* end if */
773 
774     /* When raster image ID is given, check index against image's attr count */
775     else if (id_group == RIIDGROUP)
776       {
777           /* locate RI's object in hash table */
778           if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(id)))
779               HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
780 
781 	  /* Check index against image's attribute count */
782           if(attrindex >= ri_ptr->lattr_count)
783               HGOTO_ERROR(DFE_ARGS, FAIL);
784           search_tree = ri_ptr->lattree;
785 	  hdf_file_id = ri_ptr->gr_ptr->hdf_file_id;
786       } /* end if */
787     else
788         HGOTO_ERROR(DFE_ARGS, FAIL);
789 
790     /* Search for an attribute with the same index */
791     aentry = (void **)tbbtfirst((TBBT_NODE *)*search_tree);
792     found = FALSE;
793     while (!found && (aentry != NULL))
794     {
795 	at_ptr = (at_info_t *)*aentry;
796 	if (at_ptr == NULL)
797 	{
798 	    HGOTO_ERROR(DFE_ARGS, FAIL);
799 	}
800 
801 	/* If index is found, set flag */
802 	if (at_ptr->index == attrindex)
803 	    found = TRUE;
804 
805 	/* Not found, go to the next entry */
806 	if (!found)
807 	    aentry = (void **)tbbtnext((TBBT_NODE *)aentry);
808     } /* end while */
809 
810     /* If the attribute is found, get offset/length of its data */
811     if (found)
812     {
813 	/* Get access to the vdata that stores the attribute */
814 	attr_vsid = VSattach(hdf_file_id, (int32)at_ptr->ref, "r");
815 	if (attr_vsid == FAIL)
816 	    HGOTO_ERROR(DFE_CANTATTACH, FAIL);
817 
818 	/* Get offset and length of attribute's data.  Note that start_block
819 	   is 0 and info_count is 1 because attribute's data is only stored
820 	   in 1 block */
821 	status = VSgetdatainfo(attr_vsid, 0, 1, offset, length);
822 	if (status == FAIL)
823 	    HGOTO_ERROR(DFE_GENAPP, FAIL);
824 
825 	if (FAIL == VSdetach(attr_vsid))
826 	    HGOTO_ERROR(DFE_CANTDETACH, FAIL);
827     }
828     ret_value = status; /* should be 1 */
829 
830 done:
831   if(ret_value == 0)
832     { /* Error condition cleanup */
833     } /* end if */
834   /* Normal function cleanup */
835   return ret_value;
836 }   /* GRgetattdatainfo */
837 
838 
839 /*---------------------------------------------------------------
840 NAME
841     GRgetdatainfo - Gets the offsets/lengths of the data of an image
842 USAGE
843     intn GRgetdatainfo(riid, start_block, info_count, offsetarray, lengtharray)
844         int32 riid		IN: raster image ID
845 	uintn start_block	IN: start retrieving data at
846 	uintn info_count	IN: number of data blocks to retrieve
847 	int32 *offsetarray	OUT: buffer for offset(s)
848 	int32 *lengtharray	OUT: buffer for length(s)
849 RETURNS
850     The number of data blocks retrieved, if successful and FAIL, otherwise.
851 
852 DESCRIPTION
853     This function uses the low-level function HDgetdatainfo to
854     get the data info of an image.
855 
856 TODO
857     - not tested with linked-block element yet
858     - need more documentation
859 ----------------------------------------------------------------*/
860 intn
GRgetdatainfo(int32 riid,uintn start_block,uintn info_count,int32 * offsetarray,int32 * lengtharray)861 GRgetdatainfo(int32 riid, uintn start_block, uintn info_count,
862 	int32 *offsetarray, int32 *lengtharray)
863 {
864     CONSTR(FUNC, "GRgetdatainfo");
865     ri_info_t *ri_ptr;          /* ptr to the image to work with */
866     int32 hdf_file_id;		/* short cut for file id */
867     int32 length = 0;
868     uintn count;
869     intn   ret_value = SUCCEED;
870 
871     /* Clear error stack */
872     HEclear();
873 
874     /* Validate array size */
875     if (info_count == 0 && (offsetarray != NULL && lengtharray != NULL))
876         HGOTO_ERROR(DFE_ARGS, FAIL);
877 
878     /* Getting only offsets or lengths is not allowed */
879     if ((offsetarray != NULL && lengtharray == NULL) ||
880         (offsetarray == NULL && lengtharray != NULL))
881         HGOTO_ERROR(DFE_ARGS, FAIL);
882 
883     /* Check the validity of the ID */
884     if (HAatom_group(riid) != RIIDGROUP)
885         HGOTO_ERROR(DFE_ARGS, FAIL);
886 
887     /* Locate RI's object in hash table */
888     ri_ptr = (ri_info_t *) HAatom_object(riid);
889     if (NULL == ri_ptr)
890 	HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
891 
892     hdf_file_id = ri_ptr->gr_ptr->hdf_file_id;	/* alias for file id */
893 
894     /* Check for no data in the image */
895 
896     /* If the image has no tag/ref pair assigned to it yet, return 0 for
897        info count */
898     if(ri_ptr->img_tag==DFTAG_NULL || ri_ptr->img_tag==DFREF_WILDCARD
899 	|| ri_ptr->img_ref==DFREF_WILDCARD)
900     {
901         if ((offsetarray != NULL && lengtharray != NULL))
902 	    *offsetarray = *lengtharray = 0;
903 	HGOTO_DONE(0);
904     }
905     /* If the image already had a tag/ref pair, make sure it has actual data,
906        if not, return 0 for info count */
907     else
908     {
909 	length = Hlength(hdf_file_id, ri_ptr->img_tag, ri_ptr->img_ref);
910 	if (length == FAIL)
911 	{
912             if ((offsetarray != NULL && lengtharray != NULL))
913 		*offsetarray = *lengtharray = 0;
914 	    HGOTO_DONE(0);
915 	}
916 
917         /* If both arrays are NULL, get the number of data blocks and return */
918         if ((offsetarray == NULL && lengtharray == NULL))
919         {
920             count = HDgetdatainfo(hdf_file_id, ri_ptr->img_tag, ri_ptr->img_ref, NULL, start_block, 0, NULL, NULL);
921             if (count == FAIL)
922                 HGOTO_ERROR(DFE_INTERNAL, FAIL);
923         }
924 
925         /* Application requests offsets/lengths */
926         else
927         {
928             count = HDgetdatainfo(hdf_file_id, ri_ptr->img_tag, ri_ptr->img_ref, NULL, start_block, info_count, offsetarray, lengtharray);
929             if (count == FAIL)
930                 HGOTO_ERROR(DFE_INTERNAL, FAIL);
931         }
932     } /* end else */
933 
934     ret_value = count;
935 
936 done:
937   if(ret_value == 0)
938     { /* Error condition cleanup */
939     } /* end if */
940   /* Normal function cleanup */
941   return ret_value;
942 }   /* GRgetdatainfo */
943 
944 
945 /*---------------------------------------------------------------
946 NAME
947     GRgetpalinfo - Gets the palette data descriptors (DDs) in the
948 		   file (i.e., palette tags, refs, offsets, and lengths)
949 USAGE
950     intn GRgetpalinfo(gr_id, pal_count, palinfo_array)
951         int32 gr_id		IN: GR interface ID
952 	uintn pal_count		IN: number of palette DDs to get
953 	hdf_ddinfo_t *palinfo_array	OUT: array of palette DDs
954 RETURNS
955     The number of palette DDs in the file or the actual number of palette
956     DDs retrieved, if successful, and FAIL, otherwise.
957 
958 DESCRIPTION
959     If the caller only requests the number of palette tags in the file,
960     i.e., when palinfo_array is NULL and pal_count is 0, we will simply
961     return the number of palette tags, including both DFTAG_IP8 and
962     DFTAG_LUT, without further processing.
963 
964     Otherwise, the function will search the file for all tags DFTAG_IP8
965     and DFTAG_LUT, then retrieve the palette data information into the
966     provided array of structures.
967 
968     -BMR 2012/6/19
969 ----------------------------------------------------------------*/
970 intn
GRgetpalinfo(int32 gr_id,uintn pal_count,hdf_ddinfo_t * palinfo_array)971 GRgetpalinfo(int32 gr_id, uintn pal_count, hdf_ddinfo_t *palinfo_array)
972 {
973     CONSTR(FUNC, "GRgetpalinfo");
974     gr_info_t *gr_ptr;
975     int32 file_id;
976     int32 nbytes = 0;
977     int32 aid = FAIL;
978     intn  idx;
979     uintn count;
980     intn  ret_value = SUCCEED;
981 
982     /* Clear error stack */
983     HEclear();
984 
985     /* check the validity of the GR ID */
986     if (HAatom_group(gr_id)!=GRIDGROUP)
987         HGOTO_ERROR(DFE_ARGS, FAIL);
988 
989     /* locate GR's object in hash table */
990     if (NULL == (gr_ptr = (gr_info_t *) HAatom_object(gr_id)))
991         HGOTO_ERROR(DFE_GRNOTFOUND, FAIL);
992 
993     file_id = gr_ptr->hdf_file_id; /* alias of the file id */
994 
995     /* Validate array size.  Fail when count is a pos number but the array is
996        NULL, or when count is a neg number */
997     if ((pal_count > 0 && palinfo_array == NULL) || pal_count < 0)
998         HGOTO_ERROR(DFE_ARGS, FAIL);
999 
1000     /* If only the number of palette tags is interested, return that */
1001     if (pal_count == 0 && palinfo_array == NULL)
1002     {
1003 	int32 n_IP8s = 0, n_LUTs = 0;
1004 
1005 	n_IP8s = Hnumber(file_id, DFTAG_IP8);
1006 	n_LUTs = Hnumber(file_id, DFTAG_LUT);
1007 	if (n_IP8s == FAIL || n_LUTs == FAIL)
1008 	{   HGOTO_ERROR(DFE_INTERNAL, FAIL); }
1009 	else
1010 	    return(n_IP8s + n_LUTs);
1011     }
1012 
1013     /* Application requests data info of palettes.  Start checking tags in
1014        the file and when a palette tag is encountered, retrieve its DD.  The
1015        process continues until no more tags/refs in the file or the maxinum
1016        size of the provided array is reached */
1017     idx = 0;
1018     ret_value = aid = Hstartread(file_id, DFTAG_WILDCARD, DFREF_WILDCARD);
1019     while (ret_value != FAIL && idx < pal_count)
1020     {
1021 	uint16 tag;
1022 
1023 	/* Get tag of this element */
1024 	ret_value = Hinquire(aid, NULL, &tag, NULL,NULL,NULL,NULL,NULL,NULL);
1025 	if (ret_value == FAIL)
1026 	    HGOTO_ERROR(DFE_INTERNAL, FAIL);
1027 
1028 	if (tag == DFTAG_IP8 || tag == DFTAG_LUT)
1029 	{ /* a palette tag is found */
1030 
1031 	    /* Get the palette's data info */
1032 	    ret_value = Hinquire(aid, NULL, &palinfo_array[idx].tag,
1033 		&palinfo_array[idx].ref, &palinfo_array[idx].length,
1034 		&palinfo_array[idx].offset, NULL, NULL, NULL);
1035 	    if (ret_value == FAIL)
1036 		HGOTO_ERROR(DFE_INTERNAL, FAIL);
1037 
1038 	    /* Move to next element in the array */
1039 	    idx++;
1040 	} /* a palette tag is found */
1041 
1042 	/* Get next element */
1043 	ret_value = Hnextread(aid, DFTAG_WILDCARD, DFREF_WILDCARD, DF_CURRENT);
1044     } /* get data info of palettes */
1045 
1046     /* Close access id */
1047     if (aid != FAIL)
1048 	if (Hendaccess(aid) == FAIL)
1049 	    HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
1050 
1051     ret_value = idx;
1052 
1053 done:
1054   if(ret_value == FAIL)
1055     { /* Error condition cleanup */
1056       if (aid != FAIL)
1057           Hendaccess(aid);
1058     } /* end if */
1059   /* Normal function cleanup */
1060   return ret_value;
1061 }   /* GRgetpalinfo */
1062 
1063 
1064 /*--------------------------------------------------------------------------
1065 NAME
1066     ANgetdatainfo -- Gets the offset(s) and length(s) locating the data of
1067 		      the annotation.
1068 USAGE
1069     int32 ANgetdatainfo(ann_id, *offset, *length)
1070 	int32  ann_id	IN: annotation ID
1071 	int32 *offset	OUT: buffer for offset
1072 	int32 *length	OUT: buffer for length
1073 RETURNS
1074     SUCCEED/FAIL
1075 
1076 DESCRIPTION
1077     Annotations have contiguous data, so ANgetdatainfo only needs to use
1078     Hoffset/Hlength to get the data info of an annotation.
1079 
1080 NOTES
1081     Aug 25, 2010: Tested in tdatainfo.c/test_annotation -BMR
1082 --------------------------------------------------------------------------*/
1083 intn
ANgetdatainfo(int32 ann_id,int32 * offset,int32 * length)1084 ANgetdatainfo(int32 ann_id,    /* IN: annotation id */
1085 	int32 *offset,	/* OUT: buffer for offset */
1086 	int32 *length)	/* OUT: buffer for length */
1087 {
1088     CONSTR(FUNC, "ANgetdatainfo");
1089     filerec_t  *file_rec = NULL;		/* file record pointer */
1090     ANnode     *ann_node   = NULL;
1091     int32       file_id = FAIL;
1092     int32       type;
1093     int32       ann_key;
1094     int         newflag = 0;
1095     uint16      ann_tag;
1096     uint16      ann_ref;
1097     intn        ret_value = SUCCEED;
1098 
1099     /* Clear error stack */
1100     HEclear();
1101 
1102     /* Both buffers must be allocated */
1103     if (offset == NULL || length == NULL)
1104         HGOTO_ERROR(DFE_ARGS, FAIL);
1105 
1106     /* Get annotation record */
1107     ann_node = HAatom_object(ann_id);
1108     if (NULL == ann_node)
1109         HGOTO_ERROR(DFE_ARGS, FAIL);
1110 
1111     /* Convert file_id to file rec and check for validity */
1112     file_id = ann_node->file_id;
1113     file_rec = HAatom_object(file_id);
1114     if (BADFREC(file_rec))
1115         HGOTO_ERROR(DFE_INTERNAL, FAIL);
1116 
1117     /* Get annotation key, type, and ref# */
1118     ann_key = ann_node->ann_key;
1119     type    = AN_KEY2TYPE(ann_key);
1120     ann_ref = AN_KEY2REF(ann_key);
1121 
1122     /* Set type tag */
1123     switch((int32)type)
1124       {
1125       case AN_DATA_LABEL:
1126           ann_tag = DFTAG_DIL;
1127           break;
1128       case AN_DATA_DESC:
1129           ann_tag = DFTAG_DIA;
1130           break;
1131       case AN_FILE_LABEL:
1132           ann_tag = DFTAG_FID;
1133           break;
1134       case AN_FILE_DESC:
1135           ann_tag = DFTAG_FD;
1136           break;
1137       default:
1138           HE_REPORT_GOTO("Bad annotation type for this call",FAIL);
1139       }
1140 
1141 #ifdef NEED_ELEMENT_TAG_REF
1142 /* Keep these here just in case we end up need the object's tag/ref -BMR */
1143     /* Get annotation entry so that we can get object's tag/ref later */
1144     if ((entry = tbbtdfind(file_rec->an_tree[type], &ann_key, NULL)) == NULL)
1145 	HE_REPORT_GOTO("failed to retrieve annotation of 'type' tree", FAIL);
1146 
1147     ann_entry = (ANentry *) entry->data;
1148 
1149     elem_tag = ann_entry->elmtag;
1150     elem_ref = ann_entry->elmref;
1151 #endif
1152 
1153     /* If annotation exists, try to get offset/length */
1154     newflag  = ann_node->new_ann;
1155     if (newflag == 0)
1156     {
1157 	int32 off=0, len=0;
1158 	if (offset != NULL && length != NULL)
1159 	{
1160 	    off = Hoffset(file_id, ann_tag, ann_ref);
1161 	    if (off == FAIL)
1162                 HGOTO_ERROR(DFE_INTERNAL, FAIL);
1163 	    len = Hlength(file_id, ann_tag, ann_ref);
1164 	    if (len == FAIL)
1165                 HGOTO_ERROR(DFE_INTERNAL, FAIL);
1166 	    *offset = off;
1167 	    *length = len;
1168 	}
1169 
1170 	/* Because for Data label/description, the object's tag/ref were
1171 	written to the file before the annotation data, 4 bytes must be
1172 	taken into account for them */
1173 	if (ann_tag == DFTAG_DIL || ann_tag == DFTAG_DIA)
1174 	{
1175 	    *offset = *offset + 4;
1176 	    *length = *length - 4;
1177 	}
1178     }
1179 
1180   done:
1181     if(ret_value == FAIL)
1182       { /* Error condition cleanup */
1183       } /* end if */
1184     /* Normal function cleanup */
1185     return ret_value;
1186 } /* ANgetdatainfo */
1187