cdi_att.c 17 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
{
22 23
  if ( varID == CDI_GLOBAL ) return &vlistptr->atts;
  else if ( varID >= 0 && varID < vlistptr->nvars ) return &(vlistptr->vars[varID].atts);
24

25
  return NULL;
26 27
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
28
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
29
cdi_att_t *find_att(cdi_atts_t *attsp, const char *name)
30
{
Deike Kleberg's avatar
Deike Kleberg committed
31
  xassert(attsp != NULL);
32 33 34

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

35
  size_t slen = strlen(name);
36
  if ( slen > CDI_MAX_NAME ) slen = CDI_MAX_NAME;
37

Thomas Jahns's avatar
Thomas Jahns committed
38
  cdi_att_t *atts = attsp->value;
39
  for ( size_t attid = 0; attid < attsp->nelems; attid++ )
40
    {
Thomas Jahns's avatar
Thomas Jahns committed
41
      cdi_att_t *attp = atts + attid;
42
      if ( attp->namesz == slen && memcmp(attp->name, name, slen) == 0 )
43
        return attp; // Normal return
44 45
    }

46
  return NULL;
47 48
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
49
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
50
cdi_att_t *new_att(cdi_atts_t *attsp, const char *name)
51
{
Deike Kleberg's avatar
Deike Kleberg committed
52 53
  xassert(attsp != NULL);
  xassert(name  != NULL);
54

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

57
  cdi_att_t *attp = &(attsp->value[attsp->nelems]);
58 59
  attsp->nelems++;

60
  size_t slen = strlen(name);
61
  if ( slen > CDI_MAX_NAME ) slen = CDI_MAX_NAME;
62

63
  attp->name = (char *) Malloc(slen+1);
64 65
  memcpy(attp->name, name, slen+1);
  attp->namesz = slen;
66
  attp->xvalue = NULL;
67

68
  return attp;
69 70
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
71
static
72
void fill_att(cdi_att_t *attp, int indtype, int exdtype, size_t nelems, size_t xsz, const void *xvalue)
73
{
Deike Kleberg's avatar
Deike Kleberg committed
74
  xassert(attp != NULL);
75

76
  attp->xsz = xsz;
77 78 79
  attp->indtype = indtype;
  attp->exdtype = exdtype;
  attp->nelems  = nelems;
80

81 82
  if ( xsz > 0 )
    {
83
      attp->xvalue = Realloc(attp->xvalue, xsz);
84 85
      memcpy(attp->xvalue, xvalue, xsz);
    }
86 87
}

88 89 90
static
cdi_atts_t *cdi_get_attsp(int objID, int varID)
{
91
  cdi_atts_t *attsp = NULL;
92

93 94
  if ( varID == CDI_GLOBAL && reshGetTxCode(objID) == GRID )
    {
95
      grid_t *gridptr = grid_to_pointer(objID);
96 97
      attsp = &gridptr->atts;
    }
98 99
  else if ( varID == CDI_GLOBAL && reshGetTxCode(objID) == ZAXIS )
    {
100
      zaxis_t *zaxisptr = zaxis_to_pointer(objID);
101 102
      attsp = &zaxisptr->atts;
    }
103 104 105 106 107
  else
    {
      vlist_t *vlistptr = vlist_to_pointer(objID);
      attsp = get_attsp(vlistptr, varID);
    }
108 109 110 111

  return attsp;
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
112
/*
113
@Function  cdiInqNatts
Uwe Schulzweida's avatar
Uwe Schulzweida committed
114
@Title     Get number of attributes
Uwe Schulzweida's avatar
Uwe Schulzweida committed
115

116
@Prototype int cdiInqNatts(int cdiID, int varID, int *nattsp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
117
@Parameter
118
    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}.
119
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
120
    @Item  nattsp   Pointer to location for returned number of attributes.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
121 122

@Description
123
The function @func{cdiInqNatts} gets the number of attributes assigned to this variable.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
124 125 126

@EndFunction
*/
127
int cdiInqNatts(int cdiID, int varID, int *nattsp)
128 129 130
{
  int status = CDI_NOERR;

131
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
132
  xassert(attsp != NULL);
133

134
  *nattsp = (int)attsp->nelems;
135

136
  return status;
137 138
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
139
/*
140
@Function  cdiInqAtt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
141 142
@Title     Get information about an attribute

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

@Description
155
The function @func{cdiInqAtt} gets information about an attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
156 157 158

@EndFunction
*/
159
int cdiInqAtt(int cdiID, int varID, int attnum, char *name, int *typep, int *lenp)
160 161 162
{
  int status = CDI_NOERR;

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

165
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
166
  xassert(attsp != NULL);
167

168
  cdi_att_t *attp = NULL;
169 170
  if ( attnum >= 0 && attnum < (int)attsp->nelems )
    attp = &(attsp->value[attnum]);
171

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

186
  return status;
187 188 189
}


190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
int cdiInqAttLen(int cdiID, int varID, const char *name)
{
  int length = -1;

  xassert(name != NULL);

  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
  xassert(attsp != NULL);

  for ( int attid = 0; attid < (int)attsp->nelems; attid++ )
    {
      cdi_att_t *attp = &(attsp->value[attid]);
      if (strcmp(attp->name, name) == 0)
        {
          length = (int)attp->nelems;
          printf("name >%s< >%s< length %d\n", attp->name, name, length);
        }
    }

  return length;
}


213
int cdiDeleteAtts(int cdiID, int varID)
214 215 216
{
  int status = CDI_NOERR;

217
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
218
  xassert(attsp != NULL);
219

220
  for ( int attid = 0; attid < (int)attsp->nelems; attid++ )
221
    {
222
      cdi_att_t *attp = &(attsp->value[attid]);
223 224
      if ( attp->name   ) Free(attp->name);
      if ( attp->xvalue ) Free(attp->xvalue);
225 226 227 228
    }

  attsp->nelems = 0;

229
  return status;
230 231 232
}


233
int cdiDelAtt(int cdiID, int varID, const char *name)
234 235 236
{
  int status = CDI_NOERR;

237
  UNUSED(cdiID);
238 239 240
  UNUSED(varID);
  UNUSED(name);

241
  fprintf(stderr, "cdiDelAtt not implemented!\n");
242

243
  return status;
244 245
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
246
static
247
int cdi_def_att(int indtype, int exdtype, int cdiID, int varID, const char *name, size_t len, size_t xsz, const void *xp)
248 249 250
{
  int status = CDI_NOERR;

251
  if ( len != 0 && xp == NULL ) // Null arg
252
    return CDI_EINVAL;
253

254
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
255
  xassert(attsp != NULL);
256

257 258
  cdi_att_t *attp = find_att(attsp, name);
  if ( attp == NULL ) attp = new_att(attsp, name);
259

260
  if ( attp != NULL ) fill_att(attp, indtype, exdtype, len, xsz, xp);
261

262
  return status;
263 264
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
265
static
266
int cdi_inq_att(int indtype, int cdiID, int varID, const char *name, size_t mxsz, void *xp)
267 268 269
{
  int status = CDI_NOERR;

270
  if ( mxsz != 0 && xp == NULL ) // Null arg
271
    return CDI_EINVAL;
272

273
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
274
  xassert(attsp != NULL);
275

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

298
  return status;
299 300 301
}


302
int cdiCopyAtts(int cdiID1, int varID1, int cdiID2, int varID2)
303 304 305
{
  int status = CDI_NOERR;

306
  cdi_atts_t *attsp1 = cdi_get_attsp(cdiID1, varID1);
Deike Kleberg's avatar
Deike Kleberg committed
307
  xassert(attsp1 != NULL);
308

309
  for ( size_t attid = 0; attid < attsp1->nelems; attid++ )
310
    {
311
      cdi_att_t *attp = &(attsp1->value[attid]);
312
      cdi_def_att(attp->indtype, attp->exdtype, cdiID2, varID2, attp->name, attp->nelems, attp->xsz, attp->xvalue);
313 314
    }

315
  return status;
316 317
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
318
/*
319
@Function  cdiDefAttInt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
320 321
@Title     Define an integer attribute

322
@Prototype int cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, const int *ip)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
323 324

@Parameter
325
    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate} or @fref{gridCreate}.
326
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
327
    @Item  name     Attribute name.
328
    @Item  type     External data type (@func{CDI_DATATYPE_INT16} or @func{CDI_DATATYPE_INT32}).
Deike Kleberg's avatar
Deike Kleberg committed
329 330
    @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
331 332

@Description
333
The function @func{cdiDefAttInt} defines an integer attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
334 335 336

@EndFunction
*/
337
int cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, const int *ip)
338
{
339
  return cdi_def_att(CDI_DATATYPE_INT, type, cdiID, varID, name, (size_t)len, (size_t)len * sizeof(int), ip);
340 341
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
342
/*
343
@Function  cdiDefAttFlt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
344 345
@Title     Define a floating point attribute

346
@Prototype int cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, const double *dp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
347 348

@Parameter
349
    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate} or @fref{gridCreate}.
350
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
351
    @Item  name     Attribute name.
352
    @Item  type     External data type (@func{CDI_DATATYPE_FLT32} or @func{CDI_DATATYPE_FLT64}).
Deike Kleberg's avatar
Deike Kleberg committed
353 354
    @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
355 356

@Description
357
The function @func{cdiDefAttFlt} defines a floating point attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
358 359 360

@EndFunction
*/
361
int cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, const double *dp)
362
{
363
  return cdi_def_att(CDI_DATATYPE_FLT, type, cdiID, varID, name, (size_t)len, (size_t)len * sizeof(double), dp);
364 365
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
366
/*
367
@Function  cdiDefAttTxt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
368 369
@Title     Define a text attribute

370
@Prototype int cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
371 372

@Parameter
373
    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate} or @fref{gridCreate}.
374
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
375 376 377
    @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
378 379

@Description
380
The function @func{cdiDefAttTxt} defines a text attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
381 382 383

@EndFunction
*/
384
int cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp)
385
{
386
  return cdi_def_att(CDI_DATATYPE_TXT, CDI_DATATYPE_TXT, cdiID, varID, name, (size_t)len, (size_t)len, tp);
387 388
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
389
/*
390
@Function  cdiInqAttInt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
391 392
@Title     Get the value(s) of an integer attribute

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
401
@Description
402
The function @func{cdiInqAttInt} gets the values(s) of an integer attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
403 404 405

@EndFunction
*/
406
int cdiInqAttInt(int cdiID, int varID, const char *name, int mlen, int *ip)
407
{
408
  return cdi_inq_att(CDI_DATATYPE_INT, cdiID, varID, name, (size_t)mlen * sizeof(int), ip);
409 410
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
411
/*
412
@Function  cdiInqAttFlt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
413 414
@Title     Get the value(s) of a floating point attribute

415
@Prototype int cdiInqAttFlt(int cdiID, int varID, const char *name, int mlen, double *dp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
416
@Parameter
417
    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}.
418
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
419 420 421
    @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
422 423

@Description
424
The function @func{cdiInqAttFlt} gets the values(s) of a floating point attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
425 426 427

@EndFunction
*/
428
int cdiInqAttFlt(int cdiID, int varID, const char *name, int mlen, double *dp)
429
{
430
  return cdi_inq_att(CDI_DATATYPE_FLT, cdiID, varID, name, (size_t)mlen * sizeof(double), dp);
431 432
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
433
/*
434
@Function  cdiInqAttTxt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
435 436
@Title     Get the value(s) of a text attribute

437
@Prototype int cdiInqAttTxt(int cdiID, int varID, const char *name, int mlen, char *tp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
438
@Parameter
439
    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}.
440
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
441 442 443
    @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
444 445

@Description
446
The function @func{cdiInqAttTxt} gets the values(s) of a text attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
447 448 449

@EndFunction
*/
450
int cdiInqAttTxt(int cdiID, int varID, const char *name, int mlen, char *tp)
451
{
452
  return cdi_inq_att(CDI_DATATYPE_TXT, cdiID, varID, name, (size_t)mlen * sizeof(char), tp);
453
}
454 455

enum {
456
  cdi_att_nints = 4,          /* namesz, exdtype, indtype, nelems */
457 458
};

459 460
static inline
int cdiAttTypeLookup(cdi_att_t *attp)
461
{
462
  int type;
Thomas Jahns's avatar
Thomas Jahns committed
463
  switch (attp->indtype)
464
  {
465 466
  case CDI_DATATYPE_FLT:
    type = CDI_DATATYPE_FLT64;
467
    break;
468 469
  case CDI_DATATYPE_INT:
  case CDI_DATATYPE_TXT:
470
    type = attp->indtype;
471 472
    break;
  default:
473
    xabort("Unknown datatype encountered in attribute %s: %d\n",
Thomas Jahns's avatar
Thomas Jahns committed
474
            attp->name, attp->indtype);
475
  }
476 477 478
  return type;
}

Thomas Jahns's avatar
Thomas Jahns committed
479

480
int cdi_att_compare(cdi_atts_t *attspa, cdi_atts_t *attspb, int attnum)
Thomas Jahns's avatar
Thomas Jahns committed
481
{
482
  xassert(attnum >= 0 && attnum < (int)attspa->nelems && attnum < (int)attspb->nelems);
Thomas Jahns's avatar
Thomas Jahns committed
483
  cdi_att_t *attpa = attspa->value + attnum,
484
            *attpb = attspb->value + attnum;
485 486 487 488 489

  if (attpa->namesz != attpb->namesz) return 1;

  if (memcmp(attpa->name, attpb->name, attpa->namesz)) return 1;

Thomas Jahns's avatar
Thomas Jahns committed
490 491 492 493
  if (attpa->indtype != attpb->indtype
      || attpa->exdtype != attpb->exdtype
      || attpa->nelems != attpb->nelems)
    return 1;
494

Thomas Jahns's avatar
Thomas Jahns committed
495 496 497 498
  return memcmp(attpa->xvalue, attpb->xvalue, attpa->xsz);
}


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

514

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

526
static
527 528
void cdiAttPack(vlist_t *vlistptr, int varID, int attnum,
                void *buf, int size, int *position, void *context)
529 530 531
{
  cdi_atts_t *attsp;
  cdi_att_t *attp;
532
  int tempbuf[cdi_att_nints];
533

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

547 548

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

560
static
561
void cdiAttUnpack(int cdiID, int varID, void *buf, int size, int *position, void *context)
562
{
563
  int tempbuf[cdi_att_nints];
564

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

598 599

void cdiAttsUnpack(int cdiID, int varID, void *buf, int size, int *position, void *context)
600
{
601
  int numAtts;
602
  serializeUnpack(buf, size, position, &numAtts, 1, CDI_DATATYPE_INT, context);
603
  for ( int i = 0; i < numAtts; ++i )
604
    cdiAttUnpack(cdiID, varID, buf, size, position, context);
605 606
}

607 608 609 610 611 612 613 614 615
/*
 * Local Variables:
 * c-file-style: "Java"
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * show-trailing-whitespace: t
 * require-trailing-newline: t
 * End:
 */