cdi_att.c 16.9 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
#include "grid.h"
19
#include "zaxis.h"
20 21
#include "resource_unpack.h"

22

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

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

38
  return attsp;
39 40
}

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

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

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

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

59
  return NULL;
60 61
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
62
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
63
cdi_att_t *new_att(cdi_atts_t *attsp, const char *name)
64
{
Deike Kleberg's avatar
Deike Kleberg committed
65 66
  xassert(attsp != NULL);
  xassert(name  != NULL);
67

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

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

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

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

81
  return attp;
82 83
}

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

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

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

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

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

  return attsp;
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
125
/*
126
@Function  cdiInqNatts
Uwe Schulzweida's avatar
Uwe Schulzweida committed
127
@Title     Get number of attributes
Uwe Schulzweida's avatar
Uwe Schulzweida committed
128

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

@Description
136
The function @func{cdiInqNatts} gets the number of attributes assigned to this variable.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
137 138 139

@EndFunction
*/
140
int cdiInqNatts(int cdiID, int varID, int *nattsp)
141 142 143
{
  int status = CDI_NOERR;

144
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
145
  xassert(attsp != NULL);
146

147
  *nattsp = (int)attsp->nelems;
148

149
  return status;
150 151
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
152
/*
153
@Function  cdiInqAtt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
154 155
@Title     Get information about an attribute

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

@Description
168
The function @func{cdiInqAtt} gets information about an attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
169 170 171

@EndFunction
*/
172
int cdiInqAtt(int cdiID, int varID, int attnum, char *name, int *typep, int *lenp)
173 174 175
{
  int status = CDI_NOERR;

Deike Kleberg's avatar
Deike Kleberg committed
176
  xassert(name != NULL);
177

178
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
179
  xassert(attsp != NULL);
180

181
  cdi_att_t *attp = NULL;
182 183
  if ( attnum >= 0 && attnum < (int)attsp->nelems )
    attp = &(attsp->value[attnum]);
184

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

199
  return status;
200 201 202
}


203
int cdiDelAtts(int cdiID, int varID)
204 205 206
{
  int status = CDI_NOERR;

207
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
208
  xassert(attsp != NULL);
209

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

  attsp->nelems = 0;

219
  return status;
220 221 222
}


223
int cdiDelAtt(int cdiID, int varID, const char *name)
224 225 226
{
  int status = CDI_NOERR;

227
  UNUSED(cdiID);
228 229 230
  UNUSED(varID);
  UNUSED(name);

231
  fprintf(stderr, "cdiDelAtt not implemented!\n");
232

233
  return status;
234 235
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
236
static
237
int cdi_def_att(int indtype, int exdtype, int cdiID, int varID, const char *name, size_t len, size_t xsz, const void *xp)
238 239 240 241
{
  int status = CDI_NOERR;

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

244
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
245
  xassert(attsp != NULL);
246

247 248
  cdi_att_t *attp = find_att(attsp, name);
  if ( attp == NULL ) attp = new_att(attsp, name);
249

250
  if ( attp != NULL ) fill_att(attp, indtype, exdtype, len, xsz, xp);
251

252
  return status;
253 254
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
255
static
256
int cdi_inq_att(int indtype, int cdiID, int varID, const char *name, size_t mxsz, void *xp)
257 258 259 260
{
  int status = CDI_NOERR;

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

263
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
264
  xassert(attsp != NULL);
265

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

288
  return status;
289 290 291
}


292
int cdiCopyVarAtts(int cdiID1, int varID_1, int cdiID2, int varID_2)
293 294 295
{
  int status = CDI_NOERR;

296
  cdi_atts_t *attsp1 = cdi_get_attsp(cdiID1, varID_1);
Deike Kleberg's avatar
Deike Kleberg committed
297
  xassert(attsp1 != NULL);
298

299
  for ( int attid = 0; attid < (int)attsp1->nelems; attid++ )
300
    {
301
      cdi_att_t *attp = &(attsp1->value[attid]);
302
      cdi_def_att(attp->indtype, attp->exdtype, cdiID2, varID_2, attp->name, attp->nelems, attp->xsz, attp->xvalue);
303 304
    }

305
  return status;
306 307
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
308
/*
309
@Function  cdiDefAttInt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
310 311
@Title     Define an integer attribute

312
@Prototype int cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, const int *ip)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
313 314

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

@Description
323
The function @func{cdiDefAttInt} defines an integer attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
324 325 326

@EndFunction
*/
327
int cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, const int *ip)
328
{
329
  return cdi_def_att(CDI_DATATYPE_INT, type, cdiID, varID, name, (size_t)len, (size_t)len * sizeof(int), ip);
330 331
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
332
/*
333
@Function  cdiDefAttFlt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
334 335
@Title     Define a floating point attribute

336
@Prototype int cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, const double *dp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
337 338

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

@Description
347
The function @func{cdiDefAttFlt} defines a floating point attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
348 349 350

@EndFunction
*/
351
int cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, const double *dp)
352
{
353
  return cdi_def_att(CDI_DATATYPE_FLT, type, cdiID, varID, name, (size_t)len, (size_t)len * sizeof(double), dp);
354 355
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
356
/*
357
@Function  cdiDefAttTxt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
358 359
@Title     Define a text attribute

360
@Prototype int cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
361 362

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

@Description
370
The function @func{cdiDefAttTxt} defines a text attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
371 372 373

@EndFunction
*/
374
int cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp)
375
{
376
  return cdi_def_att(CDI_DATATYPE_TXT, CDI_DATATYPE_TXT, cdiID, varID, name, (size_t)len, (size_t)len, tp);
377 378
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
379
/*
380
@Function  cdiInqAttInt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
381 382
@Title     Get the value(s) of an integer attribute

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
391
@Description
392
The function @func{cdiInqAttInt} gets the values(s) of an integer attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
393 394 395

@EndFunction
*/
396
int cdiInqAttInt(int cdiID, int varID, const char *name, int mlen, int *ip)
397
{
398
  return cdi_inq_att(CDI_DATATYPE_INT, cdiID, varID, name, (size_t)mlen * sizeof(int), ip);
399 400
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
401
/*
402
@Function  cdiInqAttFlt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
403 404
@Title     Get the value(s) of a floating point attribute

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

@Description
414
The function @func{cdiInqAttFlt} gets the values(s) of a floating point attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
415 416 417

@EndFunction
*/
418
int cdiInqAttFlt(int cdiID, int varID, const char *name, int mlen, double *dp)
419
{
420
  return cdi_inq_att(CDI_DATATYPE_FLT, cdiID, varID, name, (size_t)mlen * sizeof(double), dp);
421 422
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
423
/*
424
@Function  cdiInqAttTxt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
425 426
@Title     Get the value(s) of a text attribute

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

@Description
436
The function @func{cdiInqAttTxt} gets the values(s) of a text attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
437 438 439

@EndFunction
*/
440
int cdiInqAttTxt(int cdiID, int varID, const char *name, int mlen, char *tp)
441
{
442
  return cdi_inq_att(CDI_DATATYPE_TXT, cdiID, varID, name, (size_t)mlen * sizeof(char), tp);
443
}
444 445

enum {
446
  cdi_att_nints = 4,          /* namesz, exdtype, indtype, nelems */
447 448
};

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

Thomas Jahns's avatar
Thomas Jahns committed
469

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


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

509

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

521
static
522 523
void cdiAttPack(vlist_t *vlistptr, int varID, int attnum,
                void *buf, int size, int *position, void *context)
524 525 526
{
  cdi_atts_t *attsp;
  cdi_att_t *attp;
527
  int tempbuf[cdi_att_nints];
528

Deike Kleberg's avatar
Deike Kleberg committed
529 530
  xassert(attsp = get_attsp(vlistptr, varID));
  xassert(attnum >= 0 && attnum < (int)attsp->nelems);
531
  attp = &(attsp->value[attnum]);
532
  tempbuf[0] = (int)attp->namesz;
533 534
  tempbuf[1] = attp->exdtype;
  tempbuf[2] = attp->indtype;
535
  tempbuf[3] = (int)attp->nelems;
536 537
  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);
538
  serializePack(attp->xvalue, (int)attp->nelems, cdiAttTypeLookup(attp),
539
                buf, size, position, context);
540 541
}

542 543

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

555
static
556
void cdiAttUnpack(int cdiID, int varID, void *buf, int size, int *position, void *context)
557
{
558
  int tempbuf[cdi_att_nints];
559

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

593 594

void cdiAttsUnpack(int cdiID, int varID, void *buf, int size, int *position, void *context)
595
{
596
  int numAtts;
597
  serializeUnpack(buf, size, position, &numAtts, 1, CDI_DATATYPE_INT, context);
598
  for ( int i = 0; i < numAtts; ++i )
599
    cdiAttUnpack(cdiID, varID, buf, size, position, context);
600 601
}

602 603 604 605 606 607 608 609 610
/*
 * Local Variables:
 * c-file-style: "Java"
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * show-trailing-whitespace: t
 * require-trailing-newline: t
 * End:
 */