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 * vsetf.c
18 * Part of the HDF VSet interface.
19 *
20 
21 LOCAL ROUTINES
22 
23 EXPORTED ROUTINES
24  VSIZEOF      -- returns the machine size of a field type.
25  VSsetfields  -- sets the fields in a vdata for reading or writing.
26                  Truncates each field to max length of FIELDNAMELENMAX.
27  VSfdefine    -- Defines a (one) new field within the vdata.
28  VFnfields    -- Return the number of fields in this Vdata.
29  VFfieldname  -- Return the name of the given field in this Vdata.
30  VFfieldtype  -- Return the type of the given field in this Vdata.
31  VFfieldisize -- Return the internal (HDF) size of the given
32                   field in this Vdata.
33  VFfieldesize -- Return the external (local machine) size of the given
34                   field in this Vdata.
35  VFfieldorder -- Return the order of the given field in this Vdata.
36  VSfpack      -- pack into or unpack from a buf the values of fully
37                   interlaced fields (of the entire record).
38 
39 ************************************************************************/
40 
41 #define VSET_INTERFACE
42 #include "hdf.h"
43 #include <stdarg.h>
44 
45 /*
46    ** ==================================================================
47    ** PRIVATE data areas and routines
48    ** ==================================================================
49    * */
50 
51 static const SYMDEF rstab[] =
52 {
53     {"PX", DFNT_FLOAT32, SIZE_FLOAT32, 1},
54     {"PY", DFNT_FLOAT32, SIZE_FLOAT32, 1},
55     {"PZ", DFNT_FLOAT32, SIZE_FLOAT32, 1},
56 
57     {"IX", DFNT_INT32, SIZE_INT32, 1},
58     {"IY", DFNT_INT32, SIZE_INT32, 1},
59     {"IZ", DFNT_INT32, SIZE_INT32, 1},
60 
61     {"NX", DFNT_FLOAT32, SIZE_FLOAT32, 1},
62     {"NY", DFNT_FLOAT32, SIZE_FLOAT32, 1},
63     {"NZ", DFNT_FLOAT32, SIZE_FLOAT32, 1},
64 
65 };
66 
67 #define NRESERVED ( sizeof(rstab)/sizeof(SYMDEF) )
68 
69 /* ------------------------------------------------------------------ */
70 /*
71    ** sets the fields in a vdata for reading or writing
72    ** RETURNS FAIL if error, and SUCCEED if ok.
73    ** truncates each field to max length of  FIELDNAMELENMAX.
74  */
75 intn
VSsetfields(int32 vkey,const char * fields)76 VSsetfields(int32 vkey, const char *fields)
77 {
78     char      **av;
79     int32       ac, found;
80     intn j, i;
81     uint16       uj;
82     uint16       order;
83     int32       value;
84     DYN_VREADLIST  *rlist;
85     DYN_VWRITELIST *wlist;
86     vsinstance_t *w;
87     VDATA      *vs;
88     intn       ret_value = FAIL;
89     CONSTR(FUNC, "VSsetfields");
90 
91     /* check if a NULL field list is passed in, then return with
92        error (bug #554) - BMR 4/30/01 */
93     if (fields == NULL)
94         HGOTO_ERROR(DFE_ARGS, FAIL);
95 
96     if (HAatom_group(vkey)!=VSIDGROUP)
97         HGOTO_ERROR(DFE_ARGS, FAIL);
98 
99     /* locate vs's index in vstab */
100     if (NULL == (w = (vsinstance_t *) HAatom_object(vkey)))
101         HGOTO_ERROR(DFE_NOVS, FAIL);
102 
103     vs = w->vs;
104     if (vs == NULL)
105         HGOTO_ERROR(DFE_ARGS, FAIL);
106 
107     if ((scanattrs(fields, &ac, &av) == FAIL) || (ac == 0))
108         HGOTO_ERROR(DFE_BADFIELDS, FAIL);
109 
110      /* check number of fields limit  */
111      if (ac > VSFIELDMAX)
112          HGOTO_ERROR(DFE_SYMSIZE,FAIL);
113 
114     /*
115      * write to an empty vdata : set the write list but do not set the
116      *   read list cuz there is nothing there to read yet...
117      */
118     if (vs->access == 'w')
119        {
120         if (vs->nvertices == 0)
121            {
122               wlist=&(vs->wlist);
123               if (wlist->n == 0) /* fields not set yet, Sept. 96. */
124                 /* do not re-set fields if they were already set. */
125               {
126                   wlist->ivsize = 0;
127                   wlist->n = 0;
128 
129               /* allocate space for the internal WRITELIST structures */
130                   /* Allocate buffer to hold all the int16/uint16 arrays */
131                   if((wlist->bptr=HDmalloc(sizeof(uint16)*(size_t)(ac*5)))==NULL)
132                       HGOTO_ERROR(DFE_NOSPACE,FAIL);
133 
134                   /* Use buffer to support the other arrays */
135                   wlist->type=(int16 *)wlist->bptr;
136                   wlist->off=(uint16 *)wlist->type+ac;
137                   wlist->isize=wlist->off+ac;
138                   wlist->order=wlist->isize+ac;
139                   wlist->esize=wlist->order+ac;
140                   if((wlist->name=HDmalloc(sizeof(char *)*(size_t)ac))==NULL)
141                     {
142                       HDfree(wlist->bptr);
143                       HGOTO_ERROR(DFE_NOSPACE,FAIL);
144                     } /* end if */
145 
146                   for (i = 0; i < ac; i++)
147                     {
148                         found = FALSE;
149                     /* --- first look in the user's symbol table --- */
150                         for (j = 0; j < vs->nusym; j++)
151                             if (!HDstrcmp(av[i], vs->usym[j].name))
152                               {
153                                   found = TRUE;
154 
155                                   if((wlist->name[wlist->n]=HDstrdup(vs->usym[j].name))==NULL)
156                                    {
157                                       HDfree(wlist->name);
158                                       HDfree(wlist->bptr);
159                                       HGOTO_ERROR(DFE_NOSPACE,FAIL);
160                                     } /* end if */
161                                   order = vs->usym[j].order;
162                                   wlist->type[wlist->n] = vs->usym[j].type;
163                                   wlist->order[wlist->n] = order;
164 
165                                   value = order * DFKNTsize(vs->usym[j].type | DFNT_NATIVE);
166                                   if (value == FAIL)
167                                       HGOTO_ERROR(DFE_BADFIELDS, FAIL);
168                                   wlist->esize[wlist->n] = (uint16) value;
169 
170                                   value = order * vs->usym[j].isize;
171                                   if (value > MAX_FIELD_SIZE)
172                                       HGOTO_ERROR(DFE_BADFIELDS, FAIL);
173                                   wlist->isize[wlist->n] = (uint16) value;
174 
175                                   value = (int32) wlist->ivsize + (int32) (wlist->isize[wlist->n]);
176                                   if (value > MAX_FIELD_SIZE)
177                                       HGOTO_ERROR(DFE_BADFIELDS, FAIL);
178                                   wlist->ivsize = (uint16) value;
179 
180                                   wlist->n++;
181                                   break;
182                               }
183 
184                     /* --- now look in the reserved symbol table --- */
185                         if (!found)
186                           {
187                               for (j = 0; j < (intn)NRESERVED; j++)
188                                   if (!HDstrcmp(av[i], rstab[j].name))
189                                     {
190                                         found = TRUE;
191 
192                                         if((wlist->name[wlist->n]=HDstrdup(rstab[j].name))==NULL)
193                                           {
194                                             HDfree(wlist->name);
195                                             HDfree(wlist->bptr);
196                                             HGOTO_ERROR(DFE_NOSPACE,FAIL);
197                                           } /* end if */
198                                         order = rstab[j].order;
199                                         wlist->type[wlist->n] = rstab[j].type;
200                                         wlist->order[wlist->n] = order;
201                                         value = order * DFKNTsize(rstab[j].type | DFNT_NATIVE);
202                                         if (value == FAIL)
203                                           HGOTO_ERROR(DFE_BADFIELDS, FAIL);
204                                         wlist->esize[wlist->n] = (uint16) value;
205                                         wlist->isize[wlist->n] = (uint16) (order * rstab[j].isize);
206                                         wlist->ivsize += (uint16) (wlist->isize[wlist->n]);
207                                         wlist->n++;
208                                         break;
209                                     }
210                           }
211                         if (!found)     /* field is not a defined field - error  */
212                             HGOTO_ERROR(DFE_BADFIELDS, FAIL);
213                     }
214 
215               /* *********************************************************** */
216               /* compute and save the fields' offsets */
217                    for (uj = 0, i = 0; i < wlist->n; i++)
218                     {
219                         wlist->off[i] = (uint16) uj;
220                         uj += wlist->isize[i];
221                     }
222 
223                   vs->marked = TRUE; /* mark vdata as being modified */
224                   vs->new_h_sz = TRUE; /* mark vdata header size being changed */
225 
226                   HGOTO_DONE(SUCCEED); /* OK */
227               } /* if wlist->n == 0 */
228           } /* writing to empty vdata */
229       } /* writing to vdata */
230 
231     /*
232      *   No matter the access mode, if there are elements in the VData
233      *      we should set the read list
234      */
235     if (vs->nvertices > 0)
236       {
237           rlist = &(vs->rlist);
238           rlist->n = 0;
239           if(rlist->item!=NULL)
240               HDfree(rlist->item);
241           rlist->item=NULL;
242 
243           /* Allocate enough space for the read list */
244           if((rlist->item=(intn *)HDmalloc(sizeof(intn)*(size_t)(ac)))==NULL)
245               HGOTO_ERROR(DFE_NOSPACE, FAIL);
246           for (i = 0; i < ac; i++)
247             {
248                 found = FALSE;
249                 for (j = 0; j < vs->wlist.n; j++)
250                     if (!HDstrcmp(av[i], vs->wlist.name[j]))
251                       {     /*  see if field exist */
252                           found = TRUE;
253 
254                           rlist->item[rlist->n] = j;    /* save as index into wlist->name */
255                           rlist->n++;
256                           break;
257                       }
258                 if (!found)     /* field does not exist - error */
259                     HGOTO_ERROR(DFE_BADFIELDS, FAIL);
260             }
261         ret_value=SUCCEED;
262       }     /* setting read list */
263 
264 done:
265   if(ret_value == FAIL)
266     { /* Error condition cleanup */
267 
268     } /* end if */
269 
270   /* Normal function cleanup */
271   return ret_value;
272 }   /* VSsetfields */
273 
274 /* ------------------------------------------------------------------ */
275 /*
276    ** defines a (one) new field within the vdata
277    ** return FAIL if error
278    ** return SUCCEED if success
279  */
280 intn
VSfdefine(int32 vkey,const char * field,int32 localtype,int32 order)281 VSfdefine(int32 vkey, const char *field, int32 localtype, int32 order)
282 {
283     char      **av;
284     int32       ac;
285     int16       isize, replacesym;
286     intn        usymid;
287     intn j;
288     vsinstance_t *w;
289     VDATA      *vs;
290     intn       ret_value = SUCCEED;
291     CONSTR(FUNC, "VSfdefine");
292 
293     if (HAatom_group(vkey)!=VSIDGROUP)
294         HGOTO_ERROR(DFE_ARGS, FAIL);
295 
296     /* locate vs's index in vstab */
297     if (NULL == (w = (vsinstance_t *) HAatom_object(vkey)))
298         HGOTO_ERROR(DFE_NOVS, FAIL);
299 
300     vs = w->vs;
301     if ((vs == NULL) || (scanattrs(field, &ac, &av) == FAIL) || (ac != 1))
302         HGOTO_ERROR(DFE_ARGS, FAIL);
303 
304     /* The order of a variable is stored in a 16-bit number, so have to keep this limit -QAK */
305     if (order < 1 || order > MAX_ORDER)
306         HGOTO_ERROR(DFE_BADORDER, FAIL);
307     /* don't forget to check for field size limit */
308     isize = (int16)DFKNTsize(localtype);
309     if ( (isize == FAIL) || (isize * order) > MAX_FIELD_SIZE )
310         HGOTO_ERROR(DFE_BADFIELDS, FAIL);
311 
312     /*
313      ** check for any duplicates
314      */
315 #ifdef OLD_WAY
316 /* It's OK to over-ride pre-defined symbols with the user's own -QAK */
317     /* --- first look in the reserved symbol table --- */
318     for (j = 0; j < NRESERVED; j++)
319         if (!HDstrcmp(av[0], rstab[j].name))
320           {
321               if (localtype != rstab[j].type && order != rstab[j].order)
322                   break;
323           }
324 #endif /* OLD_WAY */
325 
326     /* --- then look in the user's symbol table --- */
327     for (replacesym = 0, j = 0; j < vs->nusym; j++)
328         if (!HDstrcmp(av[0], vs->usym[j].name))
329           {
330               if (localtype != rstab[j].type && order != rstab[j].order)
331                 {
332                     replacesym = 1;
333                     break;
334                 }
335           }
336 
337     if (replacesym)
338         usymid = j;     /* new definition will replace old at this index */
339     else
340       {
341           SYMDEF *tmp_sym=vs->usym;  /* temp. pointer to the new symdef list */
342 
343           usymid = (intn)vs->nusym;
344           /* use temporary pointer in case we run out of memory, so we don't loose original list */
345           if (tmp_sym == NULL)
346            {
347              if((tmp_sym=(SYMDEF *) HDmalloc(sizeof(SYMDEF)*(size_t)(usymid+1)))==NULL)
348               HGOTO_ERROR(DFE_NOSPACE,FAIL);
349             }
350           else
351             {
352               if((tmp_sym=(SYMDEF *) HDrealloc(tmp_sym,sizeof(SYMDEF)*(size_t)(usymid+1)))==NULL)
353                   HGOTO_ERROR(DFE_NOSPACE,FAIL);
354             }
355           vs->usym=tmp_sym;
356       } /* end else */
357 
358       vs->usym[usymid].isize = (uint16) isize; /* ok, because number
359           type sizes are smaller than max(int16) */
360 
361     /* Copy the symbol [field] information */
362     if ((vs->usym[usymid].name = (char *) HDstrdup(av[0]) ) == NULL)
363         HGOTO_ERROR(DFE_NOSPACE, FAIL);
364     vs->usym[usymid].type = (int16) localtype;
365     vs->usym[usymid].order = (uint16) order;
366 
367     /* increment vs->nusym only if no user field has been redefined */
368     if (!replacesym)
369         vs->nusym++;
370 
371 done:
372   if(ret_value == FAIL)
373     { /* Error condition cleanup */
374 
375     } /* end if */
376 
377   /* Normal function cleanup */
378   return ret_value;
379 }	/* VSfdefine */
380 
381 /* ------------------------------ VFnfields ------------------------------- */
382 /*
383    Return the number of fields in this Vdata
384    Return FAIL on failure
385  */
386 int32
VFnfields(int32 vkey)387 VFnfields(int32 vkey)
388 {
389     vsinstance_t *w;
390     VDATA      *vs;
391     int32      ret_value = SUCCEED;
392     CONSTR(FUNC, "VFnfields");
393 
394     if (HAatom_group(vkey)!=VSIDGROUP)
395         HGOTO_ERROR(DFE_ARGS,FAIL);
396 
397     /* locate vs's index in vstab */
398     if (NULL == (w = (vsinstance_t *) HAatom_object(vkey)))
399       HGOTO_ERROR(DFE_NOVS,FAIL);
400 
401     vs = w->vs;
402     if ((vs == NULL) || (vs->otag != VSDESCTAG))
403       HGOTO_ERROR(DFE_ARGS,FAIL);
404 
405     ret_value = ((int32) vs->wlist.n);
406 
407 done:
408   if(ret_value == FAIL)
409     { /* Error condition cleanup */
410 
411     } /* end if */
412 
413   /* Normal function cleanup */
414   return ret_value;
415 }	/* VFnfields */
416 
417 /* ----------------------------- VFfieldname ------------------------------ */
418 /*
419    Return the name of the given field in this Vdata.
420    This is just a pointer to the string in local memory and is only guarenteed
421    to be valid as long as we are VSattached() to this Vdata
422 
423    Return NULL on failure
424  */
425 char       *
VFfieldname(int32 vkey,int32 index)426 VFfieldname(int32 vkey, int32 index)
427 {
428     vsinstance_t *w;
429     VDATA      *vs;
430     char       *ret_value = NULL; /* FAIL */
431     CONSTR(FUNC, "VFfieldname");
432 
433     if (HAatom_group(vkey)!=VSIDGROUP)
434       HGOTO_ERROR(DFE_ARGS,NULL);
435 
436     /* locate vs's index in vstab */
437     if (NULL == (w = (vsinstance_t *) HAatom_object(vkey)))
438       HGOTO_ERROR(DFE_NOVS,NULL);
439 
440     vs = w->vs;
441     if ((vs == NULL) || (vs->otag != VSDESCTAG))
442       HGOTO_ERROR(DFE_ARGS,NULL);
443 
444     if (vs->wlist.n == 0)
445       HGOTO_ERROR(DFE_BADFIELDS,NULL);
446 
447     ret_value = ((char *) vs->wlist.name[index]);
448 
449 done:
450   if(ret_value == NULL)
451     { /* Error condition cleanup */
452 
453     } /* end if */
454 
455   /* Normal function cleanup */
456   return ret_value;
457 }   /* VFfieldname */
458 
459 /* ----------------------------- VFfieldtype ------------------------------ */
460 /*
461    Return the type of the given field in this Vdata.
462 
463    Return FAIL on failure
464  */
465 int32
VFfieldtype(int32 vkey,int32 index)466 VFfieldtype(int32 vkey, int32 index)
467 {
468     vsinstance_t *w;
469     VDATA      *vs;
470     int32      ret_value = SUCCEED;
471     CONSTR(FUNC, "VFfeildtype");
472 
473     if (HAatom_group(vkey)!=VSIDGROUP)
474       HGOTO_ERROR(DFE_ARGS,FAIL);
475 
476     /* locate vs's index in vstab */
477     if (NULL == (w = (vsinstance_t *) HAatom_object(vkey)))
478       HGOTO_ERROR(DFE_NOVS,FAIL);
479 
480     vs = w->vs;
481     if ((vs == NULL) || (vs->otag != VSDESCTAG))
482       HGOTO_ERROR(DFE_ARGS,FAIL);
483 
484     if (vs->wlist.n == 0)
485       HGOTO_ERROR(DFE_BADFIELDS,FAIL);
486 
487     ret_value = ((int32) vs->wlist.type[index]);
488 
489 done:
490   if(ret_value == FAIL)
491     { /* Error condition cleanup */
492 
493     } /* end if */
494 
495   /* Normal function cleanup */
496   return ret_value;
497 }   /* VFfieldtype */
498 
499 /* ----------------------------- VFfieldisize ------------------------------ */
500 /*
501    Return the internal size of the given field in this Vdata.
502    (internal to HDF file, see VWRITELIST in vg.h. 4/3/96)
503 
504    Return FAIL on failure
505  */
506 int32
VFfieldisize(int32 vkey,int32 index)507 VFfieldisize(int32 vkey, int32 index)
508 {
509     vsinstance_t *w;
510     VDATA      *vs;
511     int32      ret_value = SUCCEED;
512     CONSTR(FUNC, "VFfieldisize");
513 
514     if (HAatom_group(vkey)!=VSIDGROUP)
515       HGOTO_ERROR(DFE_ARGS,FAIL);
516 
517     /* locate vs's index in vstab */
518     if (NULL == (w = (vsinstance_t *) HAatom_object(vkey)))
519       HGOTO_ERROR(DFE_NOVS,FAIL);
520 
521     vs = w->vs;
522     if ((vs == NULL) || (vs->otag != VSDESCTAG))
523       HGOTO_ERROR(DFE_ARGS,FAIL);
524 
525     if (vs->wlist.n == 0)
526       HGOTO_ERROR(DFE_BADFIELDS,FAIL);
527 
528     ret_value = ((int32) vs->wlist.isize[index]);
529 
530 done:
531   if(ret_value == FAIL)
532     { /* Error condition cleanup */
533 
534     } /* end if */
535 
536   /* Normal function cleanup */
537   return ret_value;
538 }   /* VFfieldisize */
539 
540 /* ----------------------------- VFfieldesize ------------------------------ */
541 /*
542    Return the external size of the given field in this Vdata.
543    (external to HDF file, see VWRITELIST in vg.h. 4/3/96)
544 
545    Return FAIL on failure
546  */
547 int32
VFfieldesize(int32 vkey,int32 index)548 VFfieldesize(int32 vkey, int32 index)
549 {
550     vsinstance_t *w;
551     VDATA      *vs;
552     int32      ret_value = SUCCEED;
553     CONSTR(FUNC, "VFfieldesize");
554 
555     if (HAatom_group(vkey)!=VSIDGROUP)
556       HGOTO_ERROR(DFE_ARGS,FAIL);
557 
558     /* locate vs's index in vstab */
559     if (NULL == (w = (vsinstance_t *) HAatom_object(vkey)))
560       HGOTO_ERROR(DFE_NOVS,FAIL);
561 
562     vs = w->vs;
563     if ((vs == NULL) || (vs->otag != VSDESCTAG))
564       HGOTO_ERROR(DFE_ARGS,FAIL);
565 
566     if (vs->wlist.n == 0)
567       HGOTO_ERROR(DFE_BADFIELDS,FAIL);
568 
569     ret_value = ((int32) vs->wlist.esize[index]);
570 
571 done:
572   if(ret_value == FAIL)
573     { /* Error condition cleanup */
574 
575     } /* end if */
576 
577   /* Normal function cleanup */
578 
579   return ret_value;
580 }   /* VFfieldesize */
581 
582 /* ----------------------------- VFfieldorder ------------------------------ */
583 /*
584    Return the order of the given field in this Vdata.
585 
586    Return FAIL on failure
587  */
588 int32
VFfieldorder(int32 vkey,int32 index)589 VFfieldorder(int32 vkey, int32 index)
590 {
591     vsinstance_t *w;
592     VDATA      *vs;
593     int32      ret_value = SUCCEED;
594     CONSTR(FUNC, "VFfieldorder");
595 
596     if (HAatom_group(vkey)!=VSIDGROUP)
597       HGOTO_ERROR(DFE_ARGS,FAIL);
598 
599     /* locate vs's index in vstab */
600     if (NULL == (w = (vsinstance_t *) HAatom_object(vkey)))
601       HGOTO_ERROR(DFE_NOVS,FAIL);
602 
603     vs = w->vs;
604     if ((vs == NULL) || (vs->otag != VSDESCTAG))
605       HGOTO_ERROR(DFE_ARGS,FAIL);
606 
607     if (vs->wlist.n == 0)
608       HGOTO_ERROR(DFE_BADFIELDS,FAIL);
609 
610     ret_value = ((int32) vs->wlist.order[index]);
611 
612 done:
613   if(ret_value == FAIL)
614     { /* Error condition cleanup */
615 
616     } /* end if */
617 
618   /* Normal function cleanup */
619   return ret_value;
620 }	/* VFfieldorder */
621 
622 /* -------------------------- VSsetexternalfile --------------------------- */
623 /*
624 
625  NAME
626 	VSsetexternalfile -- store Vdat info in a separate file
627  USAGE
628 	int32 VSsetexternalfile(id, filename, offset)
629         int32   id;                  IN: vdata ID
630         char  * filename;            IN: name of external file
631         int32   offset;              IN: offset in external file
632  RETURNS
633         Return SUCCEED or FAIL
634 
635  DESCRIPTION
636         Specify that the actual data for this Vdata be stored in a
637         separate file (an "external file" in HDF terms).
638 
639         Only the data (as in VSwrite()) will be stored externally.
640         Attributes and such will still be in the main file
641 
642         IMPORTANT:  It is the user's responsibility to see that the
643         separate files are transported with the main file.
644 FORTRAN
645 	vsfsextf
646 
647 --------------------------------------------------------------------------- */
648 
VSsetexternalfile(int32 vkey,const char * filename,int32 offset)649 intn VSsetexternalfile(int32 vkey, const char *filename, int32 offset)
650 {
651     CONSTR(FUNC, "VSsetexternalfile");
652     int32       ret_value = SUCCEED;
653 
654     vsinstance_t *w;
655     VDATA      *vs;
656     intn       status;
657 
658     if(!filename || offset < 0)
659 	HGOTO_ERROR(DFE_ARGS, FAIL);
660 
661     if (HAatom_group(vkey)!=VSIDGROUP)
662 	    HGOTO_ERROR(DFE_ARGS, FAIL);
663 
664     /* locate vs's index in vstab */
665     if (NULL == (w = (vsinstance_t *) HAatom_object(vkey)))
666         HGOTO_ERROR(DFE_NOVS, FAIL);
667 
668     vs = w->vs;
669     if (vs->access != 'w')
670         HGOTO_ERROR(DFE_BADACC, FAIL);
671 
672     if (FAIL == vexistvs(vs->f, vs->oref))
673         HGOTO_ERROR(DFE_NOVS, FAIL);
674 
675     if(!w->ref)
676         HGOTO_ERROR(DFE_NOVS, FAIL);
677 
678     /* no need to give a length since the element already exists */
679     /* The Data portion of a Vdata is always stored in linked blocks. */
680     /* So, use the special tag */
681     status = (intn)HXcreate(vs->f, (uint16)VSDATATAG, (uint16) w->ref,
682 		      filename, offset, (int32)0);
683     if(status != FAIL)
684       {
685         if((vs->aid != 0) && (vs->aid != FAIL))
686             Hendaccess(vs->aid);
687         vs->aid = status;
688       }
689     else
690         ret_value = FAIL;
691 
692 done:
693     if(ret_value == FAIL)
694     { /* Error condition cleanup */
695 
696     } /* end if */
697 
698     /* Normal function cleanup */
699 
700     return ret_value;
701 } /* VSsetexternalfile */
702 
703 /* -------------------------- VSgetexternalfile --------------------------- */
704 /*
705 
706  NAME
707 	VSgetexternalfile -- gets external file name and offset
708  USAGE
709 	int32 VSgetexternalfile(id, name_len, filename, offset)
710         int32  vkey;            IN: vdata ID
711 	size_t name_len;        IN: length of buffer for external file name
712         char  *extfilename;     IN: external file name
713         int32 *offset;          IN: offset in external file
714  RETURNS
715         Returns length of the external file name or FAIL.  If the vdata
716 	does not have external element, the length will be 0.
717 
718  DESCRIPTION
719         IMPORTANT:  It is the user's responsibility to see that the
720         separate files are transported with the main file.
721  FORTRAN
722 	N/A
723 
724 --------------------------------------------------------------------------- */
725 
VSgetexternalfile(int32 vkey,uintn buf_size,char * ext_filename,int32 * offset)726 intn VSgetexternalfile(int32 vkey, uintn buf_size, char *ext_filename, int32 *offset)
727 {
728     CONSTR(FUNC, "VSgetexternalfile");
729     vsinstance_t *w;
730     VDATA *vs;
731     sp_info_block_t info_block;
732     intn  actual_len = 0;
733     intn  ret_value = SUCCEED;
734 
735     if (HAatom_group(vkey) != VSIDGROUP)
736 	HGOTO_ERROR(DFE_ARGS, FAIL);
737 
738     /* Locate vs's index in vstab */
739     if (NULL == (w = (vsinstance_t *) HAatom_object(vkey)))
740         HGOTO_ERROR(DFE_NOVS, FAIL);
741 
742     /* Get the vdata structure */
743     vs = w->vs;
744 
745     /* Vdata should have an aid */
746     if (vs->aid == 0 || vs->aid == FAIL)
747         HGOTO_ERROR(DFE_ARGS, FAIL)
748     else
749     {
750 	HDmemset(&info_block, 0, sizeof(sp_info_block_t));
751 
752 	/* HDget_special_info gets the special type and the special info */
753         if (HDget_special_info(vs->aid, &info_block) == FAIL)
754             HGOTO_ERROR(DFE_INTERNAL, FAIL)
755 
756 	/* If the vdata has external element, return the external file info */
757 	if (info_block.key == SPECIAL_EXT)
758 	{
759 	    /* If the file name is not available, the file is probably
760 		corrupted, so we need to report it. */
761 	    if (info_block.path == NULL || HDstrlen(info_block.path) <= 0)
762 		ret_value = FAIL;
763 	    else
764 	    {
765 		size_t ext_file_len = HDstrlen(info_block.path);
766 
767 		/* If caller requests the length of the external file name
768 		   only, return the length */
769 		if (buf_size == 0)
770 		    actual_len = (intn)ext_file_len;
771 		else
772 		{
773 		    /* Caller requests file name, so buffer must not be NULL */
774 		    if (ext_filename == NULL)
775 			HGOTO_ERROR(DFE_ARGS, FAIL);
776 
777 		    /* Get the name and its length */
778 		    HDstrncpy(ext_filename, info_block.path, buf_size);
779 		    actual_len = buf_size < ext_file_len ? buf_size : ext_file_len;
780 
781 		    /* Get the offset in the external file if it's requested */
782 		    if (offset != NULL)
783 			*offset = info_block.offset;
784 		} /* buf_size != 0 */
785 		ret_value = actual_len;
786 	    }
787 	}
788 	/* Not external */
789 	else
790 	    ret_value = FAIL;
791     }
792 done:
793     if(ret_value == FAIL)
794     { /* Error condition cleanup */
795 
796     } /* end if */
797     /* Normal function cleanup */
798     return ret_value;
799 } /* VSgetexternalfile */
800 
801 /* -------------------------- VSgetexternalinfo --------------------------- */
802 /*
803 
804  NAME
805 	VSgetexternalinfo -- gets external file name and offset
806  USAGE
807 	int32 VSgetexternalinfo(id, name_len, filename, offset)
808         int32  vkey;            IN: vdata ID
809 	uintn  buf_size;        IN: length of buffer for external file name
810         char  *extfilename;     IN: external file name
811         int32 *offset;          IN: offset in external file, where data starts
812         int32 *length;          IN: length of data in external file
813  RETURNS
814         Returns length of the external file name or FAIL.  If the vdata
815 	does not have external element, the length will be 0.
816 
817  DESCRIPTION
818 	VSgetexternalinfo gets the external file's name and the external data's
819 	offset and length, which specify the location and size of the data in
820 	the external file.
821 
822 	buf_size specifies the size of the buffer ext_filename.  When buf_size
823 	is 0, VSgetexternalinfo will simply return the length of the external
824 	file name, and not the file name itself.
825 
826 	When the element is not special, VSgetexternalinfo will return 0.  If
827 	the element is SPECIAL_EXT, but the external file name doesn't exist,
828 	VSgetexternalinfo will return FAIL.
829 
830         IMPORTANT:  It is the user's responsibility to see that the
831         separate files are transported with the main file.
832  FORTRAN
833 	N/A
834 
835 --------------------------------------------------------------------------- */
836 
VSgetexternalinfo(int32 vkey,uintn buf_size,char * ext_filename,int32 * offset,int32 * length)837 intn VSgetexternalinfo(int32 vkey, uintn buf_size, char *ext_filename, int32 *offset, int32 *length)
838 {
839     CONSTR(FUNC, "VSgetexternalinfo");
840     vsinstance_t *w;
841     VDATA *vs;
842     intn   actual_fname_len = 0;
843     intn   ret_value = SUCCEED;
844 
845     if (HAatom_group(vkey) != VSIDGROUP)
846 	HGOTO_ERROR(DFE_ARGS, FAIL);
847 
848     /* Locate vs's index in vstab */
849     if (NULL == (w = (vsinstance_t *) HAatom_object(vkey)))
850         HGOTO_ERROR(DFE_NOVS, FAIL);
851 
852     /* Get the vdata structure */
853     vs = w->vs;
854 
855     /* Vdata should have an aid */
856     if (vs->aid == 0 || vs->aid == FAIL)
857         HGOTO_ERROR(DFE_ARGS, FAIL)
858     else
859     {
860 	intn retcode = 0;
861 	sp_info_block_t info_block;
862 	HDmemset(&info_block, 0, sizeof(sp_info_block_t));
863 
864 	/* Get the special info */
865 	retcode = HDget_special_info(vs->aid, &info_block);
866 
867 	/* When HDget_special_info returns FAIL, it could be the element is not
868 	   special or some failure occur internally, info_block.key will be
869 	   FAIL in the former case */
870 	if (retcode == FAIL)
871 	{
872 	    if (info_block.key == FAIL)
873 		ret_value = 0;	/* not a special elem, no external file name */
874 
875 	    /* Some failure occurred in HDget_special_info */
876 	    else
877 		HGOTO_ERROR(DFE_ARGS, FAIL)
878 	}
879 
880 	/* If the vdata has external element, get the external info */
881 	else if (info_block.key == SPECIAL_EXT)
882 	{
883 	    /* If the file name is not available, the file is probably
884 		corrupted, so we need to report it. */
885 	    if (info_block.path == NULL || HDstrlen(info_block.path) <= 0)
886 		ret_value = FAIL;
887 	    else
888 	    {
889 		intn tmp_len = (intn)info_block.length_file_name;
890 
891 		/* If caller requests the length of the external file name
892 		   only, return the length */
893 		if (buf_size == 0)
894 		    actual_fname_len = tmp_len;
895 		else
896 		{
897 		    /* Caller requests file name, so buffer must not be NULL */
898 		    if (ext_filename == NULL)
899 			HGOTO_ERROR(DFE_ARGS, FAIL);
900 
901 		    /* Compute the length of the name to be returned: if
902 		       requested buffer size is smaller, use that value for
903 		       name's length, but that means file name could be
904 		       truncated! */
905 		    actual_fname_len = (intn)buf_size < tmp_len ? (intn)buf_size : tmp_len;
906 
907 		    /* Get the name */
908 		    HDstrncpy(ext_filename, info_block.path, buf_size);
909 
910 		    /* Get offset/length of the external data if requested */
911 		    if (offset != NULL)
912 			*offset = info_block.offset;
913                     if (length != NULL)
914                         *length = info_block.length;
915 		} /* buf_size != 0 */
916 		ret_value = actual_fname_len;
917 	    }
918 	}
919 	/* Special, but not external */
920 	else
921 	    ret_value = 0;	/* no external file name */
922     }
923 done:
924     if(ret_value == FAIL)
925     { /* Error condition cleanup */
926 
927     } /* end if */
928     /* Normal function cleanup */
929     return ret_value;
930 } /* VSgetexternalinfo */
931 
932 /*-----------------------------------------------------------------
933 NAME
934     VSfpack -- pack into or unpack from a buf the values of fully
935               interlaced fields.
936 USAGE
937     intn VSfpack(int32 vsid, intn packtype, char *fields_in_buf,
938          void * buf, intn bufsz, intn n_records, char *fields, void * fldbufpt[])
939     int32 vsid; IN: vdata id.
940     intn packtype; IN:
941          _HDF_VSPACK(0) -- pack field values into vdata buf;
942          _HDF_VSUNPACK(1) -- unpack vdata value into filed bufs.
943     char *fields_in_buf; IN:
944          fields in buf to write to or read from vdata. NULL
945          stands for all fields in the vdata.
946     void * buf; IN: buffer for vdata values.
947     intn bufsz; IN: buf size in byte.
948     intn n_records; IN: number of records to pack or unpack.
949     char *fields; IN:
950          names of the fields to be pack/unpack. It may be a
951          subset of the fields_in_buf. NULL stands for all
952          fields in buf.
953     void * fldbufpt[]; IN: array of pointers to field buffers.
954 RETURNS
955     SUCCEED(0) on success; FIAL(-1) otherwise.
956 DESCRIPTION
957     1. This pack/unpack routine is convenient for users. It also
958        serves for FORTRAN programs to pack/unpack numeric and
959        non-numeric fields.
960     2. The caller should supply correct number of field buffers,
961        which should agree with the number of fields to be
962        packed/unpacked.
963     3. For packtype = _HDF_VSPACK, the calling sequence should be:
964           VSsetfields,  VSfpack, and VSwrite;
965        For packtype = _HDF_VSUNPACK, the calling sequence should be:
966           VSsetfields, VSread and VSfpack.
967 */
968 
969 /*---------------------------------------------------------*/
970 
VSfpack(int32 vsid,intn packtype,const char * fields_in_buf,void * buf,intn bufsz,intn n_records,const char * fields,void * fldbufpt[])971 intn VSfpack(int32 vsid, intn packtype, const char *fields_in_buf,
972          void * buf, intn bufsz, intn n_records, const char *fields, void * fldbufpt[])
973 {
974     CONSTR(FUNC, "VSfpack");
975 
976     int32 ac;
977     char **av, *s;
978     uint8 *bufp = (uint8 *)buf;
979     uint8 **fbufps=NULL;
980     int32 b_rec_size, *fmsizes=NULL, *foffs=NULL;
981     intn i, j, found, ret_value = SUCCEED;
982     vsinstance_t *wi;
983     VDATA *vs;
984     DYN_VWRITELIST *w;
985     struct blist_t  { /* contains info about fields in buf */
986        intn n;       /* number of fields in buf     */
987        int32 *idx;  /* index of buf fields in vdata */
988        int32 *offs; /* offset of buf fields in buf */
989     }  blist;
990 
991     if (HAatom_group(vsid)!=VSIDGROUP)
992         HGOTO_ERROR(DFE_ARGS, FAIL);
993     /* locate vs' index in vgtab */
994     if (NULL == (wi = (vsinstance_t *) HAatom_object(vsid)))
995         HGOTO_ERROR(DFE_NOVS, FAIL);
996     vs = wi->vs;
997     if (vs == NULL)
998         HGOTO_ERROR(DFE_NOVS, FAIL);
999     w = &vs->wlist;
1000          /* build blist based on info in w */
1001     if (fields_in_buf == NULL)
1002          ac = w->n;
1003     else    {           /* build our own blist */
1004        if (scanattrs(fields_in_buf, &ac, &av) == FAIL)
1005            HGOTO_ERROR(DFE_BADFIELDS, FAIL);
1006        if ((av == NULL) || (ac < 1))
1007             HGOTO_ERROR(DFE_ARGS, FAIL);
1008     }
1009     blist.n = ac;
1010     blist.idx = (int32 *)HDmalloc((size_t)ac * sizeof(int32));
1011     blist.offs = (int32 *)HDmalloc((size_t)ac * sizeof(int32));
1012     if ((blist.idx == NULL) || (blist.offs == NULL))
1013          HGOTO_ERROR(DFE_NOSPACE, FAIL);
1014       /* fill arrays blist.msizes and blist.offs; calculate
1015            buf record size */
1016     b_rec_size = 0;
1017     if (fields_in_buf != NULL)
1018         /* a subset of vdata fields are contained in buf */
1019         for (i=0; i<ac; i++) {
1020            /* look for the field in vdata fields */
1021            found = 0;
1022            s = av[i];
1023            for (j=0; j< w->n; j++)  {
1024 #ifdef VDATA_FIELDS_ALL_UPPER
1025                if (matchnocase(s, w->name[j]))
1026                {
1027                     found = 1;
1028                     break;
1029                 }
1030 #else
1031                 if (HDstrcmp(s, w->name[j]) == 0)
1032                 {
1033                      found = 1;
1034                      break;
1035                  }
1036 #endif /* VDATA_FIELDS_ALL_UPPER */
1037             }     /* for j */
1038             if (!found)
1039                 HGOTO_ERROR(DFE_BADFIELDS, FAIL);
1040                /* get field info */
1041             blist.idx[i] = j;
1042             blist.offs[i] =
1043                (i==0? 0 : blist.offs[i-1] + w->esize[blist.idx[i-1]]);
1044             b_rec_size += w->esize[j];
1045         }  /* for i */
1046     else  /* buf contains all vdata fields  */
1047        for (i=0; i< ac; i++) {
1048            blist.idx[i] = i;
1049            blist.offs[i] =
1050                 (i==0? 0 : blist.offs[i-1] + w->esize[i-1]);
1051            b_rec_size += w->esize[i];
1052        }
1053 
1054        /* check bufsz */
1055     if (bufsz < b_rec_size * n_records)
1056         HGOTO_ERROR(DFE_NOTENOUGH, FAIL);
1057     if (fields != NULL) { /* convert field names into tokens. */
1058         if (scanattrs(fields, &ac, &av) == FAIL )
1059             HGOTO_ERROR(DFE_BADFIELDS, FAIL);
1060         if ((av == NULL) || (ac < 1))
1061             HGOTO_ERROR(DFE_ARGS, FAIL);
1062     }
1063     else
1064         ac = blist.n;
1065        /* fill array of fmsizes, foffs, fbufps */
1066     if ((fmsizes=(int32 *)HDmalloc((size_t)ac*sizeof(int32))) == NULL)
1067          HGOTO_ERROR(DFE_NOSPACE, FAIL);
1068     if ((foffs = (int32 *)HDmalloc((size_t)ac*sizeof(int32))) == NULL)
1069          HGOTO_ERROR(DFE_NOSPACE, FAIL);
1070     if ((fbufps=(uint8 **)HDmalloc((size_t)ac*sizeof(uint8 *))) == NULL)
1071          HGOTO_ERROR(DFE_NOSPACE, FAIL);
1072     if (fields != NULL)  { /* a subset of buf fields */
1073         for (i=0; i<ac; i++) {
1074            /* find field info */
1075            found = 0;
1076            s = av[i];
1077            for (j=0; j< blist.n; j++)  {
1078 #ifdef VDATA_FIELDS_ALL_UPPER
1079                if (matchnocase(s, w->name[blist.idx[j]]))
1080                {
1081                     found = 1;
1082                     break;
1083                 }
1084 #else
1085                 if (HDstrcmp(s, w->name[blist.idx[j]]) == 0)
1086                 {
1087                      found = 1;
1088                      break;
1089                  }
1090 #endif /* VDATA_FIELDS_ALL_UPPER */
1091             }     /* for */
1092             if (!found)
1093                 HGOTO_ERROR(DFE_BADFIELDS, FAIL);
1094             fmsizes[i] = (int32)w->esize[blist.idx[j]];
1095             foffs[i] = blist.offs[j];
1096 	    fbufps[i] = fldbufpt[i];
1097             if (fbufps[i] == NULL)
1098                 HGOTO_ERROR(DFE_BADPTR,FAIL);
1099         }
1100     }
1101     else
1102     {     /* all buf fields */
1103         for (i=0; i < ac; i++)   {
1104             fmsizes[i] = (int32)w->esize[blist.idx[i]];
1105             foffs[i] = blist.offs[i];
1106 	    fbufps[i] = fldbufpt[i];
1107             if (fbufps[i] == NULL)
1108                 HGOTO_ERROR(DFE_BADPTR,FAIL);
1109         }
1110      }
1111     if (packtype == _HDF_VSPACK ) {
1112         /* memory copy fields data to vdata buf */
1113         for (i=0; i<n_records; i++)   {
1114             for (j=0; j<ac; j++)       {
1115                 HDmemcpy(bufp + foffs[j], fbufps[j], fmsizes[j]);
1116                 fbufps[j] += fmsizes[j];
1117             }
1118             bufp += b_rec_size;
1119         }
1120     }
1121     else  { /* unpack from buf to fields */
1122         for (i=0; i<n_records; i++)   {
1123             for (j=0; j<ac; j++)       {
1124                 HDmemcpy(fbufps[j], bufp + foffs[j], fmsizes[j]);
1125                 fbufps[j] += fmsizes[j];
1126             }
1127             bufp += b_rec_size;
1128         }
1129     }
1130 
1131 done:
1132     if (ret_value == FAIL) {
1133     }
1134     if (blist.idx != NULL)
1135        HDfree(blist.idx);
1136     if (blist.offs != NULL)
1137        HDfree(blist.offs);
1138     if (fmsizes != NULL)
1139        HDfree(fmsizes);
1140     if (foffs != NULL)
1141        HDfree(foffs);
1142     if (fbufps != NULL)
1143        HDfree(fbufps);
1144 
1145   return ret_value;
1146 }       /* VSfpack */
1147 /*--------------------------------------------------------- */
1148