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