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

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

#include "dmemory.h"

#include "cdi.h"
13
#include "cdi_int.h"
14
#include "vlist.h"
15
#include "cdi_att.h"
16
#include "error.h"
17
#include "serialize.h"
18 19 20
#include "grid.h"
#include "resource_unpack.h"

21

Uwe Schulzweida's avatar
Uwe Schulzweida committed
22
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
23
cdi_atts_t *get_attsp(vlist_t *vlistptr, int varID)
24
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
25
  cdi_atts_t *attsp = NULL;
26 27 28 29 30 31 32

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

37
  return attsp;
38 39
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
40
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
41
cdi_att_t *find_att(cdi_atts_t *attsp, const char *name)
42
{
Deike Kleberg's avatar
Deike Kleberg committed
43
  xassert(attsp != NULL);
44 45 46

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

47
  size_t slen = strlen(name);
48
  if ( slen > CDI_MAX_NAME ) slen = CDI_MAX_NAME;
49

Thomas Jahns's avatar
Thomas Jahns committed
50
  cdi_att_t *atts = attsp->value;
51
  for ( size_t attid = 0; attid < attsp->nelems; attid++ )
52
    {
Thomas Jahns's avatar
Thomas Jahns committed
53
      cdi_att_t *attp = atts + attid;
54
      if ( attp->namesz == slen && memcmp(attp->name, name, slen) == 0 )
55
        return attp; /* Normal return */
56 57
    }

58
  return NULL;
59 60
}

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
{
Deike Kleberg's avatar
Deike Kleberg committed
64 65
  xassert(attsp != NULL);
  xassert(name  != NULL);
66

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

69
  cdi_att_t *attp = &(attsp->value[attsp->nelems]);
70 71
  attsp->nelems++;

72
  size_t slen = strlen(name);
73
  if ( slen > CDI_MAX_NAME ) slen = CDI_MAX_NAME;
74

75
  attp->name = (char *) Malloc(slen+1);
76 77
  memcpy(attp->name, name, slen+1);
  attp->namesz = slen;
78
  attp->xvalue = NULL;
79

80
  return attp;
81 82
}

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

88
  attp->xsz = xsz;
89 90 91
  attp->indtype = indtype;
  attp->exdtype = exdtype;
  attp->nelems  = nelems;
92

93 94
  if ( xsz > 0 )
    {
95
      attp->xvalue = Realloc(attp->xvalue, xsz);
96 97
      memcpy(attp->xvalue, xvalue, xsz);
    }
98 99
}

100 101 102
static
cdi_atts_t *cdi_get_attsp(int objID, int varID)
{
103
  cdi_atts_t *attsp = NULL;
104

105 106 107 108 109 110 111 112 113 114
  if ( varID == CDI_GLOBAL && reshGetTxCode(objID) == GRID )
    {
      grid_t *gridptr = gridID2Ptr(objID);
      attsp = &gridptr->atts;
    }
  else
    {
      vlist_t *vlistptr = vlist_to_pointer(objID);
      attsp = get_attsp(vlistptr, varID);
    }
115 116 117 118

  return attsp;
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
119
/*
120
@Function  cdiInqNatts
Uwe Schulzweida's avatar
Uwe Schulzweida committed
121
@Title     Get number of attributes
Uwe Schulzweida's avatar
Uwe Schulzweida committed
122

123
@Prototype int cdiInqNatts(int cdiID, int varID, int *nattsp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
124
@Parameter
125
    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}.
126
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
127
    @Item  nattsp   Pointer to location for returned number of attributes.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
128 129

@Description
130
The function @func{cdiInqNatts} gets the number of attributes assigned to this variable.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
131 132 133

@EndFunction
*/
134
int cdiInqNatts(int cdiID, int varID, int *nattsp)
135 136 137
{
  int status = CDI_NOERR;

138
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
139
  xassert(attsp != NULL);
140

141
  *nattsp = (int)attsp->nelems;
142

143
  return status;
144 145
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
146
/*
147
@Function  cdiInqAtt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
148 149
@Title     Get information about an attribute

150
@Prototype int cdiInqAtt(int cdiID, int varID, int attnum, char *name, int *typep, int *lenp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
151
@Parameter
152
    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}.
153
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
154
    @Item  attnum   Attribute number (from 0 to natts-1).
155
    @Item  name     Pointer to the location for the returned attribute name. The caller must allocate space for the
Deike Kleberg's avatar
Deike Kleberg committed
156
                    returned string. The maximum possible length, in characters, of
157
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Deike Kleberg's avatar
Deike Kleberg committed
158 159
    @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
160 161

@Description
162
The function @func{cdiInqAtt} gets information about an attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
163 164 165

@EndFunction
*/
166
int cdiInqAtt(int cdiID, int varID, int attnum, char *name, int *typep, int *lenp)
167 168 169
{
  int status = CDI_NOERR;

Deike Kleberg's avatar
Deike Kleberg committed
170
  xassert(name != NULL);
171

172
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
173
  xassert(attsp != NULL);
174

175
  cdi_att_t *attp = NULL;
176 177
  if ( attnum >= 0 && attnum < (int)attsp->nelems )
    attp = &(attsp->value[attnum]);
178

179
  if ( attp != NULL ) /* name in use */
180
    {
181
      memcpy(name, attp->name, attp->namesz+1);
182
      *typep  = attp->exdtype;
183
      *lenp   = (int)attp->nelems;
184 185 186 187 188 189
    }
  else
    {
      name[0] =  0;
      *typep  = -1;
      *lenp   =  0;
190
      status  = -1;
191 192
    }

193
  return status;
194 195 196
}


197
int cdiDelAtts(int cdiID, int varID)
198 199 200
{
  int status = CDI_NOERR;

201
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
202
  xassert(attsp != NULL);
203

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

  attsp->nelems = 0;

213
  return status;
214 215 216
}


217
int cdiDelAtt(int cdiID, int varID, const char *name)
218 219 220
{
  int status = CDI_NOERR;

221
  UNUSED(cdiID);
222 223 224
  UNUSED(varID);
  UNUSED(name);

225
  fprintf(stderr, "cdiDelAtt not implemented!\n");
226

227
  return status;
228 229
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
230
static
231
int cdi_def_att(int indtype, int exdtype, int cdiID, int varID, const char *name, size_t len, size_t xsz, const void *xp)
232 233 234 235
{
  int status = CDI_NOERR;

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

238
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
239
  xassert(attsp != NULL);
240

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

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

246
  return status;
247 248
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
249
static
250
int cdi_inq_att(int indtype, int cdiID, int varID, const char *name, size_t mxsz, void *xp)
251 252 253 254
{
  int status = CDI_NOERR;

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

257
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
258
  xassert(attsp != NULL);
259

260
  cdi_att_t *attp = find_att(attsp, name);
261
  if ( attp != NULL ) /* name in use */
262
    {
263 264
      if ( attp->indtype == indtype )
	{
265
	  size_t xsz = attp->xsz;
266 267 268 269 270 271 272
	  if ( mxsz < xsz ) xsz = mxsz;
	  if ( xsz > 0 )
	    memcpy(xp, attp->xvalue, xsz);
	}
      else
	{
	  Warning("Attribute %s has wrong data type!", name);
273
          status = -2;
274
	}
275 276 277
    }
  else
    {
278 279
      //Warning("Internal problem, attribute %s not found!", name);
      status = -1;
280 281
    }

282
  return status;
283 284 285
}


286
int cdiCopyVarAtts(int cdiID1, int varID_1, int cdiID2, int varID_2)
287 288 289
{
  int status = CDI_NOERR;

290
  cdi_atts_t *attsp1 = cdi_get_attsp(cdiID1, varID_1);
Deike Kleberg's avatar
Deike Kleberg committed
291
  xassert(attsp1 != NULL);
292

293
  for ( int attid = 0; attid < (int)attsp1->nelems; attid++ )
294
    {
295
      cdi_att_t *attp = &(attsp1->value[attid]);
296
      cdi_def_att(attp->indtype, attp->exdtype, cdiID2, varID_2, attp->name, attp->nelems, attp->xsz, attp->xvalue);
297 298
    }

299
  return status;
300 301
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
302
/*
303
@Function  cdiDefAttInt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
304 305
@Title     Define an integer attribute

306
@Prototype int cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, const int *ip)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
307 308

@Parameter
309
    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate} or @fref{gridCreate}.
310
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
311
    @Item  name     Attribute name.
312
    @Item  type     External data type (@func{DATATYPE_INT16} or @func{DATATYPE_INT32}).
Deike Kleberg's avatar
Deike Kleberg committed
313 314
    @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
315 316

@Description
317
The function @func{cdiDefAttInt} defines an integer attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
318 319 320

@EndFunction
*/
321
int cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, const int *ip)
322
{
323
  return cdi_def_att(DATATYPE_INT, type, cdiID, varID, name, (size_t)len, (size_t)len * sizeof(int), ip);
324 325
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
326
/*
327
@Function  cdiDefAttFlt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
328 329
@Title     Define a floating point attribute

330
@Prototype int cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, const double *dp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
331 332

@Parameter
333
    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate} or @fref{gridCreate}.
334
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
335
    @Item  name     Attribute name.
336
    @Item  type     External data type (@func{DATATYPE_FLT32} or @func{DATATYPE_FLT64}).
Deike Kleberg's avatar
Deike Kleberg committed
337 338
    @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
339 340

@Description
341
The function @func{cdiDefAttFlt} defines a floating point attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
342 343 344

@EndFunction
*/
345
int cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, const double *dp)
346
{
347
  return cdi_def_att(DATATYPE_FLT, type, cdiID, varID, name, (size_t)len, (size_t)len * sizeof(double), dp);
348 349
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
350
/*
351
@Function  cdiDefAttTxt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
352 353
@Title     Define a text attribute

354
@Prototype int cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
355 356

@Parameter
357
    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate} or @fref{gridCreate}.
358
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
359 360 361
    @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
362 363

@Description
364
The function @func{cdiDefAttTxt} defines a text attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
365 366 367

@EndFunction
*/
368
int cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp)
369
{
370
  return cdi_def_att(DATATYPE_TXT, DATATYPE_TXT, cdiID, varID, name, (size_t)len, (size_t)len, tp);
371 372
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
373
/*
374
@Function  cdiInqAttInt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
375 376
@Title     Get the value(s) of an integer attribute

377
@Prototype int cdiInqAttInt(int cdiID, int varID, const char *name, int mlen, int *ip)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
378
@Parameter
379
    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}.
380
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
381 382 383
    @Item  name     Attribute name.
    @Item  mlen     Number of allocated values provided for the attribute.
    @Item  ip       Pointer location for returned integer attribute value(s).
384

Uwe Schulzweida's avatar
Uwe Schulzweida committed
385
@Description
386
The function @func{cdiInqAttInt} gets the values(s) of an integer attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
387 388 389

@EndFunction
*/
390
int cdiInqAttInt(int cdiID, int varID, const char *name, int mlen, int *ip)
391
{
392
  return cdi_inq_att(DATATYPE_INT, cdiID, varID, name, (size_t)mlen * sizeof(int), ip);
393 394
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
395
/*
396
@Function  cdiInqAttFlt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
397 398
@Title     Get the value(s) of a floating point attribute

399
@Prototype int cdiInqAttFlt(int cdiID, int varID, const char *name, int mlen, double *dp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
400
@Parameter
401
    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}.
402
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
403 404 405
    @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
406 407

@Description
408
The function @func{cdiInqAttFlt} gets the values(s) of a floating point attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
409 410 411

@EndFunction
*/
412
int cdiInqAttFlt(int cdiID, int varID, const char *name, int mlen, double *dp)
413
{
414
  return cdi_inq_att(DATATYPE_FLT, cdiID, varID, name, (size_t)mlen * sizeof(double), dp);
415 416
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
417
/*
418
@Function  cdiInqAttTxt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
419 420
@Title     Get the value(s) of a text attribute

421
@Prototype int cdiInqAttTxt(int cdiID, int varID, const char *name, int mlen, char *tp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
422
@Parameter
423
    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}.
424
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
425 426 427
    @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
428 429

@Description
430
The function @func{cdiInqAttTxt} gets the values(s) of a text attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
431 432 433

@EndFunction
*/
434
int cdiInqAttTxt(int cdiID, int varID, const char *name, int mlen, char *tp)
435
{
436
  return cdi_inq_att(DATATYPE_TXT, cdiID, varID, name, (size_t)mlen * sizeof(char), tp);
437
}
438 439

enum {
440
  cdi_att_nints = 4,          /* namesz, exdtype, indtype, nelems */
441 442
};

443 444
static inline
int cdiAttTypeLookup(cdi_att_t *attp)
445
{
446
  int type;
Thomas Jahns's avatar
Thomas Jahns committed
447
  switch (attp->indtype)
448 449
  {
  case DATATYPE_FLT:
450
    type = DATATYPE_FLT64;
451 452 453
    break;
  case DATATYPE_INT:
  case DATATYPE_TXT:
454
    type = attp->indtype;
455 456
    break;
  default:
457
    xabort("Unknown datatype encountered in attribute %s: %d\n",
Thomas Jahns's avatar
Thomas Jahns committed
458
            attp->name, attp->indtype);
459
  }
460 461 462
  return type;
}

Thomas Jahns's avatar
Thomas Jahns committed
463

464
int cdi_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB, int attnum)
Thomas Jahns's avatar
Thomas Jahns committed
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
{
  cdi_atts_t *attspa = get_attsp(a, varIDA),
    *attspb = get_attsp(b, varIDB);
  if (attspa == NULL && attspb == NULL)
    return 0;
  xassert(attnum >= 0 && attnum < (int)attspa->nelems
          && attnum < (int)attspb->nelems);
  cdi_att_t *attpa = attspa->value + attnum,
    *attpb = attspb->value + attnum;
  size_t len;
  if ((len = attpa->namesz) != attpb->namesz)
    return 1;
  int diff;
  if ((diff = memcmp(attpa->name, attpb->name, len)))
    return 1;
  if (attpa->indtype != attpb->indtype
      || attpa->exdtype != attpb->exdtype
      || attpa->nelems != attpb->nelems)
    return 1;
  return memcmp(attpa->xvalue, attpb->xvalue, attpa->xsz);
}


488 489
static
int cdiAttGetSize(vlist_t *vlistptr, int varID, int attnum, void *context)
490 491 492 493 494 495 496
{
  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]);
497
  int txsize = serializeGetSize(cdi_att_nints, DATATYPE_INT, context)
498
    + serializeGetSize((int)attp->namesz, DATATYPE_TXT, context);
499
  txsize += serializeGetSize((int)attp->nelems, cdiAttTypeLookup(attp), context);
500 501 502
  return txsize;
}

503

504
int cdiAttsGetSize(void *vp, int varID, void *context)
505
{
506
  vlist_t *p = (vlist_t*) vp;
507
  cdi_atts_t *attsp = get_attsp(p, varID);
508
  int txsize = serializeGetSize(1, DATATYPE_INT, context);
509 510
  size_t numAtts = attsp->nelems;
  for (size_t i = 0; i < numAtts; ++i)
511
    txsize += cdiAttGetSize(p, varID, (int)i, context);
512 513 514
  return txsize;
}

515
static
516 517
void cdiAttPack(vlist_t *vlistptr, int varID, int attnum,
                void *buf, int size, int *position, void *context)
518 519 520
{
  cdi_atts_t *attsp;
  cdi_att_t *attp;
521
  int tempbuf[cdi_att_nints];
522

Deike Kleberg's avatar
Deike Kleberg committed
523 524
  xassert(attsp = get_attsp(vlistptr, varID));
  xassert(attnum >= 0 && attnum < (int)attsp->nelems);
525
  attp = &(attsp->value[attnum]);
526
  tempbuf[0] = (int)attp->namesz;
527 528
  tempbuf[1] = attp->exdtype;
  tempbuf[2] = attp->indtype;
529
  tempbuf[3] = (int)attp->nelems;
530
  serializePack(tempbuf, cdi_att_nints, DATATYPE_INT, buf, size, position, context);
531
  serializePack(attp->name, (int)attp->namesz, DATATYPE_TXT, buf, size, position, context);
532
  serializePack(attp->xvalue, (int)attp->nelems, cdiAttTypeLookup(attp),
533
                buf, size, position, context);
534 535
}

536 537

void cdiAttsPack(void *vp, int varID, void *buf, int size, int *position, void *context)
538
{
539
  vlist_t *p = (vlist_t*) vp;
540
  cdi_atts_t *attsp = get_attsp(p, varID);
541 542 543 544 545
  size_t numAtts = attsp->nelems;
  int numAttsI = (int)numAtts;
  xassert(numAtts <= INT_MAX);
  serializePack(&numAttsI, 1, DATATYPE_INT, buf, size, position, context);
  for (size_t i = 0; i < numAtts; ++i)
546
    cdiAttPack(p, varID, (int)i, buf, size, position, context);
547 548
}

549
static
550
void cdiAttUnpack(int cdiID, int varID, void *buf, int size, int *position, void *context)
551
{
552
  int tempbuf[cdi_att_nints];
553

554
  serializeUnpack(buf, size, position,
555
                  tempbuf, cdi_att_nints, DATATYPE_INT, context);
556
  char *attName = (char *) Malloc((size_t)tempbuf[0] + 1);
557
  serializeUnpack(buf, size, position, attName, tempbuf[0], DATATYPE_TXT, context);
558
  attName[tempbuf[0]] = '\0';
559 560
  int attVDt;
  size_t elemSize;
561 562 563
  switch (tempbuf[2])
  {
  case DATATYPE_FLT:
564
    attVDt = DATATYPE_FLT64;
565 566 567
    elemSize = sizeof(double);
    break;
  case DATATYPE_INT:
568
    attVDt = DATATYPE_INT;
569 570 571
    elemSize = sizeof(int);
    break;
  case DATATYPE_TXT:
572
    attVDt = DATATYPE_TXT;
573 574 575
    elemSize = 1;
    break;
  default:
576 577
    xabort("Unknown datatype encountered in attribute %s: %d\n",
           attName, tempbuf[2]);
578
  }
579
  void *attData = (void *) Malloc(elemSize * (size_t)tempbuf[3]);
580
  serializeUnpack(buf, size, position, attData, tempbuf[3], attVDt, context);
581 582
  cdi_def_att(tempbuf[2], tempbuf[1], cdiID, varID, attName,
              (size_t)tempbuf[3], (size_t)tempbuf[3] * elemSize, attData);
583 584
  Free(attName);
  Free(attData);
585 586
}

587 588

void cdiAttsUnpack(int cdiID, int varID, void *buf, int size, int *position, void *context)
589
{
590
  int numAtts;
591
  serializeUnpack(buf, size, position, &numAtts, 1, DATATYPE_INT, context);
592
  for ( int i = 0; i < numAtts; ++i )
593
    cdiAttUnpack(cdiID, varID, buf, size, position, context);
594 595
}

596 597 598 599 600 601 602 603 604
/*
 * Local Variables:
 * c-file-style: "Java"
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * show-trailing-whitespace: t
 * require-trailing-newline: t
 * End:
 */