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