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 *
18 * vrw.c
19 * Part of the HDF VSet interface.
20 * This module handles reading and writing of Vdatas.
21 *
22 
23 LOCAL ROUTINES
24  VSPshutdown  --  Free the Vtbuf buffer.
25 
26 EXPORTED ROUTINES
27  VSseek  -- Seeks to an element boundary within a vdata i.e. 2nd element.
28  VSread  -- Reads a specified number of elements' worth of data from a vdata.
29              Data will be returned to you interlaced in the way you specified.
30  VSwrite -- Writes a specified number of elements' worth of data to a vdata.
31 	     You must specify how your data in your buffer is interlaced.
32              Creates an aid, and writes it out if this is the first time.
33 
34  NOTE: Another pass needs to made through this file to update some of
35        the comments about certain sections of the code. -GV 9/8/97
36 
37 ************************************************************************/
38 
39 #define VSET_INTERFACE
40 #include "hdf.h"
41 
42 #ifndef MIN
43 #define MIN(a,b)     ((a) < (b) ? (a) : (b))
44 #endif /* MIN */
45 
46 PRIVATE uint32 Vtbufsize = 0;
47 PRIVATE uint8 *Vtbuf = NULL;
48 
49 /*******************************************************************************
50  NAME
51     VSPshutdown  --  Free the Vtbuf buffer.
52 
53  DESCRIPTION
54     For completeness, when the VSet interface is shut-down, free the Vtbuf.
55 
56     Should only ever be called by the "atexit" function HDFend
57 
58  RETURNS
59     Returns SUCCEED/FAIL
60 
61 *******************************************************************************/
62 intn
VSPshutdown(void)63 VSPshutdown(void)
64 {
65   intn  ret_value = SUCCEED;
66 
67   /* free global buffers */
68   if(Vtbuf != NULL)
69     {
70       HDfree(Vtbuf);
71       Vtbuf = NULL;
72       Vtbufsize = 0;
73     } /* end if */
74 
75   /* Clear the local buffers in vio.c */
76   ret_value = VSPhshutdown();
77 
78   return ret_value;
79 } /* end VSPshutdown() */
80 
81 /*******************************************************************************
82 NAME
83    VSseek
84 
85 DESCRIPTION
86    Seeks to an element boundary within a vdata
87    Vdata must be attached with "r" or "w" access.
88    Specify eltpos = 0 for 1st element, 1 for 2nd element etc.
89 
90    (eg  returns 5 if seek to the 6th element, etc)
91 
92 RETURNS
93    RETURNS FAIL on error
94    RETURNS position of element seeked to (0 or a +ve integer)
95 
96 *******************************************************************************/
97 int32
VSseek(int32 vkey,int32 eltpos)98 VSseek(int32 vkey,   /* IN: vdata key */
99        int32 eltpos  /* IN: element position in vdata */)
100 {
101     int32        ret;
102     int32        offset;
103     vsinstance_t *w = NULL;
104     VDATA        *vs = NULL;
105     int32        ret_value = SUCCEED;
106     CONSTR(FUNC, "VSseek");
107 
108     /* clear error stack */
109     HEclear();
110 
111     /* check if vdata is part of vdata group */
112     if (HAatom_group(vkey)!=VSIDGROUP)
113         HGOTO_ERROR(DFE_ARGS, FAIL);
114 
115     /* get vdata instance */
116     if (NULL == (w = (vsinstance_t *) HAatom_object(vkey)))
117         HGOTO_ERROR(DFE_NOVS, FAIL);
118 
119     /* get vdata itself and check it. Check element postion also. */
120     vs = w->vs;
121     if ((vs == NULL) || (eltpos < 0))
122         HGOTO_ERROR(DFE_ARGS, FAIL);
123 
124     /* Don't allow seeks in 0-field vdatas */
125     if (vs->wlist.n<=0)
126         HGOTO_ERROR(DFE_BADFIELDS, FAIL);
127 
128     /* calculate offset of element in vdata */
129     offset = eltpos * vs->wlist.ivsize;
130 
131     /* seek to element */
132     if (( ret = Hseek(vs->aid, offset, DF_START)) == FAIL)
133         HGOTO_ERROR(DFE_BADSEEK, FAIL);
134 
135     ret_value = (eltpos);
136 
137 done:
138   if(ret_value == FAIL)
139     { /* Error condition cleanup */
140 
141     } /* end if */
142 
143   /* Normal function cleanup */
144   return ret_value;
145 }	/* VSseek */
146 
147 /*******************************************************************************
148 NAME
149    VSread
150 
151 DESCRIPTION
152    Reads a specified number of elements' worth of data from a vdata.
153    Data will be returned to you interlaced in the way you specified.
154 
155 RETURNS
156    RETURNS FAIL if error
157    RETURNS the number of elements read (0 or a +ve integer).
158 
159 *******************************************************************************/
160 int32
VSread(int32 vkey,uint8 buf[],int32 nelt,int32 interlace)161 VSread(int32 vkey,       /* IN: vdata key */
162        uint8 buf[],      /* IN/OUT: space to put elements in */
163        int32 nelt,       /* IN: number of elements to read */
164        int32 interlace   /* IN: interlace to return elements in 'buf' */)
165 {
166     intn isize = 0;
167     intn order = 0;
168     intn index = 0;
169     intn esize = 0;
170     intn hsize = 0;
171     uint8 *Src;
172     uint8 *b1 = NULL;
173     uint8 *b2 = NULL;
174     int32  i, j;
175     int32  nv;
176     int32  offset;
177     int32  type;
178     int32  uvsize;         /* size of "element" as NEEDED by user */
179     int32  total_bytes;     /* total number of bytes that need to be read in */
180     int32  bytes;           /* number of elements / bytes to read next time */
181     int32  chunk;           /* number of records in a buffer */
182     int32  done;            /* number of records to do / done */
183     DYN_VWRITELIST *w = NULL;
184     DYN_VREADLIST  *r = NULL;
185     vsinstance_t   *wi = NULL;
186     VDATA          *vs = NULL;
187     int32      ret_value = SUCCEED;
188     CONSTR(FUNC, "VSread");
189 
190     /* clear error stack */
191     HEclear();
192 
193     /* check if vdata is part of vdata group */
194     if (HAatom_group(vkey) != VSIDGROUP)
195         HGOTO_ERROR(DFE_ARGS, FAIL);
196 
197     /* get vdata instance */
198     if (NULL == (wi = (vsinstance_t *) HAatom_object(vkey)))
199         HGOTO_ERROR(DFE_NOVS, FAIL);
200 
201     /* get vdata itself and check it */
202     vs = wi->vs;
203     if (vs == NULL)
204         HGOTO_ERROR(DFE_ARGS, FAIL);
205 
206     /* check access id and number of vertices in vdata */
207     if ((vs->aid == 0) || (vs->nvertices == 0))
208         HGOTO_ERROR(DFE_ARGS, FAIL);
209 
210     /* Don't allow reads in 0-field vdatas */
211     if (vs->wlist.n<=0)
212         HGOTO_ERROR(DFE_BADFIELDS, FAIL);
213 
214     /* check if vdata exists in file */
215     if (vexistvs(vs->f, vs->oref) == FAIL)
216         HGOTO_ERROR(DFE_NOVS, FAIL);
217 
218     /* check interlace parameter */
219     if (interlace != FULL_INTERLACE && interlace != NO_INTERLACE)
220         HGOTO_ERROR(DFE_ARGS, FAIL);
221 
222     /* read/write lists */
223     w = &(vs->wlist);
224     r = &(vs->rlist);
225     hsize = (intn)vs->wlist.ivsize;   /* size as stored in HDF */
226     total_bytes = hsize * nelt;
227 
228     /*
229        Now, convert and repack field(s) from Vtbuf into buf.
230 
231        This section of the code deals with interlacing. In all cases
232        the items for each of the fields are converted and shuffled
233        around from the internal buffer "Vtbuf" to the user's buffer
234        "buf".
235 
236        There are 5 cases :
237        (A) user=NO_INTERLACE   & vdata=FULL_INTERLACE)
238        (B) user=NO_INTERLACE   & vdata=NO_INTERLACE)
239        (C) user=FULL_INTERLACE & vdata=FULL_INTERLACE)
240        (D) user=FULL_INTERLACE & vadat=NO_INTERLACE)
241        (E) SPECIAL CASE when only one field.
242 
243        Cases (A)-(D) handles multiple fields.
244        Case (E) handles reading from a Vdata with a single field.
245 
246        Cases (E) and (C) are the most frequently used.  Limit buffer
247        allocations to VDATA_BUFFER_MAX size so that we conserve
248        memory.  Doing this involves a certain degree of added code
249        complexity so don't bother doing it for the less frequent
250        cases.  Cases E and C have been rolled together since they are
251        very similar and both need the incremental writing.
252 
253      */
254 
255     /* ----------------------------------------------------------------- */
256     /* CASE  (E + C): Easy to unroll case */
257     if ((w->n == 1) || (interlace == FULL_INTERLACE && vs->interlace == FULL_INTERLACE))
258       {
259           /*
260            * figure out how many elements we can move at a time and
261            * make sure our buffer is big enough
262            */
263 
264           if ((uint32) total_bytes < Vtbufsize)
265             {
266                 chunk = nelt;
267             }
268           else
269             {
270                 int32       buf_size;
271 
272                 /* we are bounded above by VDATA_BUFFER_MAX */
273                 buf_size = MIN(total_bytes, VDATA_BUFFER_MAX);
274 
275                 /* make sure there is at least room for one record in our buffer */
276                 chunk = buf_size / hsize + 1;
277 
278                 /* get a buffer big enough to hold the values */
279                 Vtbufsize = (size_t)chunk * (size_t)hsize;
280                 if (Vtbuf)
281                     HDfree(Vtbuf);
282                 if ((Vtbuf = (uint8 *) HDmalloc(Vtbufsize)) == NULL)
283                     HGOTO_ERROR(DFE_NOSPACE, FAIL);
284             }
285 
286           done = 0;
287 
288           /* set loop invariant parameters */
289           Src = buf;
290           bytes = hsize * chunk;
291 
292           for (uvsize = 0, j = 0; j < r->n; j++)
293               uvsize += w->esize[r->item[j]];
294 
295           while (done < nelt)
296             {
297 
298             /* chunk has changed so update the byte counts */
299             if (nelt - done < chunk)
300               {
301                   chunk = nelt - done;
302                   bytes = hsize * chunk;
303               }
304 
305             /* ================ start reading ============================== */
306             if ((nv = Hread(vs->aid, bytes, (uint8 *) Vtbuf)) != bytes)
307               {
308                   HERROR(DFE_READERROR);
309                   HEreport("Tried to read %d, only read %d", bytes, nv);
310                   HGOTO_DONE(FAIL);
311               }
312 
313             /* CASE  (E): Only a single field in the Vdata */
314             if (w->n == 1)
315               {
316                   DFKconvert(Vtbuf,Src,w->type[0], (uint32) w->order[0] * (uint32)chunk, DFACC_READ, 0, 0);
317               }     /* case (e) */
318             /* ----------------------------------------------------------------- */
319             /* CASE  (C):  iu=full, iv=full */
320             else
321               {
322                   offset = 0;
323                   for (j = 0; j < r->n; j++)
324                     {
325                         i = r->item[j];
326                         b1 = Src + offset;
327                         b2 = Vtbuf + (size_t)w->off[i];
328                         type = (int32)w->type[r->item[j]];
329                         esize = (intn)w->esize[i];
330                         isize = (intn)w->isize[i];
331                         order = (intn)w->order[i];
332 
333                         for (index = 0; index < order; index++)
334                           {
335                               DFKconvert(b2, b1, type, (uint32) chunk, DFACC_READ, (uint32) hsize, (uint32) uvsize);
336                               b1 += (int) esize / order;
337                               b2 += (int) isize / order;
338                           }
339                         offset += esize;
340                     }
341                 } /* case (E) */
342 
343                 /* record what we've done and move to next group */
344                 done += chunk;
345                 Src += chunk * uvsize;
346             } /* end while */
347           }     /* case (C + E) */
348     else {
349 	  /*
350 	   * Handle the other cases now.
351 	   * These cases are less frequent so don't bother unrolling
352 	   *   the loops for now.  As a result, we may get into memory
353 	   *   problems since we may end up allocating a huge buffer
354 	   */
355 
356         /* alloc space (Vtbuf) for reading in the raw data from vdata */
357         if (Vtbufsize < (size_t)nelt * (size_t) hsize)
358           {
359               Vtbufsize = (size_t)nelt * (size_t) hsize;
360               if (Vtbuf)
361                   HDfree(Vtbuf);
362               if ((Vtbuf = (uint8 *) HDmalloc(Vtbufsize)) == NULL)
363                   HGOTO_ERROR(DFE_NOSPACE, FAIL);
364           }
365 
366         /* ================ start reading ============================== */
367 
368         nv = Hread(vs->aid, nelt * hsize, (uint8 *) Vtbuf);
369 
370         if (nv != nelt * hsize)
371           {
372               HERROR(DFE_READERROR);
373               HEreport("Tried to read %d, only read %d", nelt * hsize, nv);
374               HGOTO_DONE(FAIL);
375           }
376 
377         /* ----------------------------------------------------------------- */
378         /* CASE  (A):  user=none, vdata=full */
379         if (interlace == NO_INTERLACE && vs->interlace == FULL_INTERLACE)
380           {
381               b1 = buf;
382               for (j = 0; j < r->n; j++)
383                 {
384                     i = r->item[j];
385                     b2 = Vtbuf + (size_t)w->off[i];
386                     type = (int32)w->type[i];
387                     isize = (intn)w->isize[i];
388                     esize = (intn)w->esize[i];
389                     order = (intn)w->order[i];
390 
391                     for (index = 0; index < order; index++)
392                       {
393                           DFKconvert(b2, b1, type, (uint32) nelt, DFACC_READ, (uint32) hsize, (uint32) esize);
394                           b2 += isize / order;
395                           b1 += esize / order;
396                       }
397                     b1 += ((nelt - 1) * esize);
398                 }
399           }     /* case (a) */
400 
401         /* ----------------------------------------------------------------- */
402         /* CASE  (B):  user=none, vdata=none */
403         else if (interlace == NO_INTERLACE && vs->interlace == NO_INTERLACE)
404           {
405               b1 = buf;
406               for (j = 0; j < r->n; j++)
407                 {
408                     i = r->item[j];
409                     b2 = Vtbuf + (size_t)w->off[i] * (size_t)nelt;
410                     type = (int32)w->type[i];
411                     esize = (intn)w->esize[i];
412                     isize = (intn)w->isize[i];
413                     order = (intn)w->order[i];
414 
415                     for (index = 0; index < order; index++)
416                       {
417                           DFKconvert(b2, b1, type, (uint32) nelt, DFACC_READ, (uint32) isize, (uint32) esize);
418                           b1 += esize / order;
419                           b2 += isize / order;
420                       }
421                     b1 += ((nelt - 1) * esize);
422                 }
423           }     /* case (b) */
424 
425         /* ----------------------------------------------------------------- */
426         /* CASE  (D):  user=full, vdata=none */
427         else if (interlace == FULL_INTERLACE && vs->interlace == NO_INTERLACE)
428           {
429 
430               for (uvsize = 0, j = 0; j < r->n; j++)
431                   uvsize += w->esize[r->item[j]];
432 
433               offset = 0;
434               for (j = 0; j < r->n; j++)
435                 {
436                     i = r->item[j];
437                     b1 = buf + offset;
438                     b2 = Vtbuf + (size_t)w->off[i] * (size_t)nelt;
439                     type = (int32)w->type[i];
440                     isize = (intn)w->isize[i];
441                     esize = (intn)w->esize[i];
442                     order = (intn)w->order[i];
443 
444                     for (index = 0; index < order; index++)
445                       {
446                           DFKconvert(b2, b1, type, (uint32) nelt, DFACC_READ, (uint32) isize, (uint32) uvsize);
447                           b1 += esize / order;
448                           b2 += isize / order;
449                       }
450                     offset += isize;
451                 }
452           }     /* case (d) */
453       } /* end else, cases a, b, and d */
454 
455     ret_value = (nelt);
456 
457 done:
458   if(ret_value == FAIL)
459     { /* Error condition cleanup */
460 
461     } /* end if */
462 
463   /* Normal function cleanup */
464   return ret_value;
465 }   /* VSread */
466 
467 /*******************************************************************************
468 NAME
469    VSwrite
470 
471 DESCRIPTION
472    Writes a specified number of elements' worth of data to a vdata.
473    You must specify how your data in your buffer is interlaced.
474 
475    NEW
476    create an aid, and write out if this is the first time.
477    (otherwise) subsequent writes result in link-blocks.
478 
479 RETURNS
480    RETURNS FAIL if error
481    RETURNS the number of elements written (0 or a +ve integer).
482 
483 *******************************************************************************/
484 int32
VSwrite(int32 vkey,const uint8 buf[],int32 nelt,int32 interlace)485 VSwrite(int32 vkey,         /* IN: vdata key */
486         const uint8 buf[],  /* IN: elements to write to vdata */
487         int32 nelt,         /* IN: number of elements */
488         int32 interlace     /* IN: interlace of elements 'buf' */)
489 {
490     intn isize = 0;
491     intn order = 0;
492     intn index = 0;
493     intn esize = 0;
494     uint8 *dest = NULL;
495     const uint8 *src, *Src;
496     int32       j;
497     int32       type;
498     int32       offset;
499     int32       position = 0;
500     int32       new_size;
501     int32       status;
502     int32       total_bytes;    /* total number of bytes that need to be written out */
503     DYN_VWRITELIST *w = NULL;
504     int32       int_size;       /* size of "element" as needed by user in memory */
505     intn        hdf_size = 0;   /* size of record in HDF file */
506     vsinstance_t *wi = NULL;
507     VDATA        *vs = NULL;
508     int32       bytes;          /* number of elements / bytes to write next time */
509     int32       chunk;
510     int32       done;    /* number of records to do / done */
511     int32       ret_value = SUCCEED;
512     CONSTR(FUNC, "VSwrite");
513 
514     /* clear error stack */
515     HEclear();
516 
517     /* check if vdata is part of vdata group */
518     if (HAatom_group(vkey) != VSIDGROUP)
519         HGOTO_ERROR(DFE_ARGS, FAIL);
520 
521     /* get vdata instance */
522     if (NULL == (wi = (vsinstance_t *) HAatom_object(vkey)))
523         HGOTO_ERROR(DFE_NOVS, FAIL);
524 
525     /* get vdata itself and check it. Also check number of elements */
526     vs = wi->vs;
527     if ((nelt <= 0) || (vs == NULL))
528         HGOTO_ERROR(DFE_ARGS, FAIL);
529 
530     /* check if write access to vdata */
531     if (vs->access != 'w')
532         HGOTO_ERROR(DFE_BADACC, FAIL);
533 
534     /* check if vdata exists in the file */
535     if (FAIL == vexistvs(vs->f, vs->oref))
536         HGOTO_ERROR(DFE_NOVS, FAIL);
537 
538     /* get write list */
539     w = & vs->wlist;
540     if (w->n == 0)
541       {
542           HERROR(DFE_NOVS);
543           HEreport("No fields set for writing");
544           HGOTO_DONE(FAIL);
545       }
546 
547     /* check interlace of input buffer */
548     if (interlace != NO_INTERLACE && interlace != FULL_INTERLACE)
549         HGOTO_ERROR(DFE_ARGS, FAIL);
550 
551     hdf_size = (intn)w->ivsize;   /* as stored in HDF file */
552     total_bytes = hdf_size * nelt;
553 
554     /* make sure we have a valid AID */
555     if (vs->aid == 0)
556       {
557 #ifdef OLD_WAY
558           vs->aid = Hstartwrite(vs->f, DFTAG_VS, vs->oref, total_bytes);
559           if (vs->aid == FAIL)
560               HGOTO_ERROR(DFE_BADAID, FAIL);
561 #else /* OLD_WAY */
562           HGOTO_ERROR(DFE_BADAID, FAIL);
563 #endif /* OLD_WAY */
564       }
565 
566     /*
567      * promote to link-block if vdata exists and is not already one
568      *  AND we are increasing its size
569      */
570     HQueryposition(vs->aid, &position);
571     new_size = (position / (intn)vs->wlist.ivsize) + nelt;
572 
573     /* this should really be cached in the Vdata structure */
574     for (int_size = 0, j = 0; j < w->n; j++)
575         int_size += w->esize[j];
576 
577     /*
578        First, convert and repack field(s) from Vtbuf into buf.
579 
580        This section of the code deals with interlacing. In all cases
581        the items for each of the fields are converted and shuffled
582        around from the user's buffer "buf" to the internal's buffer
583        "Vtbuf".  The data in "Vtbuf" is then written out to the vdata.
584 
585        There are 5 cases :
586        (A) user=NO_INTERLACE   & vdata=FULL_INTERLACE)
587        (B) user=NO_INTERLACE   & vdata=NO_INTERLACE)
588        (C) user=FULL_INTERLACE & vdata=FULL_INTERLACE)
589        (D) user=FULL_INTERLACE & vadat=NO_INTERLACE)
590        (E) SPECIAL CASE when only one field.
591 
592        Cases (A)-(D) handles multiple fields
593        Case (E) handles single field Vdatas
594 
595        Cases (E) and (C) are the most frequently used.  Limit buffer
596        allocations to VDATA_BUFFER_MAX size so that we conserve
597        memory.  Doing this involves a certain degree of added code
598        complexity so don't bother doing it for the less frequent
599        cases.  Cases E and C have been rolled together since they are
600        very similar and both need the incremental writing.
601 
602        --------------------------------------------------------------------- */
603     /* CASE  (E + C): Easy to unroll case */
604     if ((w->n == 1) || (interlace == FULL_INTERLACE && vs->interlace == FULL_INTERLACE))
605       {
606 
607           /*
608            * figure out how many elements we can move at a time and
609            * make sure our buffer is big enough
610            */
611 
612           if ((uint32) total_bytes < Vtbufsize)
613             {
614                 chunk = nelt;
615             }
616           else
617             {
618                 int32       buf_size;
619 
620                 /* we are bounded above by VDATA_BUFFER_MAX */
621                 buf_size = MIN(total_bytes, VDATA_BUFFER_MAX);
622 
623                 /* make sure there is at least room for one record in our buffer */
624                 chunk = buf_size / hdf_size + 1;
625 
626                 /* get a buffer big enough to hold the values */
627                 Vtbufsize = (size_t)chunk * (size_t)hdf_size;
628                 if (Vtbuf)
629                     HDfree(Vtbuf);
630                 if ((Vtbuf = (uint8 *) HDmalloc(Vtbufsize)) == NULL)
631                     HGOTO_ERROR(DFE_NOSPACE, FAIL);
632             }
633 
634           done = 0;
635 
636           /* set loop invariant parameters */
637           Src = buf;
638           dest = Vtbuf;
639           bytes = hdf_size * chunk;
640 
641           while (done < nelt)
642             {
643 
644                 /* chunk has changed so update the byte counts */
645                 if (nelt - done < chunk)
646                   {
647                       chunk = nelt - done;
648                       bytes = hdf_size * chunk;
649                   }
650 /*
651    printf("Case E/C: [%d,%d] writing %d (elems) %d bytes\n", done, nelt, chunk, bytes);
652  */
653 
654                 offset = 0;
655                 for (j = 0; j < w->n; j++)
656                   {
657                       src = Src + offset;
658                       dest = Vtbuf + (size_t)w->off[j];
659                       type = (int32)w->type[j];
660                       esize = (intn)w->esize[j];
661                       isize = (intn)w->isize[j];
662                       order = (intn)w->order[j];
663 
664                       for (index = 0; index < order; index++)
665                         {
666                             DFKconvert((VOIDP)src, dest, type, (uint32) chunk, DFACC_WRITE, (uint32) int_size, (uint32) hdf_size);
667                             dest += isize / order;
668                             src += esize / order;
669                         }
670                       offset += esize;
671                   }
672 
673                 /* write the converted data to the file */
674                 status = Hwrite(vs->aid, bytes, (uint8 *) Vtbuf);
675                 if (status != bytes)
676                     HGOTO_ERROR(DFE_WRITEERROR, FAIL);
677 
678                 /* record what we've done and move to next group */
679                 done += chunk;
680                 Src += chunk * int_size;
681             }
682 
683       }     /* case (C + E) */
684 
685     else
686       {
687 
688 	  /*
689 	   * Handle the other cases now.
690 	   * These cases are less frequent so don't bother unrolling
691 	   *   the loops for now.  As a result, we may get into memory
692 	   *   problems since we may end up allocating a huge buffer
693 	   */
694 
695 	  /* alloc space (Vtbuf) for writing out the data */
696 	  if (Vtbufsize < (uint32) total_bytes)
697 	    {
698           Vtbufsize = (uint32)total_bytes;
699           if (Vtbuf)
700               HDfree(Vtbuf);
701           if ((Vtbuf = (uint8 *) HDmalloc(Vtbufsize)) == NULL)
702               HGOTO_ERROR(DFE_NOSPACE, FAIL);
703 	    }
704 
705 	  /* ----------------------------------------------------------------- */
706 	  /* CASE  (A):  user=none, vdata=full */
707 	  if (interlace == NO_INTERLACE && vs->interlace == FULL_INTERLACE)
708 	    {
709 
710 		src = buf;
711 		for (j = 0; j < w->n; j++)
712 		  {
713 		      dest = Vtbuf + (size_t)w->off[j];
714 		      type = (int32)w->type[j];
715 		      esize = (intn)w->esize[j];
716 		      isize = (intn)w->isize[j];
717 		      order = (intn)w->order[j];
718 
719 		      for (index = 0; index < order; index++) {
720 			    DFKconvert((VOIDP)src, dest, type, (uint32) nelt, DFACC_WRITE, (uint32) esize, (uint32) hdf_size);
721 			    src += esize / order;
722 			    dest += isize / order;
723 			  }
724 		      src += ((nelt - 1) * esize);
725 		  }
726 
727 	    }	/* case (a) */
728 
729 	  /* --------------------------------------------------------------------- */
730 	  /* CASE  (B):  user=none, vdata=none */
731 	  else if (interlace == NO_INTERLACE && vs->interlace == NO_INTERLACE)
732 	    {
733 
734 		src = buf;
735 		for (j = 0; j < w->n; j++)
736 		  {
737 		      dest = Vtbuf + w->off[j] * nelt;
738 		      type = (int32)w->type[j];
739 		      esize = (intn)w->esize[j];
740 		      isize = (intn)w->isize[j];
741 		      order = (intn)w->order[j];
742 
743 		      for (index = 0; index < order; index++) {
744 			    DFKconvert((VOIDP)src, dest, type, (uint32) nelt, DFACC_WRITE, (uint32) esize, (uint32) isize);
745 			    dest += isize / order;
746 			    src += esize / order;
747 			  }
748 		      src += ((nelt - 1) * esize);
749 		  }
750 
751 	    }	/* case (b) */
752 
753 	  /* ----------------------------------------------------------------- */
754 	  /* CASE  (D):  user=full, vdata=none */
755 	  else if (interlace == FULL_INTERLACE && vs->interlace == NO_INTERLACE)
756 	    {
757 		offset = 0;
758 		for (j = 0; j < w->n; j++)
759 		  {
760 		      src = buf + offset;
761 		      dest = Vtbuf + w->off[j] * nelt;
762 		      type = (int32)w->type[j];
763 		      isize = (intn)w->isize[j];
764 		      esize = (intn)w->esize[j];
765 		      order = (intn)w->order[j];
766 
767 		      for (index = 0; index < order; index++) {
768 			    DFKconvert((VOIDP)src, dest, type, (uint32) nelt, DFACC_WRITE, (uint32) int_size, (uint32) isize);
769 			    dest += isize / order;
770 			    src += esize / order;
771   			  }
772 		      offset += esize;
773 		  }
774 	    }	/* case (d) */
775 
776 	  status = Hwrite(vs->aid, total_bytes, (uint8 *) Vtbuf);
777 	  if (status != total_bytes)
778 	      HGOTO_ERROR(DFE_WRITEERROR, FAIL);
779 
780       }     /* cases a, b, and d */
781 
782     /* update the internal structure to reflect write */
783     if (new_size > vs->nvertices)
784         vs->nvertices = new_size;
785     vs->marked = 1;
786 
787     ret_value = (nelt);
788 
789 done:
790   if(ret_value == FAIL)
791     { /* Error condition cleanup */
792 
793     } /* end if */
794 
795   /* Normal function cleanup */
796   return ret_value;
797 }	/* VSwrite */
798 
799