cdi_att.c 16.5 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
int cdiDeleteAtts(int cdiID, int varID)
191 192 193
{
  int status = CDI_NOERR;

194
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
195
  xassert(attsp != NULL);
196

197
  for ( int attid = 0; attid < (int)attsp->nelems; attid++ )
198
    {
199
      cdi_att_t *attp = &(attsp->value[attid]);
200 201
      if ( attp->name   ) Free(attp->name);
      if ( attp->xvalue ) Free(attp->xvalue);
202 203 204 205
    }

  attsp->nelems = 0;

206
  return status;
207 208 209
}


210
int cdiDelAtt(int cdiID, int varID, const char *name)
211 212 213
{
  int status = CDI_NOERR;

214
  UNUSED(cdiID);
215 216 217
  UNUSED(varID);
  UNUSED(name);

218
  fprintf(stderr, "cdiDelAtt not implemented!\n");
219

220
  return status;
221 222
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
223
static
224
int cdi_def_att(int indtype, int exdtype, int cdiID, int varID, const char *name, size_t len, size_t xsz, const void *xp)
225 226 227
{
  int status = CDI_NOERR;

228
  if ( len != 0 && xp == NULL ) // Null arg
229
    return CDI_EINVAL;
230

231
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
232
  xassert(attsp != NULL);
233

234 235
  cdi_att_t *attp = find_att(attsp, name);
  if ( attp == NULL ) attp = new_att(attsp, name);
236

237
  if ( attp != NULL ) fill_att(attp, indtype, exdtype, len, xsz, xp);
238

239
  return status;
240 241
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
242
static
243
int cdi_inq_att(int indtype, int cdiID, int varID, const char *name, size_t mxsz, void *xp)
244 245 246
{
  int status = CDI_NOERR;

247
  if ( mxsz != 0 && xp == NULL ) // Null arg
248
    return CDI_EINVAL;
249

250
  cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID);
Deike Kleberg's avatar
Deike Kleberg committed
251
  xassert(attsp != NULL);
252

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

275
  return status;
276 277 278
}


279
int cdiCopyAtts(int cdiID1, int varID1, int cdiID2, int varID2)
280 281 282
{
  int status = CDI_NOERR;

283
  cdi_atts_t *attsp1 = cdi_get_attsp(cdiID1, varID1);
Deike Kleberg's avatar
Deike Kleberg committed
284
  xassert(attsp1 != NULL);
285

286
  for ( size_t attid = 0; attid < attsp1->nelems; attid++ )
287
    {
288
      cdi_att_t *attp = &(attsp1->value[attid]);
289
      cdi_def_att(attp->indtype, attp->exdtype, cdiID2, varID2, attp->name, attp->nelems, attp->xsz, attp->xvalue);
290 291
    }

292
  return status;
293 294
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
295
/*
296
@Function  cdiDefAttInt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
297 298
@Title     Define an integer attribute

299
@Prototype int cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, const int *ip)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
300 301

@Parameter
302
    @Item  cdiID    CDI ID, from a previous call to @fref{vlistCreate} or @fref{gridCreate}.
303
    @Item  varID    Variable identifier, or @func{CDI_GLOBAL} for a global attribute.
Deike Kleberg's avatar
Deike Kleberg committed
304
    @Item  name     Attribute name.
305
    @Item  type     External data type (@func{CDI_DATATYPE_INT16} or @func{CDI_DATATYPE_INT32}).
Deike Kleberg's avatar
Deike Kleberg committed
306 307
    @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
308 309

@Description
310
The function @func{cdiDefAttInt} defines an integer attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
311 312 313

@EndFunction
*/
314
int cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, const int *ip)
315
{
316
  return cdi_def_att(CDI_DATATYPE_INT, type, cdiID, varID, name, (size_t)len, (size_t)len * sizeof(int), ip);
317 318
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
319
/*
320
@Function  cdiDefAttFlt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
321 322
@Title     Define a floating point attribute

323
@Prototype int cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, const double *dp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
324 325

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

@Description
334
The function @func{cdiDefAttFlt} defines a floating point attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
335 336 337

@EndFunction
*/
338
int cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, const double *dp)
339
{
340
  return cdi_def_att(CDI_DATATYPE_FLT, type, cdiID, varID, name, (size_t)len, (size_t)len * sizeof(double), dp);
341 342
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
343
/*
344
@Function  cdiDefAttTxt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
345 346
@Title     Define a text attribute

347
@Prototype int cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
348 349

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

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

@EndFunction
*/
361
int cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp)
362
{
363
  return cdi_def_att(CDI_DATATYPE_TXT, CDI_DATATYPE_TXT, cdiID, varID, name, (size_t)len, (size_t)len, tp);
364 365
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
366
/*
367
@Function  cdiInqAttInt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
368 369
@Title     Get the value(s) of an integer attribute

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
378
@Description
379
The function @func{cdiInqAttInt} gets the values(s) of an integer attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
380 381 382

@EndFunction
*/
383
int cdiInqAttInt(int cdiID, int varID, const char *name, int mlen, int *ip)
384
{
385
  return cdi_inq_att(CDI_DATATYPE_INT, cdiID, varID, name, (size_t)mlen * sizeof(int), ip);
386 387
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
388
/*
389
@Function  cdiInqAttFlt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
390 391
@Title     Get the value(s) of a floating point attribute

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

@Description
401
The function @func{cdiInqAttFlt} gets the values(s) of a floating point attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
402 403 404

@EndFunction
*/
405
int cdiInqAttFlt(int cdiID, int varID, const char *name, int mlen, double *dp)
406
{
407
  return cdi_inq_att(CDI_DATATYPE_FLT, cdiID, varID, name, (size_t)mlen * sizeof(double), dp);
408 409
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
410
/*
411
@Function  cdiInqAttTxt
Uwe Schulzweida's avatar
Uwe Schulzweida committed
412 413
@Title     Get the value(s) of a text attribute

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

@Description
423
The function @func{cdiInqAttTxt} gets the values(s) of a text attribute.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
424 425 426

@EndFunction
*/
427
int cdiInqAttTxt(int cdiID, int varID, const char *name, int mlen, char *tp)
428
{
429
  return cdi_inq_att(CDI_DATATYPE_TXT, cdiID, varID, name, (size_t)mlen * sizeof(char), tp);
430
}
431 432

enum {
433
  cdi_att_nints = 4,          /* namesz, exdtype, indtype, nelems */
434 435
};

436 437
static inline
int cdiAttTypeLookup(cdi_att_t *attp)
438
{
439
  int type;
Thomas Jahns's avatar
Thomas Jahns committed
440
  switch (attp->indtype)
441
  {
442 443
  case CDI_DATATYPE_FLT:
    type = CDI_DATATYPE_FLT64;
444
    break;
445 446
  case CDI_DATATYPE_INT:
  case CDI_DATATYPE_TXT:
447
    type = attp->indtype;
448 449
    break;
  default:
450
    xabort("Unknown datatype encountered in attribute %s: %d\n",
Thomas Jahns's avatar
Thomas Jahns committed
451
            attp->name, attp->indtype);
452
  }
453 454 455
  return type;
}

Thomas Jahns's avatar
Thomas Jahns committed
456

457
int cdi_att_compare(cdi_atts_t *attspa, cdi_atts_t *attspb, int attnum)
Thomas Jahns's avatar
Thomas Jahns committed
458
{
459
  xassert(attnum >= 0 && attnum < (int)attspa->nelems && attnum < (int)attspb->nelems);
Thomas Jahns's avatar
Thomas Jahns committed
460
  cdi_att_t *attpa = attspa->value + attnum,
461
            *attpb = attspb->value + attnum;
462 463 464 465 466

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

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

Thomas Jahns's avatar
Thomas Jahns committed
467 468 469 470
  if (attpa->indtype != attpb->indtype
      || attpa->exdtype != attpb->exdtype
      || attpa->nelems != attpb->nelems)
    return 1;
471

Thomas Jahns's avatar
Thomas Jahns committed
472 473 474 475
  return memcmp(attpa->xvalue, attpb->xvalue, attpa->xsz);
}


476 477
static
int cdiAttGetSize(vlist_t *vlistptr, int varID, int attnum, void *context)
478 479 480 481 482 483 484
{
  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]);
485 486
  int txsize = serializeGetSize(cdi_att_nints, CDI_DATATYPE_INT, context)
    + serializeGetSize((int)attp->namesz, CDI_DATATYPE_TXT, context);
487
  txsize += serializeGetSize((int)attp->nelems, cdiAttTypeLookup(attp), context);
488 489 490
  return txsize;
}

491

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

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

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

524 525

void cdiAttsPack(void *vp, int varID, void *buf, int size, int *position, void *context)
526
{
527
  vlist_t *p = (vlist_t*) vp;
528
  cdi_atts_t *attsp = get_attsp(p, varID);
529 530 531
  size_t numAtts = attsp->nelems;
  int numAttsI = (int)numAtts;
  xassert(numAtts <= INT_MAX);
532
  serializePack(&numAttsI, 1, CDI_DATATYPE_INT, buf, size, position, context);
533
  for (size_t i = 0; i < numAtts; ++i)
534
    cdiAttPack(p, varID, (int)i, buf, size, position, context);
535 536
}

537
static
538
void cdiAttUnpack(int cdiID, int varID, void *buf, int size, int *position, void *context)
539
{
540
  int tempbuf[cdi_att_nints];
541

542
  serializeUnpack(buf, size, position,
543
                  tempbuf, cdi_att_nints, CDI_DATATYPE_INT, context);
544
  char *attName = (char *) Malloc((size_t)tempbuf[0] + 1);
545
  serializeUnpack(buf, size, position, attName, tempbuf[0], CDI_DATATYPE_TXT, context);
546
  attName[tempbuf[0]] = '\0';
547 548
  int attVDt;
  size_t elemSize;
549 550
  switch (tempbuf[2])
  {
551 552
  case CDI_DATATYPE_FLT:
    attVDt = CDI_DATATYPE_FLT64;
553 554
    elemSize = sizeof(double);
    break;
555 556
  case CDI_DATATYPE_INT:
    attVDt = CDI_DATATYPE_INT;
557 558
    elemSize = sizeof(int);
    break;
559 560
  case CDI_DATATYPE_TXT:
    attVDt = CDI_DATATYPE_TXT;
561 562 563
    elemSize = 1;
    break;
  default:
564 565
    xabort("Unknown datatype encountered in attribute %s: %d\n",
           attName, tempbuf[2]);
566
  }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
567
  void *attData = Malloc(elemSize * (size_t)tempbuf[3]);
568
  serializeUnpack(buf, size, position, attData, tempbuf[3], attVDt, context);
569 570
  cdi_def_att(tempbuf[2], tempbuf[1], cdiID, varID, attName,
              (size_t)tempbuf[3], (size_t)tempbuf[3] * elemSize, attData);
571 572
  Free(attName);
  Free(attData);
573 574
}

575 576

void cdiAttsUnpack(int cdiID, int varID, void *buf, int size, int *position, void *context)
577
{
578
  int numAtts;
579
  serializeUnpack(buf, size, position, &numAtts, 1, CDI_DATATYPE_INT, context);
580
  for ( int i = 0; i < numAtts; ++i )
581
    cdiAttUnpack(cdiID, varID, buf, size, position, context);
582 583
}

584 585 586 587 588 589 590 591 592
/*
 * Local Variables:
 * c-file-style: "Java"
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * show-trailing-whitespace: t
 * require-trailing-newline: t
 * End:
 */