vlist_att.c 15.7 KB
Newer Older
1
2
3
4
#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

5
6
#include <stdio.h>
#include <string.h>
7
#include <assert.h>
8
9
10
11

#include "dmemory.h"

#include "cdi.h"
12
#include "cdi_int.h"
13
#include "vlist.h"
14
#include "error.h"
15
#include "serialize.h"
16

Uwe Schulzweida's avatar
Uwe Schulzweida committed
17
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
18
cdi_atts_t *get_attsp(vlist_t *vlistptr, int varID)
19
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
20
  cdi_atts_t *attsp = NULL;
21
22
23
24
25
26
27

  if ( varID == CDI_GLOBAL )
    {
      attsp = &vlistptr->atts;
    }
  else
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
28
29
      if ( varID >= 0 && varID < vlistptr->nvars )
	attsp = &(vlistptr->vars[varID].atts);
30
31
32
33
34
    }

  return (attsp);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
35
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
36
cdi_att_t *find_att(cdi_atts_t *attsp, const char *name)
37
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
38
  cdi_att_t *attp;
39
  size_t attid;
40
41
  size_t slen;

Deike Kleberg's avatar
Deike Kleberg committed
42
  xassert(attsp != NULL);
43
44
45
46
47

  if ( attsp->nelems == 0 ) return NULL;

  slen = strlen(name);

48
  for ( attid = 0; attid < attsp->nelems; attid++ )
49
    {
50
51
      attp = &(attsp->value[attid]);
      if ( attp->namesz == slen )
52
	if ( memcmp(attp->name, name, slen) == 0)
53
	  {
54
	    return (attp); /* Normal return */
55
56
57
58
59
60
	  }
    }

  return (NULL);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
61
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
62
cdi_att_t *new_att(cdi_atts_t *attsp, const char *name)
63
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
64
  cdi_att_t *attp;
65
66
  size_t slen;

Deike Kleberg's avatar
Deike Kleberg committed
67
68
  xassert(attsp != NULL);
  xassert(name  != NULL);
69
70
71

  if ( attsp->nelems == attsp->nalloc ) return (NULL);

72
  attp = &(attsp->value[attsp->nelems]);
73
74
75
76
  attsp->nelems++;

  slen = strlen(name);

77
78
79
  attp->name = (char *) malloc(slen+1);
  memcpy(attp->name, name, slen+1);
  attp->namesz = slen;
80
  attp->xvalue = NULL;
81

82
  return (attp);
83
84
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
85
static
86
void fill_att(cdi_att_t *attp, int indtype, int exdtype, size_t nelems, size_t xsz, const void *xvalue)
87
{
Deike Kleberg's avatar
Deike Kleberg committed
88
  xassert(attp != NULL);
89

90
  attp->xsz = xsz;
91
92
93
  attp->indtype = indtype;
  attp->exdtype = exdtype;
  attp->nelems  = nelems;
94

95
96
  if ( xsz > 0 )
    {
97
      attp->xvalue = xrealloc(attp->xvalue, xsz);
98
99
      memcpy(attp->xvalue, xvalue, xsz);
    }
100
101
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
102
103
104
105
106
107
/*
@Function  vlistInqNatts
@Title     Get number of variable attributes

@Prototype int vlistInqNatts(int vlistID, int varID, int *nattsp)
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
108
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}.
109
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
110
    @Item  nattsp   Pointer to location for returned number of variable attributes.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
111
112
113
114
115
116

@Description
The function @func{vlistInqNatts} gets the number of variable attributes assigned to this variable.

@EndFunction
*/
117
118
119
int vlistInqNatts(int vlistID, int varID, int *nattsp)
{
  int status = CDI_NOERR;
120
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
121
  cdi_atts_t *attsp;
122
123
124
125

  vlistptr = vlist_to_pointer(vlistID);
  
  attsp = get_attsp(vlistptr, varID);
Deike Kleberg's avatar
Deike Kleberg committed
126
  xassert(attsp != NULL);
127
128
129
130
131
132

  *nattsp = attsp->nelems;

  return (status);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
133
134
135
136
137
138
/*
@Function  vlistInqAtt
@Title     Get information about an attribute

@Prototype int vlistInqAtt(int vlistID, int varID, int attnum, char *name, int *typep, int *lenp)
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
139
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}.
140
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
141
142
143
    @Item  attnum   Attribute number (from 0 to natts-1).
    @Item  name     Pointer to the location for the returned attribute name. The caller must allocate space for the 
                    returned string. The maximum possible length, in characters, of
144
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Deike Kleberg's avatar
Deike Kleberg committed
145
146
    @Item  typep    Pointer to location for returned attribute type.
    @Item  lenp     Pointer to location for returned attribute number.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
147
148

@Description
149
The function @func{vlistInqAtt} gets information about an attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
150
151
152

@EndFunction
*/
153
int vlistInqAtt(int vlistID, int varID, int attnum, char *name, int *typep, int *lenp)
154
155
{
  int status = CDI_NOERR;
156
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
157
158
  cdi_att_t *attp = NULL;
  cdi_atts_t *attsp;
159

Deike Kleberg's avatar
Deike Kleberg committed
160
  xassert(name != NULL);
161
162
163
164

  vlistptr = vlist_to_pointer(vlistID);

  attsp = get_attsp(vlistptr, varID);
Deike Kleberg's avatar
Deike Kleberg committed
165
  xassert(attsp != NULL);
166

167
168
  if ( attnum >= 0 && attnum < (int)attsp->nelems )
    attp = &(attsp->value[attnum]);
169

170
  if ( attp != NULL ) /* name in use */
171
    {
172
      memcpy(name, attp->name, attp->namesz+1);
173
      *typep  = attp->exdtype;
174
      *lenp   = attp->nelems;
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
    }
  else
    {
      name[0] =  0;
      *typep  = -1;
      *lenp   =  0;
    }

  return (status);
}


int vlistDelAtts(int vlistID, int varID)
{
  int status = CDI_NOERR;
190
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
191
192
  cdi_att_t *attp = NULL;
  cdi_atts_t *attsp;
193
  int attid;
194
195
196
197

  vlistptr = vlist_to_pointer(vlistID);

  attsp = get_attsp(vlistptr, varID);
Deike Kleberg's avatar
Deike Kleberg committed
198
  xassert(attsp != NULL);
199

200
  for ( attid = 0; attid < (int)attsp->nelems; attid++ )
201
    {
202
203
204
      attp = &(attsp->value[attid]);
      if ( attp->name   ) free(attp->name);
      if ( attp->xvalue ) free(attp->xvalue);
205
206
207
208
209
210
211
212
    }

  attsp->nelems = 0;

  return (status);
}


213
int vlistDelAtt(int vlistID, int varID, const char *name)
214
215
216
{
  int status = CDI_NOERR;

217
  fprintf(stderr, "vlistDelAtt not implemented!\n");
218
219
220
221

  return (status);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
222
static
223
int vlist_def_att(int indtype, int exdtype, int vlistID, int varID, const char *name, size_t len, size_t xsz, const void *xp)
224
225
{
  int status = CDI_NOERR;
226
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
227
228
  cdi_att_t *attp;
  cdi_atts_t *attsp;
229
230
231
232
233
234
235
236
237

  if ( len != 0 && xp == NULL ) /* Null arg */
    {
      return (CDI_EINVAL);
    }

  vlistptr = vlist_to_pointer(vlistID);

  attsp = get_attsp(vlistptr, varID);
Deike Kleberg's avatar
Deike Kleberg committed
238
  xassert(attsp != NULL);
239

240
  attp = find_att(attsp, name);
241
242
  if ( attp == NULL )
    attp = new_att(attsp, name);
243

244
  if ( attp != NULL )
245
    fill_att(attp, indtype, exdtype, len, xsz, xp);
246

247
248
249
  return (status);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
250
static
251
int vlist_inq_att(int indtype, int vlistID, int varID, const char *name, size_t mxsz, void *xp)
252
253
{
  int status = CDI_NOERR;
254
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
255
256
  cdi_att_t *attp;
  cdi_atts_t *attsp;
257
258
259
260
261
262
263
264
265
266
  size_t xsz;

  if ( mxsz != 0 && xp == NULL ) /* Null arg */
    {
      return (CDI_EINVAL);
    }

  vlistptr = vlist_to_pointer(vlistID);

  attsp = get_attsp(vlistptr, varID);
Deike Kleberg's avatar
Deike Kleberg committed
267
  xassert(attsp != NULL);
268

269
270
  attp = find_att(attsp, name);
  if ( attp != NULL ) /* name in use */
271
    {
272
273
274
275
276
277
278
279
280
281
282
      if ( attp->indtype == indtype )
	{
	  xsz = attp->xsz;
	  if ( mxsz < xsz ) xsz = mxsz;
	  if ( xsz > 0 )
	    memcpy(xp, attp->xvalue, xsz);
	}
      else
	{
	  Warning("Attribute %s has wrong data type!", name);
	}
283
284
285
    }
  else
    {
286
      Warning("Internal problem, attribute %s not found!", name);
287
288
289
290
291
292
293
294
295
    }

  return (status);
}


int vlistCopyVarAtts(int vlistID1, int varID_1, int vlistID2, int varID_2)
{
  int status = CDI_NOERR;
296
  vlist_t *vlistptr1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
297
298
  cdi_att_t *attp = NULL;
  cdi_atts_t *attsp1;
299
  int attid;
300
301
302
303

  vlistptr1 = vlist_to_pointer(vlistID1);

  attsp1 = get_attsp(vlistptr1, varID_1);
Deike Kleberg's avatar
Deike Kleberg committed
304
  xassert(attsp1 != NULL);
305

306
  for ( attid = 0; attid < (int)attsp1->nelems; attid++ )
307
    {
308
      attp = &(attsp1->value[attid]);
309
      vlist_def_att(attp->indtype, attp->exdtype, vlistID2, varID_2, attp->name, attp->nelems, attp->xsz, attp->xvalue);
310
311
312
313
314
    }

  return (status);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
315
316
317
318
/*
@Function  vlistDefAttInt
@Title     Define an integer attribute

319
@Prototype int vlistDefAttInt(int vlistID, int varID, const char *name, int type, int len, const int *ip)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
320
321

@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
322
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}.
323
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
324
    @Item  name     Attribute name.
325
    @Item  type     External data type (@func{DATATYPE_INT16} or @func{DATATYPE_INT32}).
Deike Kleberg's avatar
Deike Kleberg committed
326
327
    @Item  len      Number of values provided for the attribute.
    @Item  ip       Pointer to one or more integer values.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
328
329
330
331
332
333

@Description
The function @func{vlistDefAttInt} defines an integer attribute.

@EndFunction
*/
334
int vlistDefAttInt(int vlistID, int varID, const char *name, int type, int len, const int *ip)
335
{
336
  return vlist_def_att(DATATYPE_INT, type, vlistID, varID, name, (size_t) len, len*sizeof(int), (const void *) ip);
337
338
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
339
340
341
342
/*
@Function  vlistDefAttFlt
@Title     Define a floating point attribute

343
@Prototype int vlistDefAttFlt(int vlistID, int varID, const char *name, int type, int len, const double *dp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
344
345

@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
346
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}.
347
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
348
    @Item  name     Attribute name.
349
    @Item  type     External data type (@func{DATATYPE_FLT32} or @func{DATATYPE_FLT64}).
Deike Kleberg's avatar
Deike Kleberg committed
350
351
    @Item  len      Number of values provided for the attribute.
    @Item  dp       Pointer to one or more floating point values.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
352
353
354
355
356
357

@Description
The function @func{vlistDefAttFlt} defines a floating point attribute.

@EndFunction
*/
358
int vlistDefAttFlt(int vlistID, int varID, const char *name, int type, int len, const double *dp)
359
{
360
  return vlist_def_att(DATATYPE_FLT, type, vlistID, varID, name, (size_t) len, len*sizeof(double), (const void *) dp);
361
362
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
363
364
365
366
367
368
369
/*
@Function  vlistDefAttTxt
@Title     Define a text attribute

@Prototype int vlistDefAttTxt(int vlistID, int varID, const char *name, int len, const char *tp)

@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
370
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}.
371
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
372
373
374
    @Item  name     Attribute name.
    @Item  len      Number of values provided for the attribute.
    @Item  tp       Pointer to one or more character values.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
375
376
377
378
379
380

@Description
The function @func{vlistDefAttTxt} defines a text attribute.

@EndFunction
*/
381
int vlistDefAttTxt(int vlistID, int varID, const char *name, int len, const char *tp)
382
{
383
  return vlist_def_att(DATATYPE_TXT, DATATYPE_TXT, vlistID, varID, name, (size_t) len, len*sizeof(char), (const void *) tp);
384
385
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
386
387
388
389
390
391
/*
@Function  vlistInqAttInt
@Title     Get the value(s) of an integer attribute

@Prototype int vlistInqAttInt(int vlistID, int varID, const char *name, int mlen, int *ip)
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
392
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}.
393
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
394
395
396
    @Item  name     Attribute name.
    @Item  mlen     Number of allocated values provided for the attribute.
    @Item  ip       Pointer location for returned integer attribute value(s).
397

Uwe Schulzweida's avatar
Uwe Schulzweida committed
398
399
400
401
402
@Description
The function @func{vlistInqAttInt} gets the values(s) of an integer attribute.

@EndFunction
*/
403
int vlistInqAttInt(int vlistID, int varID, const char *name, int mlen, int *ip)
404
{
405
  return vlist_inq_att(DATATYPE_INT, vlistID, varID, name, mlen*sizeof(int), (void *) ip);
406
407
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
408
409
410
411
/*
@Function  vlistInqAttFlt
@Title     Get the value(s) of a floating point attribute

412
@Prototype int vlistInqAttFlt(int vlistID, int varID, const char *name, int mlen, double *dp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
413
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
414
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}.
415
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
416
417
418
    @Item  name     Attribute name.
    @Item  mlen     Number of allocated values provided for the attribute.
    @Item  dp       Pointer location for returned floating point attribute value(s).
Uwe Schulzweida's avatar
Uwe Schulzweida committed
419
420
421
422
423
424

@Description
The function @func{vlistInqAttFlt} gets the values(s) of a floating point attribute.

@EndFunction
*/
425
int vlistInqAttFlt(int vlistID, int varID, const char *name, int mlen, double *dp)
426
{
427
  return vlist_inq_att(DATATYPE_FLT, vlistID, varID, name, mlen*sizeof(double), (void *) dp);
428
429
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
430
431
432
433
/*
@Function  vlistInqAttTxt
@Title     Get the value(s) of a text attribute

434
@Prototype int vlistInqAttTxt(int vlistID, int varID, const char *name, int mlen, char *tp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
435
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
436
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}.
437
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
438
439
440
    @Item  name     Attribute name.
    @Item  mlen     Number of allocated values provided for the attribute.
    @Item  tp       Pointer location for returned text attribute value(s).
Uwe Schulzweida's avatar
Uwe Schulzweida committed
441
442
443
444
445
446

@Description
The function @func{vlistInqAttTxt} gets the values(s) of a text attribute.

@EndFunction
*/
447
int vlistInqAttTxt(int vlistID, int varID, const char *name, int mlen, char *tp)
448
{
449
  return vlist_inq_att(DATATYPE_TXT, vlistID, varID, name, mlen*sizeof(char), (void *) tp);
450
}
451
452
453
454
455

enum {
  vlist_att_nints = 4,          /* namesz, exdtype, indtype, nelems */
};

456
457
static inline int
vlistAttTypeLookup(cdi_att_t *attp)
458
{
459
  int type;
Thomas Jahns's avatar
Thomas Jahns committed
460
  switch (attp->indtype)
461
462
  {
  case DATATYPE_FLT:
463
    type = DATATYPE_FLT64;
464
465
466
    break;
  case DATATYPE_INT:
  case DATATYPE_TXT:
467
    type = attp->indtype;
468
469
    break;
  default:
470
    xabort("Unknown datatype encountered in attribute %s: %d\n",
Thomas Jahns's avatar
Thomas Jahns committed
471
            attp->name, attp->indtype);
472
  }
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
  return type;
}

static int
vlistAttGetSize(vlist_t *vlistptr, int varID, int attnum, void *context)
{
  cdi_atts_t *attsp;
  cdi_att_t *attp;

  xassert(attsp = get_attsp(vlistptr, varID));
  xassert(attnum >= 0 && attnum < (int)attsp->nelems);
  attp = &(attsp->value[attnum]);
  int txsize = serializeGetSize(vlist_att_nints, DATATYPE_INT, context)
    + serializeGetSize(attp->namesz, DATATYPE_TXT, context);
  txsize += serializeGetSize((int)attp->nelems, vlistAttTypeLookup(attp), context);
488
489
490
491
  return txsize;
}

int
492
vlistAttsGetSize(vlist_t *p, int varID, void *context)
493
494
495
{
  int numAtts, i;
  cdi_atts_t *attsp = get_attsp(p, varID);
496
  int txsize = serializeGetSize(1, DATATYPE_INT, context);
497
498
  numAtts = attsp->nelems;
  for (i = 0; i < numAtts; ++i)
499
    txsize += vlistAttGetSize(p, varID, i, context);
500
501
502
  return txsize;
}

503
static void
504
vlistAttPack(vlist_t *vlistptr, int varID, int attnum,
505
             void * buf, int size, int *position, void *context)
506
507
508
509
510
{
  cdi_atts_t *attsp;
  cdi_att_t *attp;
  int tempbuf[vlist_att_nints];

Deike Kleberg's avatar
Deike Kleberg committed
511
512
  xassert(attsp = get_attsp(vlistptr, varID));
  xassert(attnum >= 0 && attnum < (int)attsp->nelems);
513
514
515
516
517
  attp = &(attsp->value[attnum]);
  tempbuf[0] = attp->namesz;
  tempbuf[1] = attp->exdtype;
  tempbuf[2] = attp->indtype;
  tempbuf[3] = attp->nelems;
518
519
520
521
  serializePack(tempbuf, vlist_att_nints, DATATYPE_INT, buf, size, position, context);
  serializePack(attp->name, attp->namesz, DATATYPE_TXT, buf, size, position, context);
  serializePack(attp->xvalue, (int)attp->nelems, vlistAttTypeLookup(attp),
                buf, size, position, context);
522
523
524
525
}

void
vlistAttsPack(vlist_t *p, int varID,
526
              void * buf, int size, int *position, void *context)
527
528
529
530
{
  int numAtts, i;
  cdi_atts_t *attsp = get_attsp(p, varID);
  numAtts = attsp->nelems;
531
  serializePack(&numAtts, 1, DATATYPE_INT, buf, size, position, context);
532
  for (i = 0; i < numAtts; ++i)
533
    vlistAttPack(p, varID, i, buf, size, position, context);
534
535
}

536
static void
537
vlistAttUnpack(int vlistID, int varID,
538
               void * buf, int size, int *position, void *context)
539
540
541
{
  char *attName;
  int tempbuf[vlist_att_nints];
542
  int attVDt;
543
  int elemSize;
544

545
546
  serializeUnpack(buf, size, position,
                  tempbuf, vlist_att_nints, DATATYPE_INT, context);
547
  attName = xmalloc(tempbuf[0] + 1);
548
  serializeUnpack(buf, size, position, attName, tempbuf[0], DATATYPE_TXT, context);
549
  attName[tempbuf[0]] = '\0';
550
551
552
  switch (tempbuf[2])
  {
  case DATATYPE_FLT:
553
    attVDt = DATATYPE_FLT64;
554
555
556
    elemSize = sizeof(double);
    break;
  case DATATYPE_INT:
557
    attVDt = DATATYPE_INT;
558
559
560
    elemSize = sizeof(int);
    break;
  case DATATYPE_TXT:
561
    attVDt = DATATYPE_TXT;
562
563
564
    elemSize = 1;
    break;
  default:
565
566
    xabort("Unknown datatype encountered in attribute %s: %d\n",
           attName, tempbuf[2]);
567
  }
568
569
  void *attData = xmalloc(elemSize * tempbuf[3]);
  serializeUnpack(buf, size, position, attData, tempbuf[3], attVDt, context);
570
571
572
573
574
575
576
577
  vlist_def_att(tempbuf[2], tempbuf[1], vlistID, varID, attName,
                tempbuf[3], tempbuf[3] * elemSize, attData);
  free(attName);
  free(attData);
}

void
vlistAttsUnpack(int vlistID, int varID,
578
                void * buf, int size, int *position, void *context)
579
580
{
  int numAtts, i;
581
  serializeUnpack(buf, size, position, &numAtts, 1, DATATYPE_INT, context);
582
583
  for (i = 0; i < numAtts; ++i)
  {
584
    vlistAttUnpack(vlistID, varID, buf, size, position, context);
585
586
587
  }
}

588
589
590
591
592
593
594
595
596
/*
 * Local Variables:
 * c-file-style: "Java"
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * show-trailing-whitespace: t
 * require-trailing-newline: t
 * End:
 */