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 HDF. The full HDF 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/HDF/releases/. *
10 * If you do not have access to either file, you may request a copy from *
11 * help@hdfgroup.org. *
12 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13
14 /* $Id$ */
15
16 /*-----------------------------------------------------------------------------
17 * File: dfan.c
18 * Purpose: read and write annotations: labels and descriptions of data items
19 * Invokes: df.c
20 * Contents:
21 *
22 * DFANclear: - reset DFAN interface
23 * DFANgetlablen: - get length of label of tag/ref
24 * DFANgetlabel: - get label of tag/ref
25 * DFANgetdesclen: - get length of description of tag/ref
26 * DFANgetdesc: - get description of tag/ref
27 *
28 * DFANgetfidlen: - get length of file ID
29 * DFANgetfid: - get file ID
30 * DFANgetfdslen: - get length of file description
31 * DFANgetfds: - get file description
32 *
33 * DFANputlabel: - put label of tag/ref
34 * DFANputdesc: - put description of tag/ref
35 *
36 * DFANaddfid: - add file ID
37 * DFANaddfds: - add file description
38 *
39 * DFANlastref: - return ref of last annotation read or written
40 * DFANlablist: - get list of labels for a particular tag
41 *
42 * DFANIclear: - clear Lastref, label/desc entries and directories
43 * DFANIopen: - open/reopen file
44 * DFANIlocate: - return ref of label/desc of tag/ref
45 * DFANIaddentry: - add entry in annotation directory
46 * DFANIgetannlen: - get length of annotation of tag/ref
47 * DFANIgetann: - get annotation of tag/ref
48 * DFANIputann: - put annotation of tag/ref
49 * DFANIlablist: - get list of labels for a particular tag
50 *
51 * DFANIaddfann: - add file annotation (ID or description)
52 * DFANIgetfannlen: - get length of file annotation
53 * DFANIgetfann: - get file annotation
54 *---------------------------------------------------------------------------*/
55
56 #include "hdf.h"
57 #include "dfan.h"
58 PRIVATE uint16 Lastref = 0; /* Last ref read/written */
59 PRIVATE uint16 Next_label_ref = 0; /* Next file label ref to read/write */
60 PRIVATE uint16 Next_desc_ref = 0; /* Next file desc ref to read/write */
61
62 #if 0
63 static char Lastfile[DF_MAXFNLEN] = ""; /* last file opened */
64 #endif
65 PRIVATE char *Lastfile = NULL;
66
67 /* pointers to directories of object annotations */
68 PRIVATE DFANdirhead *DFANdir[2] =
69 {NULL, /* object labels */
70 NULL /* object descriptions */
71 };
72
73 /* Whether we've installed the library termination function yet for this interface */
74 PRIVATE intn library_terminate = FALSE;
75
76 /*
77 ** Prototypes for local functions
78 */
79
80 PRIVATE int32 DFANIopen(const char *filename, intn acc_mode);
81 PRIVATE intn DFANIstart(void);
82
83 /*-----------------------------------------------------------------------------
84 * HDF object (i.e. tag/ref) label and description input routines
85 *---------------------------------------------------------------------------*/
86
87 /*-----------------------------------------------------------------------------
88 NAME
89 DFANgetlablen -- get length of label of tag/ref
90 USAGE
91 int32 DFANgetlablen(filename, tag, ref)
92 char *filename; IN: filename: name of HDF file
93 uint16 tag; IN: tag of data object assigned the label
94 uint16 ref; IN: reference number of the data object assigned
95 the label
96 RETURNS
97 length of label on success, FAIL (-1) otherwise
98 DESCRIPTION
99 Calls DFANIgetannlen to get label length.
100 GLOBAL VARIABLES
101 COMMENTS, BUGS, ASSUMPTIONS
102 This routine should be used to insure that there is enough space
103 allocated for a label before actually reading it.
104 EXAMPLES
105 REVISION LOG
106 *---------------------------------------------------------------------------*/
107 int32
DFANgetlablen(const char * filename,uint16 tag,uint16 ref)108 DFANgetlablen(const char *filename, uint16 tag, uint16 ref)
109 {
110 int32 ret_value;
111
112 ret_value = (DFANIgetannlen(filename, tag, ref, DFAN_LABEL));
113
114 return ret_value;
115 }
116
117 /*--------------------------------------------------------------------------
118 NAME
119 DFANgetlabel -- get label of object identified by tag/ref
120 USAGE
121 int DFANgetlabel(filename, tag, ref, label, maxlen)
122 char *filename; IN: name of HDF file
123 uint16 tag; IN: tag of object of assigned the label
124 uint16 ref; IN: ref number of object of assigned the label
125 char *label; OUT: buffer allocated to hold the label
126 int32 maxlen; IN: size of buffer allocated to hold the label
127 RETURNS
128 SUCCEED (0) if successful and FAIL (-1) otherwise
129 DESCRIPTION
130 Invokes DFANIgetann to get label
131 GLOBAL VARIABLES
132 COMMENTS, BUGS, ASSUMPTIONS
133 The value of maxlen must be at least one greater than the
134 anticipated length of the label, because a NULL byte is appended
135 to the annotation
136 EXAMPLES
137 REVISION LOG
138 *---------------------------------------------------------------------------*/
139 intn
DFANgetlabel(const char * filename,uint16 tag,uint16 ref,char * label,int32 maxlen)140 DFANgetlabel(const char *filename, uint16 tag, uint16 ref, char *label,
141 int32 maxlen)
142 {
143 intn ret_value;
144
145 ret_value = (DFANIgetann(filename, tag, ref, (uint8 *) label, maxlen, DFAN_LABEL, 0));
146
147 return ret_value;
148 }
149
150 /*--------------------------------------------------------------------------
151 NAME
152 DFANgetdesclen -- get length of description of tag/ref
153 USAGE
154 int32 DFANgetdesclen(filename, tag, ref)
155 char *filename; IN: name of HDF file
156 uint16 tag; IN: tag of item of which we want description
157 uint16 ref; IN: ref number of item of which we want description
158 RETURNS
159 Length of description if successful, and FAIL (-1) otherwise
160 DESCRIPTION
161 Calls DFANIgetannlen to get description length
162 GLOBAL VARIABLES
163 COMMENTS, BUGS, ASSUMPTIONS
164 This routine should be used to insure that there is enough space
165 allocated for a description before actually reading it.
166 EXAMPLES
167 REVISION LOG
168 *------------------------------------------------------------------------*/
169 int32
DFANgetdesclen(const char * filename,uint16 tag,uint16 ref)170 DFANgetdesclen(const char *filename, uint16 tag, uint16 ref)
171 {
172 int32 ret_value;
173
174 ret_value = (DFANIgetannlen(filename, tag, ref, DFAN_DESC));
175
176 return ret_value;
177 }
178
179 /*--------------------------------------------------------------------------
180 NAME
181 DFANgetdesc -- Reads the description assigned to the data object
182 with the given tag and reference number.
183 USAGE
184 int DFANgetdesc(filename, tag, ref, desc, maxlen)
185 char * filename; IN: name of HDF file
186 uint16 tag; IN: tag of object of assigned the label
187 uint16 ref; IN: ref number of object of assigned the label
188 char *desc; OUT: buffer allocated to hold the description
189 int32 maxlen; IN: size of buffer allocated to hold the description
190 RETURNS
191 SUCCEED (0) if successful and FAIL (-1) otherwise
192 DESCRIPTION
193 Invokes DFANIgetann to get description
194 GLOBAL VARIABLES
195 COMMENTS, BUGS, ASSUMPTIONS
196 The value of maxlen must be at least one greater than the
197 anticipated length of the description, because a NULL byte is
198 appended to the annotation
199 EXAMPLES
200 REVISION LOG
201 *------------------------------------------------------------------------*/
202
203 intn
DFANgetdesc(const char * filename,uint16 tag,uint16 ref,char * desc,int32 maxlen)204 DFANgetdesc(const char *filename, uint16 tag, uint16 ref, char *desc,
205 int32 maxlen)
206 {
207 intn ret_value;
208
209 ret_value = (DFANIgetann(filename, tag, ref, (uint8 *) desc, maxlen, DFAN_DESC, 0));
210
211 return ret_value;
212 }
213
214 /*-----------------------------------------------------------------------------
215 * File ID and description input routines
216 *---------------------------------------------------------------------------*/
217
218 /*--------------------------------------------------------------------------
219 NAME
220 DFANgetfidlen -- get length of file label
221 USAGE
222 int32 DFANgetfidlen(file_id, isfirst)
223 int32 file_id; IN: HDF file label returned by Hopen
224 int isfirst; IN: 1 to read the first label in the file
225 0 to read the next label in the file
226 RETURNS
227 Length of file label if successful, and FAIL (-1) otherwise
228 DESCRIPTION
229 Calls DFANIgetfannlen to get label length
230 GLOBAL VARIABLES
231 COMMENTS, BUGS, ASSUMPTIONS
232 When first called for a given file, DFANgetfidlen returns the
233 length of the first file label. In order to get the lengths
234 of successive labels, you must call DFANgetfid between calls
235 to DFANgetfidlen. Otherwise, successive calls to DFANgetfidlen
236 will return the length of the same file label.
237 EXAMPLES
238 REVISION LOG
239 *------------------------------------------------------------------------*/
240 int32
DFANgetfidlen(int32 file_id,int isfirst)241 DFANgetfidlen(int32 file_id, int isfirst)
242 {
243 int32 ret_value;
244
245 ret_value = (DFANIgetfannlen(file_id, DFAN_LABEL, isfirst));
246
247 return ret_value;
248 }
249
250 /*--------------------------------------------------------------------------
251 NAME
252 DFANgetfid -- get next file label
253 USAGE
254 int32 DFANgetfid(file_id, label, maxlen, isfirst)
255 int32 file_id; IN: HDF file label returned by Hopen
256 char *label; OUT: buffer allocated to hold the label
257 int32 maxlen; IN: size of buffer allocated to hold the label
258 int isfirst; IN: 0 to read the next label in the file;
259 1 to read the first label in the file
260 RETURNS
261 On success, length of label; FAIL (-1) otherwise
262 DESCRIPTION
263 Invokes DFANIgetfann to get label
264 GLOBAL VARIABLES
265 COMMENTS, BUGS, ASSUMPTIONS
266 If maxlen is not great enough, the label is truncated to
267 maxlen-1 characters.
268 EXAMPLES
269 REVISION LOG
270 *---------------------------------------------------------------------------*/
271 int32
DFANgetfid(int32 file_id,char * label,int32 maxlen,intn isfirst)272 DFANgetfid(int32 file_id, char *label, int32 maxlen, intn isfirst)
273 {
274 int32 ret_value;
275
276 ret_value = (DFANIgetfann(file_id, label, maxlen, DFAN_LABEL, isfirst));
277
278 return ret_value;
279 }
280
281 /*--------------------------------------------------------------------------
282 NAME
283 DFANgetfdslen -- get length of file description
284 USAGE
285 int32 DFANgetfdslen(file_id, isfirst)
286 int32 file_id; IN: HDF file description returned by Hopen
287 int isfirst; IN: 1 to read the first description in the file
288 0 to read the next description in the file
289 RETURNS
290 Length of file description if successful, and FAIL (-1) otherwise
291 DESCRIPTION
292 Calls DFANIgetfannlen to get description length
293 GLOBAL VARIABLES
294 COMMENTS, BUGS, ASSUMPTIONS
295 When first called for a given file, DFANgetfdslen returns the
296 length of the first file description. In order to get the lengths
297 of successive descriptions, you must call DFANgetfds between calls
298 to DFANgetfdslen. Otherwise, successive calls to DFANgetfdslen
299 will return the length of the same file description.
300 EXAMPLES
301 REVISION LOG
302 *------------------------------------------------------------------------*/
303 int32
DFANgetfdslen(int32 file_id,intn isfirst)304 DFANgetfdslen(int32 file_id, intn isfirst)
305 {
306 int32 ret_value;
307
308 ret_value = (DFANIgetfannlen(file_id, DFAN_DESC, isfirst));
309
310 return ret_value;
311 }
312
313 /*--------------------------------------------------------------------------
314 NAME
315 DFANgetfds -- get next file description
316 USAGE
317 int32 DFANgetfds(file_id, desc, maxlen, isfirst)
318 int32 file_id; IN: HDF file description returned by Hopen
319 char *desc; OUT: buffer allocated to hold the description
320 int32 maxlen; IN: size of buffer allocated to hold the description
321 int isfirst; IN: 0 to read the next description in the file;
322 1 to read the first description in the file
323 RETURNS
324 On success, length of description; FAIL (-1) otherwise
325 DESCRIPTION
326 Invokes DFANIgetfann to get description
327 GLOBAL VARIABLES
328 COMMENTS, BUGS, ASSUMPTIONS
329 If maxlen is not great enough, the description is truncated to
330 maxlen-1 characters.
331 EXAMPLES
332 REVISION LOG
333 *---------------------------------------------------------------------------*/
334 int32
DFANgetfds(int32 file_id,char * desc,int32 maxlen,intn isfirst)335 DFANgetfds(int32 file_id, char *desc, int32 maxlen, intn isfirst)
336 {
337 int32 ret_value;
338
339 ret_value = (DFANIgetfann(file_id, desc, maxlen, DFAN_DESC, isfirst));
340
341 return ret_value;
342 }
343
344 /*-----------------------------------------------------------------------------
345 * HDF object (i.e. tag/ref) label and description output routines
346 *---------------------------------------------------------------------------*/
347
348 /*--------------------------------------------------------------------------
349 NAME
350 DFANputlabel -- Assign a label to the data object with the given
351 tag and reference number
352 USAGE
353 int DFANputlabel(filename, tag, ref, label)
354 char *filename; IN: name of HDF file
355 uint16 tag; IN: tag of item to be assigned the label
356 uint16 ref; IN: reference number of item to be assigned the label
357 char *label; IN: label to write to file; a single string of
358 NULL-terminated text
359 RETURNS
360 SUCCEED (0) if successful and FAIL (-1) otherwise
361 DESCRIPTION
362 Invokes DFANIgetfann to write out label
363 GLOBAL VARIABLES
364 COMMENTS, BUGS, ASSUMPTIONS
365 EXAMPLES
366 REVISION LOG
367 *------------------------------------------------------------------------*/
368 intn
DFANputlabel(const char * filename,uint16 tag,uint16 ref,char * label)369 DFANputlabel(const char *filename, uint16 tag, uint16 ref, char *label)
370 {
371 intn ret_value;
372
373 ret_value = (DFANIputann(filename, tag, ref, (uint8 *) label,
374 (int32) HDstrlen(label), DFAN_LABEL));
375
376 return ret_value;
377 }
378
379 /*--------------------------------------------------------------------------
380 NAME
381 DFANputdesc -- Assign a description to the data object with the given
382 tag and reference number
383 USAGE
384 int DFANputdesc(filename, tag, ref, desc, desclen)
385 char *filename; IN: name of HDF file
386 uint16 tag; IN: tag of item to be assigned the description
387 uint16 ref; IN: ref number of item to be assigned description
388 char *desc; IN: description to write to file; a single string
389 of NULL-terminated text
390 int32 desclen; IN: length of description
391 RETURNS
392 SUCCEED (0) if successful and FAIL (-1) otherwise
393 DESCRIPTION
394 Invokes DFANIgetfann to write out description
395 GLOBAL VARIABLES
396 COMMENTS, BUGS, ASSUMPTIONS
397 The parameter desc can contain any sequence of ASCII characters.
398 It does not have to be a string.
399 EXAMPLES
400 REVISION LOG
401 *------------------------------------------------------------------------*/
402 intn
DFANputdesc(const char * filename,uint16 tag,uint16 ref,char * desc,int32 desclen)403 DFANputdesc(const char *filename, uint16 tag, uint16 ref, char *desc,
404 int32 desclen)
405 {
406 intn ret_value;
407
408 ret_value = (DFANIputann(filename, tag, ref, (uint8 *) desc, desclen, DFAN_DESC));
409
410 return ret_value;
411 }
412
413 /*-----------------------------------------------------------------------------
414 * File ID and description output routines
415 *---------------------------------------------------------------------------*/
416
417 /*--------------------------------------------------------------------------
418 NAME
419 DFANaddfid -- Write a file label to a file
420 USAGE
421 int DFANaddfid(file_id, id)
422 int32 file_id; IN: file identifier
423 char *id; IN: label to write to file
424 RETURNS
425 SUCCEED (0) if successful and FAIL (-1) otherwise
426 DESCRIPTION
427 Invokes DFANIaddfann to write out label
428 GLOBAL VARIABLES
429 COMMENTS, BUGS, ASSUMPTIONS
430 EXAMPLES
431 REVISION LOG
432 *------------------------------------------------------------------------*/
433 intn
DFANaddfid(int32 file_id,char * id)434 DFANaddfid(int32 file_id, char *id)
435 {
436 intn ret_value;
437
438 ret_value = (DFANIaddfann(file_id, id, (int32) HDstrlen(id), DFAN_LABEL));
439
440 return ret_value;
441 }
442
443 /*--------------------------------------------------------------------------
444 NAME
445 DFANaddfds -- Write a file description to a file
446 USAGE
447 int DFANaddfds(file_id, desc, desclen)
448 int32 file_id; IN: file identifier
449 char *desc; IN: description to write to file
450 int32 desclen; IN: length of description
451 RETURNS
452 SUCCEED (0) if successful and FAIL (-1) otherwise
453 DESCRIPTION
454 Invokes DFANIaddfann to write out description
455 GLOBAL VARIABLES
456 COMMENTS, BUGS, ASSUMPTIONS
457 The parameter desc can contain any sequence of ASCII characters.
458 It does not have to be a string.
459 EXAMPLES
460 REVISION LOG
461 *------------------------------------------------------------------------*/
462 intn
DFANaddfds(int32 file_id,char * desc,int32 desclen)463 DFANaddfds(int32 file_id, char *desc, int32 desclen)
464 {
465 intn ret_value;
466
467 ret_value = (DFANIaddfann(file_id, desc, desclen, DFAN_DESC));
468
469 return ret_value;
470 }
471
472 /*-----------------------------------------------------------------------------
473 * Miscellaneous other routines
474 *---------------------------------------------------------------------------*/
475
476 /*--------------------------------------------------------------------------
477 NAME
478 DFANlastref -- Return the reference number of the annotation last
479 written or read
480 USAGE
481 uint16 DFANlastref()
482 RETURNS
483 Reference number if successful and 0 otherwise
484 DESCRIPTION
485 GLOBAL VARIABLES
486 Lastref
487 COMMENTS, BUGS, ASSUMPTIONS
488 EXAMPLES
489 REVISION LOG
490 *------------------------------------------------------------------------*/
491 uint16
DFANlastref(void)492 DFANlastref(void)
493 {
494 uint16 ret_value;
495
496 ret_value = (Lastref);
497
498 return ret_value;
499 }
500
501 /*--------------------------------------------------------------------------
502 NAME
503 DFANlablist -- Return list of refs and labels for a given tag
504 USAGE
505 int DFANlablist(filename, tag, reflist, labellist,
506 listsize, maxlen, startpos)
507 char *filename; IN: name of HDF file
508 uint16 tag; IN: tag to use when searching for ref numbers
509 and labels
510 uint16 reflist[]; OUT: array allocated to place ref numbers in
511 char *labellist; OUT: array of strings allocated to place labels in
512 int listsize; IN: size of ref number list and label list
513 int maxlen; IN: maximum length allocated for label
514 int startpos; IN: Starting position. Beginning from the
515 startpos'th entry, up to listsize entries
516 will be returned.
517 RETURNS
518 Number of ref numbers found if successful and FAIL (-1) otherwise
519 DESCRIPTION
520 Invokes DFANIlablist to get label list.
521 Where there is no corresponding label, the position in
522 labellist is zero filled (C) or blank filled (Fortran).
523 Revised 04/17/90 so that it returns all ref numbers for
524 the given tag, rather than just those that have labels.
525 GLOBAL VARIABLES
526 COMMENTS, BUGS, ASSUMPTIONS
527 EXAMPLES
528 REVISION LOG
529 Revised 04/17/90. (See DESCRIPTION.)
530 *------------------------------------------------------------------------*/
531 intn
DFANlablist(const char * filename,uint16 tag,uint16 reflist[],char * labellist,intn listsize,intn maxlen,intn startpos)532 DFANlablist(const char *filename, uint16 tag, uint16 reflist[], char *labellist,
533 intn listsize, intn maxlen, intn startpos)
534 {
535 intn ret_value;
536
537 ret_value = (DFANIlablist(filename, tag, reflist, (uint8 *) labellist,
538 listsize, maxlen, startpos, 0));
539 return ret_value;
540 }
541
542 /*-------------------------------------------------------------------
543 Name
544 DFANclear -- Clear DFAN interface
545 Usage
546 intn DFANclear()
547 Returns
548 SUCCEED if ok; FAIL otherwise.
549 DESCRIPTION
550 Invokes DFANIclear.
551 GLOBAL VARIABLES
552 COMMENTS, BUGS, ASSUMPTIONS
553 When a file is re-created in a single run by other
554 interface, such as DFSDputdata(), user should
555 call DFANclear to reset DFAN interface structures.
556 EXAMPLES
557 REVISION LOG
558 *------------------------------------------------------------------*/
DFANclear(void)559 intn DFANclear(void)
560 {
561 intn ret_value;
562
563 ret_value = DFANIclear();
564
565 return ret_value;
566 }
567
568 /******************************************************************************/
569 /*----------------------- Internal routines ---------------------------------*/
570 /******************************************************************************/
571
572 /*---------------------------------------------------------------------------
573 Name
574 DFANIclear -- Clear label/desc entries and directories
575 Reset DFANdir[i] and Lastref
576 USAGE
577 intn DFANIclear()
578 Returns
579 SUCCEED if ok; FAIL otherwise.
580 DESCRIPTION
581 Reset DFANdir[i] and Lastref
582 GLOBAL VARIABLES
583 Lastref, DFANdir
584 COMMENTS, BUGS, ASSUMPTIONS
585
586 EXAMPLES
587 REVISION LOG
588
589 *-------------------------------------------------------------------------*/
590 intn
DFANIclear(void)591 DFANIclear(void)
592 {
593 CONSTR(FUNC, "DFANIclear");
594 DFANdirhead *p, *q;
595 intn ret_value = SUCCEED;
596
597 HEclear();
598
599 /* Perform global, one-time initialization */
600 if (library_terminate == FALSE)
601 if(DFANIstart()==FAIL)
602 HGOTO_ERROR(DFE_CANTINIT, FAIL);
603
604 for (p=DFANdir[0]; p!=NULL; p=q) { /* free linked list space */
605 q = p->next;
606 if (p->entries != NULL)
607 HDfree((VOIDP) p->entries);
608 p->nentries=0;
609 p->entries = NULL;
610 p->next=NULL;
611 HDfree((VOIDP) p);
612 }
613 for (p=DFANdir[1]; p!=NULL; p=q) {
614 q = p->next;
615 if (p->entries != NULL)
616 HDfree((VOIDP) p->entries);
617 p->nentries=0;
618 p->entries = NULL;
619 p->next=NULL;
620 HDfree((VOIDP) p);
621 }
622 DFANdir[0] = DFANdir[1] = NULL;
623
624 Lastref = 0; /* 0 is invalid ref */
625
626 done:
627 if(ret_value == FAIL)
628 { /* Error condition cleanup */
629
630 } /* end if */
631
632 /* Normal function cleanup */
633
634 return ret_value;
635 }
636
637 /*--------------------------------------------------------------------------
638 NAME
639 DFANIopen -- open or reopen a file
640 USAGE
641 PRIVATE int32 DFANIopen(filename, acc_mode)
642 char *filename; IN: name of file to open
643 intn acc_mode; IN: access mode
644 RETURNS
645 File identifier if successful and NULL on failure.
646 DESCRIPTION
647 GLOBAL VARIABLES
648 COMMENTS, BUGS, ASSUMPTIONS
649 This is a hook for someday providing more efficient ways to
650 reopen a file, to avoid re-reading all the headers
651
652 EXAMPLES
653 REVISION LOG
654
655 *------------------------------------------------------------------------*/
656 PRIVATE int32
DFANIopen(const char * filename,intn acc_mode)657 DFANIopen(const char *filename, intn acc_mode)
658 {
659 CONSTR(FUNC, "DFANIopen");
660 int32 file_id;
661 DFANdirhead *p, *q;
662 int32 ret_value = SUCCEED;
663
664 HEclear();
665
666 /* Perform global, one-time initialization */
667 if (library_terminate == FALSE)
668 if(DFANIstart()==FAIL)
669 HGOTO_ERROR(DFE_CANTINIT, FAIL);
670
671 /* Check if filename buffer has been allocated */
672 if (Lastfile == NULL)
673 {
674 Lastfile = (char *) HDmalloc((DF_MAXFNLEN + 1) * sizeof(char));
675 if (Lastfile == NULL)
676 HGOTO_ERROR(DFE_NOSPACE, FAIL);
677 *Lastfile = '\0'; /* initialize with 0-length string */
678 }
679
680 /* use reopen if same file as last time - more efficient */
681 if (HDstrncmp(Lastfile, filename, DF_MAXFNLEN) || (acc_mode == DFACC_CREATE))
682 {
683 /* treat create as different file */
684 if (( file_id = Hopen(filename, acc_mode, 0))== FAIL)
685 HGOTO_ERROR(DFE_BADOPEN,FAIL);
686
687 for (p = DFANdir[0]; p != NULL; p = q)
688 { /* free linked list space */
689 q = p->next;
690 if (p->entries != NULL)
691 HDfree((VOIDP) p->entries);
692 p->nentries=0;
693 p->entries = NULL;
694 p->next=NULL;
695 HDfree((VOIDP) p);
696 }
697 for (p = DFANdir[1]; p != NULL; p = q)
698 {
699 q = p->next;
700 if (p->entries != NULL)
701 HDfree((VOIDP) p->entries);
702 p->nentries=0;
703 p->entries = NULL;
704 p->next=NULL;
705 HDfree((VOIDP) p);
706 }
707 DFANdir[0] = DFANdir[1] = NULL;
708 }
709 else
710 {
711 if (( file_id = Hopen(filename, acc_mode, 0))== FAIL)
712 HGOTO_ERROR(DFE_BADOPEN,FAIL);
713 }
714
715 HIstrncpy(Lastfile, filename, DF_MAXFNLEN);
716 /* remember filename, so reopen may be used next time if same file */
717
718 ret_value = file_id;
719
720 done:
721 if(ret_value == FAIL)
722 { /* Error condition cleanup */
723
724 } /* end if */
725
726 /* Normal function cleanup */
727
728 return ret_value;
729 }
730
731 /*--------------------------------------------------------------------------
732 NAME
733 DFANIlocate -- get ref of annotation of given data tag/ref
734 USAGE
735 uint16 DFANIlocate(file_id, type, tag, ref)
736 int32 file_id: IN: pointer to HDF file
737 int type: IN: DFAN_LABEL for labels, DFAN_DESC for descriptions
738 uint16 tag, ref: IN: tag/ref of item for which we want ref of
739 annotation
740
741 RETURNS
742 ref of annotation on if successful; 0 otherwise
743 DESCRIPTION
744 Searches through directory for annotations with given tag/ref. (If
745 there is no directory, it creates one.)
746
747 GLOBAL VARIABLES
748
749 COMMENTS, BUGS, ASSUMPTIONS
750 BUG: When FORTRAN calls this routine with type "label", the string
751 returned is incorrect in length by one character
752 EXAMPLES
753
754 REVISION LOG
755
756 *------------------------------------------------------------------------*/
757 uint16
DFANIlocate(int32 file_id,int type,uint16 tag,uint16 ref)758 DFANIlocate(int32 file_id, int type, uint16 tag, uint16 ref)
759 {
760 CONSTR(FUNC, "DFANIlocate");
761 uint8 datadi[4];
762 int32 more_anns;
763 int32 aid;
764 int32 nanns, i;
765 uint16 anntag, annref = 0;
766 DFANdirhead *p;
767 uint8 *ptr;
768 uint16 ret_value = 0; /* FAIL ? */
769
770 HEclear();
771
772 /* Perform global, one-time initialization */
773 if (library_terminate == FALSE)
774 if(DFANIstart()==FAIL)
775 HGOTO_ERROR(DFE_CANTINIT, (uint16)FAIL);
776
777 anntag = (uint16) ((type == DFAN_LABEL) ? DFTAG_DIL : DFTAG_DIA);
778
779 /* if no directory for this type of annotation, make one */
780 if (DFANdir[type] == NULL)
781 {
782 nanns = Hnumber(file_id, anntag);
783 if (nanns == 0)
784 HGOTO_ERROR(DFE_INTERNAL, 0);
785
786 /* allocate directory space, and space for entries. */
787 DFANdir[type] = (DFANdirhead *) HDmalloc((uint32) sizeof(DFANdirhead));
788 if (DFANdir[type] == NULL)
789 HGOTO_ERROR(DFE_NOSPACE, 0);
790 DFANdir[type]->entries = (DFANdirentry *)
791 HDmalloc( (size_t)nanns * sizeof(DFANdirentry));
792 if (DFANdir[type]->entries == NULL)
793 HGOTO_ERROR(DFE_NOSPACE, 0);
794
795 DFANdir[type]->next = NULL;
796 DFANdir[type]->nentries = nanns;
797
798 /* fill directory table */
799 if (( aid = Hstartread(file_id, anntag, DFREF_WILDCARD))== FAIL)
800 {
801 HGOTO_ERROR(DFE_BADAID, 0);
802 } /* end if */
803 else
804 more_anns = SUCCEED;
805
806 for (i = 0; (i < nanns) && (more_anns != FAIL); i++)
807 {
808 if (FAIL == Hinquire(aid, (int32 *) NULL, (uint16 *) NULL, &annref,
809 (int32 *) NULL, (int32 *) NULL, (int32 *) NULL,
810 (int16 *) NULL, (int16 *) NULL))
811 HGOTO_ERROR(DFE_INTERNAL, 0);
812
813 if ((int32) FAIL == Hread(aid, (int32) 4, datadi))
814 HGOTO_ERROR(DFE_READERROR, 0);
815
816 /* get data tag/ref */
817 DFANdir[type]->entries[i].annref = annref;
818 ptr = (uint8 *) &(datadi[0]);
819 UINT16DECODE(ptr, DFANdir[type]->entries[i].datatag);
820 UINT16DECODE(ptr, DFANdir[type]->entries[i].dataref);
821
822 more_anns = Hnextread(aid, anntag, DFREF_WILDCARD, DF_CURRENT);
823 }
824 Hendaccess(aid);
825 }
826
827 if (!tag)
828 HGOTO_DONE(1);
829
830 /* find annotation that goes with this tag/ref */
831 for (p = (DFANdirhead *) DFANdir[type]; p != NULL; p = p->next)
832 for (i = 0; i < p->nentries; i++)
833 if (p->entries[i].annref != 0)
834 if ((p->entries[i].dataref == ref) && (p->entries[i].datatag == tag))
835 HGOTO_DONE(p->entries[i].annref);
836
837 HERROR(DFE_NOMATCH);
838
839 done:
840 if(ret_value == 0)
841 { /* Error condition cleanup */
842
843 } /* end if */
844 /* Normal function cleanup */
845
846 return ret_value;
847 }
848
849 /*--------------------------------------------------------------------------
850 NAME
851 DFANIaddentry -- add entry to annotation directory
852 USAGE
853 int type: IN: DFAN_LABEL for labels, DFAN_DESC for descriptions
854 uint16 annref: IN: ref of annotation
855 uint16 datatag,: IN: tag of item of which this is annotation
856 uint16 dataref; IN: ref of item of which this is annotation
857
858 RETURNS
859 SUCCEED (0) if successful and FAIL (-1) otherwise
860 DESCRIPTION
861 Moves to end of directory and appends entry.
862 GLOBAL VARIABLES
863 COMMENTS, BUGS, ASSUMPTIONS
864 EXAMPLES
865 REVISION LOG
866 *------------------------------------------------------------------------*/
867 int
DFANIaddentry(int type,uint16 annref,uint16 datatag,uint16 dataref)868 DFANIaddentry(int type, uint16 annref, uint16 datatag, uint16 dataref)
869 {
870 CONSTR(FUNC, "DFANIaddentry");
871 int32 i;
872 DFANdirhead *p, *q;
873 int ret_value = SUCCEED;
874
875 HEclear();
876
877 /* Perform global, one-time initialization */
878 if (library_terminate == FALSE)
879 if(DFANIstart()==FAIL)
880 HGOTO_ERROR(DFE_CANTINIT, FAIL);
881
882 /* move to last entry in list */
883 for (p = DFANdir[type]; (p != NULL) && (p->next != NULL); p = p->next)
884 ;
885
886 if (p)
887 { /* not new list */
888 for (i = 0; i < p->nentries; i++) /* check all entries */
889 if (p->entries[i].annref == 0)
890 { /* empty slot */
891 p->entries[i].annref = annref; /* store entry */
892 p->entries[i].datatag = datatag;
893 p->entries[i].dataref = dataref;
894 HGOTO_DONE(SUCCEED);
895 }
896 }
897
898 /* need new list or new node in list */
899 /* allocate directory space and space for entries. */
900 if ((q = (DFANdirhead *) HDmalloc((uint32) sizeof(DFANdirhead))) == NULL)
901 HGOTO_ERROR(DFE_NOSPACE,FAIL);
902 q->entries = (DFANdirentry *) HDmalloc( DFAN_DEFENTRIES * sizeof(DFANdirentry));
903 if (q->entries == NULL)
904 HGOTO_ERROR(DFE_NOSPACE,FAIL);
905
906 q->next = NULL;
907 q->nentries = DFAN_DEFENTRIES;
908 if (!p)
909 DFANdir[type] = q; /* set pointer to this new node */
910 else
911 p->next = q;
912
913 /* store entry */
914 q->entries[0].annref = annref;
915 q->entries[0].datatag = datatag;
916 q->entries[0].dataref = dataref;
917
918 for (i = 1; i < DFAN_DEFENTRIES; i++) /* mark rest unused */
919 q->entries[i].annref = 0;
920
921 done:
922 if(ret_value == FAIL)
923 { /* Error condition cleanup */
924
925 } /* end if */
926 /* Normal function cleanup */
927
928 return ret_value;
929 }
930
931 /*--------------------------------------------------------------------------
932 NAME
933 DFANIgetannlen -- get length of annotation of tag/ref
934 USAGE
935 int32 DFANIgetannlen(filename, tag, ref, type)
936 char *filename; IN: name of HDF file
937 int32 tag, ref; IN: tag/ref of item of which we want annotation
938 int type; IN: DFAN_LABEL for labels, DFAN_DESC for descriptions
939 RETURNS
940 length of annotation if successful and FAIL (-1) otherwise
941 DESCRIPTION
942 Calls DFANIlocate to get ref of annotation.
943 Calls Hlength to get its length.
944 GLOBAL VARIABLES
945 Lastref
946 COMMENTS, BUGS, ASSUMPTIONS
947 EXAMPLES
948 REVISION LOG
949 *------------------------------------------------------------------------*/
950 int32
DFANIgetannlen(const char * filename,uint16 tag,uint16 ref,int type)951 DFANIgetannlen(const char *filename, uint16 tag, uint16 ref, int type)
952 {
953 CONSTR(FUNC, "DFANIgetannlen");
954 int32 file_id, annlength;
955 uint16 anntag, annref;
956 int32 ret_value = SUCCEED;
957
958 HEclear();
959
960 /* Perform global, one-time initialization */
961 if (library_terminate == FALSE)
962 if(DFANIstart()==FAIL)
963 HGOTO_ERROR(DFE_CANTINIT, FAIL);
964
965 if (!tag)
966 HGOTO_ERROR(DFE_BADTAG,FAIL);
967
968 if (!ref)
969 HGOTO_ERROR(DFE_BADREF,FAIL);
970
971 if (( file_id = DFANIopen(filename, DFACC_READ))== FAIL)
972 HGOTO_ERROR(DFE_BADOPEN,FAIL);
973
974 /* get ref of annotation of tag/ref */
975 annref = DFANIlocate(file_id, type, tag, ref);
976 if (annref == 0)
977 HCLOSE_GOTO_ERROR(file_id,DFE_INTERNAL,FAIL);
978 anntag = (uint16) ((type == DFAN_LABEL) ? DFTAG_DIL : DFTAG_DIA); /* set type tag */
979
980 annlength = Hlength(file_id, anntag, annref) - 4; /* 4=len of data tag/ref */
981 if (annlength == FAIL)
982 HCLOSE_GOTO_ERROR(file_id,DFE_BADLEN,FAIL);
983 Lastref = annref; /* remember ref last accessed */
984 if (Hclose(file_id) == FAIL) /* close file */
985 ret_value = FAIL;
986
987 ret_value = annlength;
988
989 done:
990 if(ret_value == FAIL)
991 { /* Error condition cleanup */
992
993 } /* end if */
994
995 /* Normal function cleanup */
996
997 return ret_value;
998 }
999
1000 /*--------------------------------------------------------------------------
1001 NAME
1002 DFANIgetann -- get annotation of tag/ref
1003 USAGE
1004 intn DFANIgetann(filename, tag, ref, ann, maxlen, type)
1005 char *filename; IN: name of HDF file
1006 uint16 tag, ref; IN: tag/ref of item of which we want annotation
1007 uint8 *ann; OUT: space to return annotation in
1008 int32 maxlen; IN: size of space to return annotation in
1009 int type; IN: DFAN_LABEL for labels, DFAN_DESC for descriptions
1010 int isfortran; IN: 0 if C, 1 if Fortran
1011 RETURNS
1012 SUCCEED (0) if successful and FAIL (-1) otherwise
1013 DESCRIPTION
1014 Gets tag and ref of annotation. Finds DD for that annotation.
1015 Reads the annotation, taking care of NULL terminator, if necessary.
1016 GLOBAL VARIABLES
1017 Lastref.
1018 COMMENTS, BUGS, ASSUMPTIONS
1019 BUG 1640: Added isfortran flag to avoid termination of the string with
1020 the null character when the routine is call from FORTRAN.
1021 EXAMPLES
1022 REVISION LOG
1023 *------------------------------------------------------------------------*/
1024 intn
DFANIgetann(const char * filename,uint16 tag,uint16 ref,uint8 * ann,int32 maxlen,int type,int isfortran)1025 DFANIgetann(const char *filename, uint16 tag, uint16 ref, uint8 *ann,
1026 int32 maxlen, int type, int isfortran)
1027 {
1028 CONSTR(FUNC, "DFANIgetann");
1029 int32 file_id, aid;
1030 int32 annlen;
1031 uint16 anntag, annref;
1032 uint8 datadi[4]; /* to read in and discard data/ref! */
1033 intn ret_value = SUCCEED;
1034
1035 HEclear();
1036
1037 /* Perform global, one-time initialization */
1038 if (library_terminate == FALSE)
1039 if(DFANIstart()==FAIL)
1040 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1041
1042 if (!ann)
1043 HGOTO_ERROR(DFE_BADPTR,FAIL);
1044
1045 if (!tag)
1046 HGOTO_ERROR(DFE_BADTAG,FAIL);
1047
1048 if (!ref)
1049 HGOTO_ERROR(DFE_BADREF,FAIL);
1050
1051 if (( file_id = DFANIopen(filename, DFACC_READ))== FAIL)
1052 HGOTO_ERROR(DFE_BADOPEN,FAIL);
1053
1054 /* get annref and anntag of annotation of tag/ref */
1055 annref = DFANIlocate(file_id, type, tag, ref);
1056 if (annref == 0)
1057 HCLOSE_GOTO_ERROR(file_id,DFE_INTERNAL,FAIL);
1058 anntag = (uint16) ((type == DFAN_LABEL) ? DFTAG_DIL : DFTAG_DIA);
1059
1060 /* find DD for that annotation */
1061 aid = Hstartread(file_id, anntag, annref);
1062 if (aid == FAIL)
1063 HCLOSE_GOTO_ERROR(file_id,DFE_BADAID,FAIL);
1064
1065 if (FAIL == Hinquire(aid, (int32 *) NULL, (uint16 *) NULL, (uint16 *) NULL,
1066 &annlen, (int32 *) NULL, (int32 *) NULL, (int16 *) NULL,
1067 (int16 *) NULL))
1068 {
1069 Hendaccess(aid);
1070 HCLOSE_GOTO_ERROR(file_id,DFE_INTERNAL,FAIL);
1071 }
1072 annlen -= 4; /* first four bytes were tag/ref, so they don't count */
1073
1074 /* check length, if not enough space, truncate annotation */
1075 /* In C labels need space for null terminator, descriptions don't */
1076 if (isfortran)
1077 {
1078 if (annlen > maxlen )
1079 annlen = maxlen;
1080 }
1081 else
1082 if (type == DFAN_LABEL)
1083 {
1084 if (annlen > maxlen - 1)
1085 annlen = maxlen - 1;
1086 }
1087 else
1088 {
1089 if (annlen > maxlen)
1090 annlen = maxlen;
1091 }
1092
1093 /* read annotation */
1094 if ((int32) FAIL == Hread(aid, (int32) 4, datadi))
1095 { /* go past tag/ref */
1096 Hendaccess(aid);
1097 HCLOSE_GOTO_ERROR(file_id,DFE_READERROR,FAIL);
1098 }
1099 if ((int32) FAIL == Hread(aid, annlen, ann))
1100 { /* read the annotation */
1101 Hendaccess(aid);
1102 HCLOSE_GOTO_ERROR(file_id,DFE_READERROR,FAIL);
1103 }
1104 /* add null for C */
1105 if (type == DFAN_LABEL)
1106 if (!isfortran)
1107 ann[annlen] = '\0'; /* terminate string properly for C */
1108
1109 Lastref = annref; /* remember ref last accessed */
1110 Hendaccess(aid);
1111 ret_value = (Hclose(file_id));
1112
1113 done:
1114 if(ret_value == FAIL)
1115 { /* Error condition cleanup */
1116
1117 } /* end if */
1118 /* Normal function cleanup */
1119
1120 return ret_value;
1121 }
1122
1123 /*--------------------------------------------------------------------------
1124 NAME
1125 DFANIputann -- put annotation of tag/ref into file
1126 USAGE
1127 intn DFANIputann(filename, tag, ref, ann, annlen, type)
1128 char *filename; IN: name of HDF file
1129 uint16 tag, ref; IN: tag/ref of item of which this is the annotation
1130 uint8 *ann; IN: space to return annotation in
1131 int32 annlen; IN: length of annotation
1132 int type; IN: DFAN_LABEL for labels, DFAN_DESC for descriptions
1133
1134 RETURNS
1135 SUCCEED (0) if successful and FAIL (-1) otherwise
1136 DESCRIPTION
1137 Checks for pre-existence of annotation, replacing old one if it
1138 exists. Writes out annotation, and updates directory..
1139 GLOBAL VARIABLES
1140 Lastref.
1141 COMMENTS, BUGS, ASSUMPTIONS
1142 If the given object already has this type of annotation, it replaces
1143 the old annotation with this one.
1144 EXAMPLES
1145 REVISION LOG
1146 *------------------------------------------------------------------------*/
1147 intn
DFANIputann(const char * filename,uint16 tag,uint16 ref,uint8 * ann,int32 annlen,int type)1148 DFANIputann(const char *filename, uint16 tag, uint16 ref, uint8 *ann,
1149 int32 annlen, int type)
1150 {
1151 CONSTR(FUNC, "DFANIputann");
1152 int32 file_id, aid;
1153 int newflag = 0;
1154 uint16 anntag, annref;
1155 uint8 datadi[4]; /* to hold data tag/ref for writing */
1156 uint8 *ptr;
1157 intn ret_value = SUCCEED;
1158
1159 HEclear();
1160
1161 /* Perform global, one-time initialization */
1162 if (library_terminate == FALSE)
1163 if(DFANIstart()==FAIL)
1164 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1165
1166 if (!ann)
1167 HGOTO_ERROR(DFE_BADPTR,FAIL);
1168
1169 if (!tag)
1170 HGOTO_ERROR(DFE_BADTAG,FAIL);
1171
1172 if (!ref)
1173 HGOTO_ERROR(DFE_BADREF,FAIL);
1174
1175 if (( file_id = DFANIopen(filename, DFACC_RDWR))== 0)
1176 HGOTO_ERROR(DFE_BADOPEN,FAIL);
1177
1178 anntag = (uint16) ((type == DFAN_LABEL) ? DFTAG_DIL : DFTAG_DIA);
1179
1180 /* check if this tag/ref already has this type of annotation */
1181 annref = DFANIlocate(file_id, type, tag, ref);
1182 if (annref == 0)
1183 {
1184 annref = Htagnewref(file_id,anntag);
1185 if (annref == 0)
1186 HCLOSE_GOTO_ERROR(file_id,DFE_NOREF,FAIL);
1187 newflag = 1; /* remember to add ann tag/ref to directory */
1188 }
1189
1190 /*
1191 * if annotation exists, reuse tag/ref and rewrite new annotation
1192 */
1193 if (newflag == 0)
1194 { /* does prev annotation exist? */
1195 if (HDreuse_tagref(file_id, anntag, annref) == FAIL)
1196 {
1197 Hclose(file_id);
1198 HEreport("Unable to replace old annotation");
1199 HGOTO_DONE(FAIL);
1200 }
1201 }
1202
1203 /* put annotation */
1204 /* Note: cannot use DFputelement because need to write data tag/ref */
1205 aid = Hstartwrite(file_id, anntag, annref, annlen + 4);
1206 if (aid == FAIL)
1207 {
1208 Hendaccess(aid);
1209 HCLOSE_GOTO_ERROR(file_id,DFE_BADAID,FAIL);
1210 }
1211
1212 /* write annotation */
1213 ptr = (uint8 *) &(datadi[0]); /* first, write the object's tag/ref */
1214 UINT16ENCODE(ptr, tag);
1215 UINT16ENCODE(ptr, ref);
1216 if ((int32) FAIL == Hwrite(aid, (int32) 4, datadi))
1217 HCLOSE_GOTO_ERROR(file_id,DFE_WRITEERROR,FAIL);
1218 if ((int32) FAIL == Hwrite(aid, annlen, ann))
1219 { /* then write the annotation */
1220 Hendaccess(aid);
1221 HCLOSE_GOTO_ERROR(file_id,DFE_WRITEERROR,FAIL);
1222 }
1223
1224 /* put annotation tag/ref into directory if new */
1225 if (newflag)
1226 {
1227 if (FAIL == DFANIaddentry(type, annref, tag, ref))
1228 {
1229 Hendaccess(aid);
1230 HCLOSE_GOTO_ERROR(file_id,DFE_INTERNAL,FAIL);
1231 }
1232 }
1233
1234 Lastref = annref; /* remember ref last accessed */
1235 Hendaccess(aid);
1236 ret_value = (Hclose(file_id));
1237
1238 done:
1239 if(ret_value == FAIL)
1240 { /* Error condition cleanup */
1241
1242 } /* end if */
1243 /* Normal function cleanup */
1244
1245 return ret_value;
1246 }
1247
1248 /*--------------------------------------------------------------------------
1249 NAME
1250 DFANIlablist -- Return list of refs and labels for a given tag
1251 USAGE
1252 int DFANlablist(filename, tag, reflist, labellist,
1253 listsize, maxlen, startpos)
1254 char *filename; IN: name of HDF file
1255 uint16 tag; IN: tag to use when searching for ref numbers
1256 and labels
1257 uint16 reflist[]; OUT: array allocated to place ref numbers in
1258 char *labellist; OUT: array of strings allocated to place labels in
1259 int listsize; IN: size of ref number list and label list
1260 int maxlen; IN: maximum length allocated for label
1261 int startpos; IN: Starting position. Beginning from the
1262 startpos'th entry, up to listsize entries
1263 will be returned.
1264 int isfortran: 0 if C, 1 if Fortran
1265 RETURNS
1266 Number of ref numbers found if successful and FAIL (-1) otherwise
1267 DESCRIPTION
1268 Where there is no corresponding label, the position in
1269 labellist is zero filled (C) or blank filled (Fortran).
1270 Revised 04/17/90 so that it returns all ref numbers for
1271 the given tag, rather than just those that have labels.
1272 GLOBAL VARIABLES
1273 COMMENTS, BUGS, ASSUMPTIONS
1274 EXAMPLES
1275 REVISION LOG
1276 Revised 04/17/90. (See DESCRIPTION.)
1277 *------------------------------------------------------------------------*/
1278 intn
DFANIlablist(const char * filename,uint16 tag,uint16 reflist[],uint8 * labellist,int listsize,int maxlen,int startpos,int isfortran)1279 DFANIlablist(const char *filename, uint16 tag, uint16 reflist[],
1280 uint8 *labellist, int listsize, int maxlen, int startpos,
1281 int isfortran)
1282 {
1283 CONSTR(FUNC, "DFANIlablist");
1284 int32 i;
1285 int j, k;
1286 int32 file_id, aid, len;
1287 uint16 ref=0;
1288 DFANdirhead *p;
1289 uint8 *lp; /* pointer to label */
1290 intn nrefs, nlabs;
1291 uint8 labeldi[4]; /* to read in and discard data/ref */
1292 intn ret_value = SUCCEED;
1293
1294 HEclear();
1295
1296 /* Perform global, one-time initialization */
1297 if (library_terminate == FALSE)
1298 if(DFANIstart()==FAIL)
1299 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1300
1301 if (!reflist || !labellist)
1302 HGOTO_ERROR(DFE_BADPTR,FAIL);
1303
1304 if (!tag)
1305 HGOTO_ERROR(DFE_BADTAG,FAIL);
1306
1307 if (( file_id = DFANIopen(filename, DFACC_READ))== 0)
1308 HGOTO_ERROR(DFE_BADOPEN,FAIL);
1309
1310 /* clear labellist. pad with blanks for Fortran; add null for C */
1311 if (isfortran)
1312 HDmemset(labellist, ' ', (uint32) maxlen * (uint32) listsize);
1313 else
1314 HDmemset(labellist, '\0', (uint32) maxlen * (uint32) listsize);
1315
1316 /* find all refs for this tag; store them in reflist */
1317 nrefs = (intn) Hnumber(file_id, tag); /* how many times is tag in file? */
1318 if (nrefs == FAIL)
1319 HCLOSE_GOTO_ERROR(file_id,DFE_NOMATCH,FAIL);
1320
1321 aid = Hstartread(file_id, tag, DFREF_WILDCARD); /* set search for refs */
1322 if (aid == FAIL)
1323 HCLOSE_GOTO_ERROR(file_id,DFE_BADAID,FAIL);
1324
1325 for (i = 0, j = 0; i < nrefs && j < listsize; i++)
1326 {
1327 if (HQuerytagref(aid, (uint16 *) NULL, &ref) == FAIL)
1328 {
1329 Hendaccess(aid);
1330 HCLOSE_GOTO_ERROR(file_id,DFE_NOMATCH,FAIL);
1331 }
1332 if (i >= startpos - 1)
1333 reflist[j++] = ref; /* store next ref in reflist */
1334 Hnextread(aid, tag, DFREF_WILDCARD, DF_CURRENT);
1335 }
1336 nrefs = j;
1337 Hendaccess(aid);
1338
1339 /* get directory of all labels */
1340
1341 nlabs = (intn) Hnumber(file_id, DFTAG_DIL);
1342 if (nlabs != 0)
1343 {
1344 if (DFANdir[DFAN_LABEL] == NULL)
1345 { /* if no dir info create dir */
1346 if (0 == DFANIlocate(file_id, DFAN_LABEL, 0, 0))
1347 {
1348 Hendaccess(aid);
1349 HCLOSE_GOTO_ERROR(file_id,DFE_INTERNAL,FAIL);
1350 }
1351 }
1352
1353 lp = labellist;
1354
1355 /* Look through all labels. Get those that correspond to the tag,
1356 and match them with corresponding tag/refs in the reflist. */
1357 for (p = DFANdir[DFAN_LABEL]; p != NULL; p = p->next)
1358 { /* for each ann dir */
1359 for (i = 0; i < p->nentries; i++)
1360 { /* for each tag in dir */
1361 if (p->entries[i].datatag == tag)
1362 { /* if this tag==our tag */
1363
1364 aid = Hstartread(file_id, DFTAG_DIL, p->entries[i].annref);
1365 if (aid == FAIL)
1366 HCLOSE_GOTO_ERROR(file_id,DFE_BADAID,FAIL);
1367 if ((int32) FAIL == Hread(aid, (int32) 4, labeldi))
1368 { /* data tag/ref */
1369 Hendaccess(aid);
1370 HCLOSE_GOTO_ERROR(file_id,DFE_READERROR,FAIL);
1371 }
1372 /* look for corresponding ref in reflist */
1373 for (k = 0; k < nrefs && p->entries[i].dataref != reflist[k]; k++)
1374 ;
1375 if (k < nrefs)
1376 { /* if ref found */
1377
1378 lp = labellist + k * maxlen; /* get pos to copy to */
1379
1380 /* note len on read may be too big, but OK for DFread */
1381 len = Hread(aid, (int32) (maxlen - 1), lp);
1382 if (len == FAIL)
1383 {
1384 Hendaccess(aid);
1385 HCLOSE_GOTO_ERROR(file_id,DFE_READERROR,FAIL);
1386 }
1387 /* ret now contains actual length read */
1388 /* pad with blanks for Fortran; add null for C */
1389 if (isfortran)
1390 while (len++ < maxlen)
1391 lp[len] = ' ';
1392 else
1393 lp[len] = '\0';
1394 }
1395 Hendaccess(aid);
1396 } /* tag == our tag */
1397 } /* for each tag in dir */
1398 } /* for each ann dir */
1399 } /* nlabs != 0 */
1400 if (FAIL == Hclose(file_id)) /* close file */
1401 ret_value = FAIL;
1402 else
1403 ret_value = nrefs;
1404
1405 done:
1406 if(ret_value == FAIL)
1407 { /* Error condition cleanup */
1408
1409 } /* end if */
1410
1411 /* Normal function cleanup */
1412
1413 return ret_value;
1414 }
1415
1416 /*--------------------------------------------------------------------------
1417 NAME
1418 DFANaddfann -- Write a file label or description to a file
1419 USAGE
1420 int DFANaddfid(file_id, id)
1421 int32 file_id; IN: pointer to HDF file
1422 char *ann; IN: annotation to write to file
1423 int32 annlen: IN: length of annotation
1424 int type: IN: DFAN_LABEL for labels, DFAN_DESC for descriptions
1425 RETURNS
1426 SUCCEED (0) if successful and FAIL (-1) otherwise
1427 DESCRIPTION
1428 Calls Hputelement to putput the annotation.
1429 GLOBAL VARIABLES
1430 Lastref
1431 COMMENTS, BUGS, ASSUMPTIONS
1432 EXAMPLES
1433 REVISION LOG
1434 *------------------------------------------------------------------------*/
1435 int
DFANIaddfann(int32 file_id,char * ann,int32 annlen,int type)1436 DFANIaddfann(int32 file_id, char *ann, int32 annlen, int type)
1437 {
1438 CONSTR(FUNC, "DFANIaddfann");
1439 uint16 anntag, annref;
1440 int ret_value = SUCCEED;
1441
1442 HEclear();
1443
1444 /* Perform global, one-time initialization */
1445 if (library_terminate == FALSE)
1446 if(DFANIstart()==FAIL)
1447 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1448
1449 if (!ann)
1450 HGOTO_ERROR(DFE_BADPTR,FAIL);
1451
1452 anntag = (uint16) ((type == DFAN_LABEL) ? DFTAG_FID : DFTAG_FD);
1453
1454 annref = Htagnewref(file_id,anntag);
1455 if (annref == 0)
1456 HGOTO_ERROR(DFE_NOREF,FAIL);
1457
1458 /* write out annotation */
1459 if (FAIL == Hputelement(file_id, anntag, annref, (uint8 *) ann, annlen))
1460 HGOTO_ERROR(DFE_PUTELEM,FAIL);
1461
1462 Lastref = annref; /* remember ref last accessed */
1463
1464 done:
1465 if(ret_value == FAIL)
1466 { /* Error condition cleanup */
1467
1468 } /* end if */
1469 /* Normal function cleanup */
1470
1471 return ret_value;
1472 }
1473
1474 /*--------------------------------------------------------------------------
1475 NAME
1476 DFANIgetfannlen -- get length of next file annotation
1477 USAGE
1478 int32 DFANIgetannlen(filename, tag, ref, type)
1479 int32 file_id; IN: id of HDF file
1480 int type; IN: DFAN_LABEL for labels, DFAN_DESC for descriptions
1481 int isfirst; IN: 1: start with first one; 0: get next one
1482 RETURNS
1483 length of annotation if successful and FAIL (-1) otherwise
1484 DESCRIPTION
1485 Uses isfirst and Next_label_ref (or Next_desc_ref) to determine
1486 which annotation to pick up next.
1487 GLOBAL VARIABLES
1488 Lastref
1489 Next_label_ref
1490 Next_desc_ref
1491 COMMENTS, BUGS, ASSUMPTIONS
1492 EXAMPLES
1493 REVISION LOG
1494 *------------------------------------------------------------------------*/
1495 int32
DFANIgetfannlen(int32 file_id,int type,int isfirst)1496 DFANIgetfannlen(int32 file_id, int type, int isfirst)
1497 {
1498 CONSTR(FUNC, "DFANIgetfannlen");
1499 uint16 anntag, annref;
1500 int32 aid;
1501 int32 length;
1502 int32 ret_value = SUCCEED;
1503
1504 HEclear();
1505
1506 /* Perform global, one-time initialization */
1507 if (library_terminate == FALSE)
1508 if(DFANIstart()==FAIL)
1509 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1510
1511 /* Identify tag for this "type" of access; determine which ref to key on. */
1512 if (type == DFAN_LABEL)
1513 {
1514 anntag = DFTAG_FID;
1515 annref = (uint16) ((isfirst == 1) ? DFREF_WILDCARD : Next_label_ref);
1516 }
1517 else
1518 {
1519 anntag = DFTAG_FD;
1520 annref = (uint16) ((isfirst == 1) ? DFREF_WILDCARD : Next_desc_ref);
1521 }
1522 aid = Hstartread(file_id, anntag, annref);
1523 if (aid == FAIL)
1524 HGOTO_ERROR(DFE_BADAID, FAIL);
1525 if (FAIL == Hinquire(aid, (int32 *) NULL, (uint16 *) NULL, &annref, &length,
1526 (int32 *) NULL, (int32 *) NULL, (int16 *) NULL, (int16 *) NULL))
1527 {
1528 Hendaccess(aid);
1529 HGOTO_ERROR(DFE_NOMATCH, FAIL);
1530 }
1531 if (type == DFAN_LABEL) /* prepare for next call */
1532 Next_label_ref = annref;
1533 else
1534 Next_desc_ref = annref;
1535
1536 Hendaccess(aid);
1537 Lastref = annref; /* remember ref last accessed */
1538
1539 if (length >= 0) /* (length == 0) => no length found */
1540 ret_value = length;
1541 else
1542 HGOTO_ERROR(DFE_NOMATCH,FAIL);
1543
1544 done:
1545 if(ret_value == FAIL)
1546 { /* Error condition cleanup */
1547
1548 } /* end if */
1549 /* Normal function cleanup */
1550
1551 return ret_value;
1552 }
1553
1554 /*--------------------------------------------------------------------------
1555 NAME
1556 DFANIgetfann -- get next file annotation (file ID or file description)
1557 USAGE
1558 intn DFANIgetfann(filename, tag, ref, ann, maxlen, type)
1559 int32 file_id; IN: id of HDF file
1560 uint8 *ann; OUT: space to return annotation in
1561 int32 annlen; IN: size of space to return annotation in
1562 int type; IN: DFAN_LABEL for labels, DFAN_DESC for descriptions
1563 int isfirst; IN: 1: start with first one; 0: get next one
1564
1565 RETURNS
1566 Length of annotation if successful and FAIL (-1) otherwise
1567 DESCRIPTION
1568 Gets tag and ref of annotation. Finds DD for that annotation.
1569 Reads the annotation, taking care of NULL terminator, if necessary.
1570 GLOBAL VARIABLES
1571 Lastref, Next_desc_ref, Next_label_ref
1572 COMMENTS, BUGS, ASSUMPTIONS
1573 If maxlen not great enough, ann is truncated to maxlen-1 chars
1574 BUG: If ref is high possible ref value, setting of Next_label_ref
1575 or Next_desc_ref behave unpredictably.
1576 EXAMPLES
1577 REVISION LOG
1578 *---------------------------------------------------------------------------*/
1579 int32
DFANIgetfann(int32 file_id,char * ann,int32 maxlen,int type,int isfirst)1580 DFANIgetfann(int32 file_id, char *ann, int32 maxlen, int type,
1581 int isfirst)
1582 {
1583 CONSTR(FUNC, "DFANIgetfann");
1584 uint16 anntag, annref;
1585 int32 length, aid;
1586 int32 ret_value = SUCCEED;
1587
1588 HEclear();
1589
1590 /* Perform global, one-time initialization */
1591 if (library_terminate == FALSE)
1592 if(DFANIstart()==FAIL)
1593 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1594
1595 if (!ann)
1596 HGOTO_ERROR(DFE_BADPTR,FAIL);
1597
1598 /* Identify tag for this "type" of access; determine which ref to key on. */
1599 if (type == DFAN_LABEL)
1600 {
1601 anntag = DFTAG_FID;
1602 annref = (uint16) ((isfirst == 1) ? DFREF_WILDCARD : Next_label_ref);
1603 }
1604 else
1605 {
1606 anntag = DFTAG_FD;
1607 annref = (uint16) ((isfirst == 1) ? DFREF_WILDCARD : Next_desc_ref);
1608 }
1609
1610 if (( aid = Hstartread(file_id, anntag, annref))== FAIL)
1611 HGOTO_ERROR(DFE_BADAID, FAIL);
1612 if (FAIL == Hinquire(aid, (int32 *) NULL, (uint16 *) NULL, &annref, &length,
1613 (int32 *) NULL, (int32 *) NULL, (int16 *) NULL, (int16 *) NULL))
1614 {
1615 Hendaccess(aid);
1616 HGOTO_ERROR(DFE_NOMATCH, FAIL);
1617 }
1618 length = (length > maxlen) ? maxlen : length; /* truncate if too long */
1619
1620 if ((int32) FAIL == Hread(aid, length, (uint8 *) ann)) /* get the annotation */
1621 {
1622 Hendaccess(aid);
1623 HGOTO_ERROR(DFE_READERROR, FAIL);
1624 }
1625
1626 if (length > maxlen - 1)
1627 length = maxlen - 1;
1628
1629 ann[length] = '\0';
1630
1631 Lastref = annref; /* remember ref last accessed */
1632
1633 /* prepare for next call */
1634 if (FAIL == Hnextread(aid, anntag, DFREF_WILDCARD, DF_CURRENT))
1635 { /* If no more of them, set Next_ ???_ref */
1636 if (type == DFAN_LABEL) /* to one higher than current value */
1637 Next_label_ref++; /* so that next call will fail. */
1638 else
1639 Next_desc_ref++;
1640 }
1641 else
1642 { /* Otherwise save the next ref */
1643 if (FAIL == Hinquire(aid, (int32 *) NULL, (uint16 *) NULL, &annref,
1644 (int32 *) NULL, (int32 *) NULL, (int32 *) NULL,
1645 (int16 *) NULL, (int16 *) NULL))
1646 {
1647 Hendaccess(aid);
1648 HGOTO_ERROR(DFE_NOMATCH, FAIL);
1649 }
1650 if (type == DFAN_LABEL)
1651 Next_label_ref = annref;
1652 else
1653 Next_desc_ref = annref;
1654 }
1655
1656 Hendaccess(aid);
1657
1658 done:
1659 if(ret_value == FAIL)
1660 { /* Error condition cleanup */
1661
1662 } /* end if */
1663 else
1664 ret_value = length;
1665
1666 /* Normal function cleanup */
1667
1668 return ret_value;
1669 }
1670
1671 /*--------------------------------------------------------------------------
1672 NAME
1673 DFANIstart
1674 PURPOSE
1675 DFAN-level initialization routine
1676 USAGE
1677 intn DFANIstart()
1678 RETURNS
1679 Returns SUCCEED/FAIL
1680 DESCRIPTION
1681 Register the shut-down routine (DFANPshutdown) for call with atexit
1682 GLOBAL VARIABLES
1683 COMMENTS, BUGS, ASSUMPTIONS
1684 EXAMPLES
1685 REVISION LOG
1686 --------------------------------------------------------------------------*/
DFANIstart(void)1687 PRIVATE intn DFANIstart(void)
1688 {
1689 CONSTR(FUNC, "DFANIstart"); /* for HERROR */
1690 intn ret_value = SUCCEED;
1691
1692 /* Don't call this routine again... */
1693 library_terminate = TRUE;
1694
1695 /* Install atexit() library cleanup routine */
1696 if (HPregister_term_func(&DFANPshutdown) != 0)
1697 HGOTO_ERROR(DFE_CANTINIT, FAIL);
1698
1699 done:
1700 if(ret_value == FAIL)
1701 { /* Error condition cleanup */
1702
1703 } /* end if */
1704
1705 /* Normal function cleanup */
1706
1707 return(ret_value);
1708 } /* end DFANIstart() */
1709
1710 /*--------------------------------------------------------------------------
1711 NAME
1712 DFANPshutdown
1713 PURPOSE
1714 Terminate various static buffers.
1715 USAGE
1716 intn DFANPshutdown()
1717 RETURNS
1718 Returns SUCCEED/FAIL
1719 DESCRIPTION
1720 Free various buffers allocated in the DFAN routines.
1721 GLOBAL VARIABLES
1722 COMMENTS, BUGS, ASSUMPTIONS
1723 Should only ever be called by the "atexit" function HDFend
1724 EXAMPLES
1725 REVISION LOG
1726 --------------------------------------------------------------------------*/
DFANPshutdown(void)1727 intn DFANPshutdown(void)
1728 {
1729 DFANIclear(); /* frees the directory lists */
1730
1731 if(Lastfile!=NULL)
1732 {
1733 HDfree(Lastfile);
1734 Lastfile=NULL;
1735 } /* end if */
1736 return(SUCCEED);
1737 } /* end DFANPshutdown() */
1738
1739