cdi_att.c 16.8 KB
Newer Older
1 2
#include <assert.h>
#include <limits.h>
3 4 5 6 7 8
#include <stdio.h>
#include <string.h>

#include "dmemory.h"

#include "cdi.h"
9
#include "cdi_int.h"
10
#include "vlist.h"
11
#include "cdi_att.h"
12
#include "error.h"
13
#include "serialize.h"
14
#include "grid.h"
15
#include "zaxis.h"
16 17
#include "resource_unpack.h"

18

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

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

34
  return attsp;
35 36
}

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

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

44
  size_t slen = strlen(name);
45
  if ( slen > CDI_MAX_NAME ) slen = CDI_MAX_NAME;
46

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

55
  return NULL;
56 57
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
58
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
59
cdi_att_t *new_att(cdi_atts_t *attsp, const char *name)
60
{
Deike Kleberg's avatar
Deike Kleberg committed
61 62
  xassert(attsp != NULL);
  xassert(name  != NULL);
63

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

66
  cdi_att_t *attp = &(attsp->value[attsp->nelems]);
67 68
  attsp->nelems++;

69
  size_t slen = strlen(name);
70
  if ( slen > CDI_MAX_NAME ) slen = CDI_MAX_NAME;
71

72
  attp->name = (char *) Malloc(slen+1);
73 74
  memcpy(attp->name, name, slen+1);
  attp->namesz = slen;
75
  attp->xvalue = NULL;
76

77
  return attp;
78 79
}

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

85
  attp->xsz = xsz;
86 87 88
  attp->indtype = indtype;
  attp->exdtype = exdtype;
  attp->nelems  = nelems;
89

90 91
  if ( xsz > 0 )
    {
92
      attp->xvalue = Realloc(attp->xvalue, xsz);
93 94
      memcpy(attp->xvalue, xvalue, xsz);
    }
95 96
}

97 98 99
static
cdi_atts_t *cdi_get_attsp(int objID, int varID)
{
100
  cdi_atts_t *attsp = NULL;
101

102 103
  if ( varID == CDI_GLOBAL && reshGetTxCode(objID) == GRID )
    {
104
      grid_t *gridptr = grid_to_pointer(objID);
105 106
      attsp = &gridptr->atts;
    }
107 108
  else if ( varID == CDI_GLOBAL && reshGetTxCode(objID) == ZAXIS )
    {
109
      zaxis_t *zaxisptr = zaxis_to_pointer(objID);
110 111
      attsp = &zaxisptr->atts;
    }
112 113 114 115 116
  else
    {
      vlist_t *vlistptr = vlist_to_pointer(objID);
      attsp = get_attsp(vlistptr, varID);
    }
117 118 119 120

  return attsp;
}

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

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

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

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

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

143
  *nattsp = (int)attsp->nelems;
144

145
  return status;
146 147
}

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

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

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

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

Deike Kleberg's avatar
Deike Kleberg committed
172
  xassert(name != NULL);
173

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

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

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

195
  return status;
196 197 198
}


199
int cdiDeleteAtts(int cdiID, int varID)
200 201 202
{
  int status = CDI_NOERR;

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

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

  attsp->nelems = 0;

215
  return status;
216 217 218
}


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

223
  UNUSED(cdiID);
224 225 226
  UNUSED(varID);
  UNUSED(name);

227
  fprintf(stderr, "cdiDelAtt not implemented!\n");
228

229
  return status;
230 231
}

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

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

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

243 244
  cdi_att_t *attp = find_att(attsp, name);
  if ( attp == NULL ) attp = new_att(attsp, name);
245

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

248
  return status;
249 250
}

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

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

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

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

284
  return status;
285 286 287
}


288
int cdiCopyAtts(int cdiID1, int varID1, int cdiID2, int varID2)
289 290 291
{
  int status = CDI_NOERR;

292
  cdi_atts_t *attsp1 = cdi_get_attsp(cdiID1, varID1);
Deike Kleberg's avatar
Deike Kleberg committed
293
  xassert(attsp1 != NULL);
294

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

301
  return status;
302 303
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

enum {
442
  cdi_att_nints = 4,          /* namesz, exdtype, indtype, nelems */
443 444
};

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

Thomas Jahns's avatar
Thomas Jahns committed
465

466
int cdi_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB, int attnum)
Thomas Jahns's avatar
Thomas Jahns committed
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
{
  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);
}


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

505

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

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

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

538 539

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

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

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

589 590

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

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