~ubuntu-branches/ubuntu/quantal/xdmf/quantal

« back to all changes in this revision

Viewing changes to Utilities/vtknetcdf/attr.m4

  • Committer: Bazaar Package Importer
  • Author(s): Alastair McKinstry
  • Date: 2011-07-09 10:33:32 UTC
  • Revision ID: james.westby@ubuntu.com-20110709103332-2w36cerw7215fzoe
Tags: upstream-2.1.dfsg.1
ImportĀ upstreamĀ versionĀ 2.1.dfsg.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
dnl This is m4 source.
 
2
dnl Process using m4 to produce 'C' language file.
 
3
dnl
 
4
dnl If you see this line, you can ignore the next one.
 
5
/* Do not edit this file. It is produced from the corresponding .m4 source */
 
6
dnl
 
7
/*
 
8
 *  Copyright 1996, University Corporation for Atmospheric Research
 
9
 *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
 
10
 */
 
11
/* $Id: attr.m4,v 1.1 2010-01-06 16:34:05 kwleiter Exp $ */
 
12
 
 
13
#include "nc.h"
 
14
#include <stdlib.h>
 
15
#include <string.h>
 
16
#include <assert.h>
 
17
#include "ncx.h"
 
18
#include "fbits.h"
 
19
#include "rnd.h"
 
20
 
 
21
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
 
22
#  pragma warning ( disable : 4130 ) /* logical operation on address of string constant */
 
23
#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
 
24
 
 
25
/*
 
26
 * Free attr
 
27
 * Formerly
 
28
NC_free_attr()
 
29
 */
 
30
void
 
31
free_NC_attr(NC_attr *attrp)
 
32
{
 
33
 
 
34
  if(attrp == NULL)
 
35
    return;
 
36
  free_NC_string(attrp->name);
 
37
  free(attrp);
 
38
}
 
39
 
 
40
 
 
41
/*
 
42
 * How much space will 'nelems' of 'type' take in
 
43
 *  external representation (as the values of an attribute)?
 
44
 */
 
45
static size_t
 
46
ncx_len_NC_attrV(nc_type type, size_t nelems)
 
47
{
 
48
  switch(type) {
 
49
  case NC_BYTE:
 
50
  case NC_CHAR:
 
51
    return ncx_len_char(nelems);
 
52
  case NC_SHORT:
 
53
    return ncx_len_short(nelems);
 
54
  case NC_INT:
 
55
    return ncx_len_int(nelems);
 
56
  case NC_FLOAT:
 
57
    return ncx_len_float(nelems);
 
58
  case NC_DOUBLE:
 
59
    return ncx_len_double(nelems);
 
60
  case NC_NAT:
 
61
    break; /* Some compilers complain if enums are missing from a switch */
 
62
  }
 
63
  /* default */
 
64
  assert("ncx_len_NC_attr bad type" == 0);
 
65
  return 0;
 
66
}
 
67
 
 
68
 
 
69
NC_attr *
 
70
new_x_NC_attr(
 
71
  NC_string *strp,
 
72
  nc_type type,
 
73
  size_t nelems)
 
74
{
 
75
  NC_attr *attrp;
 
76
  const size_t xsz = ncx_len_NC_attrV(type, nelems);
 
77
  size_t sz = M_RNDUP(sizeof(NC_attr));
 
78
 
 
79
  assert(!(xsz == 0 && nelems != 0));
 
80
 
 
81
  sz += xsz;
 
82
 
 
83
  attrp = (NC_attr *) malloc(sz);
 
84
  if(attrp == NULL )
 
85
    return NULL;
 
86
 
 
87
  attrp->xsz = xsz;
 
88
 
 
89
  attrp->name = strp;
 
90
  attrp->type = type;
 
91
  attrp->nelems = nelems;
 
92
  if(xsz != 0)
 
93
    attrp->xvalue = (char *)attrp + M_RNDUP(sizeof(NC_attr));
 
94
  else
 
95
    attrp->xvalue = NULL;
 
96
 
 
97
  return(attrp);
 
98
}
 
99
 
 
100
 
 
101
/*
 
102
 * Formerly
 
103
NC_new_attr(name,type,count,value)
 
104
 */
 
105
static NC_attr *
 
106
new_NC_attr(
 
107
  const char *name,
 
108
  nc_type type,
 
109
  size_t nelems)
 
110
{
 
111
  NC_string *strp;
 
112
  NC_attr *attrp;
 
113
 
 
114
  assert(name != NULL && *name != 0);
 
115
 
 
116
  strp = new_NC_string(strlen(name), name);
 
117
  if(strp == NULL)
 
118
    return NULL;
 
119
  
 
120
  attrp = new_x_NC_attr(strp, type, nelems);
 
121
  if(attrp == NULL)
 
122
  {
 
123
    free_NC_string(strp);
 
124
    return NULL;
 
125
  }
 
126
 
 
127
  return(attrp);
 
128
}
 
129
 
 
130
 
 
131
static NC_attr *
 
132
dup_NC_attr(const NC_attr *rattrp)
 
133
{
 
134
  NC_attr *attrp = new_NC_attr(rattrp->name->cp,
 
135
     rattrp->type, rattrp->nelems);
 
136
  if(attrp == NULL)
 
137
    return NULL;
 
138
  (void) memcpy(attrp->xvalue, rattrp->xvalue, rattrp->xsz);
 
139
  return attrp;
 
140
}
 
141
 
 
142
/* attrarray */
 
143
 
 
144
/*
 
145
 * Free the stuff "in" (referred to by) an NC_attrarray.
 
146
 * Leaves the array itself allocated.
 
147
 */
 
148
void
 
149
free_NC_attrarrayV0(NC_attrarray *ncap)
 
150
{
 
151
  assert(ncap != NULL);
 
152
 
 
153
  if(ncap->nelems == 0)
 
154
    return;
 
155
 
 
156
  assert(ncap->value != NULL);
 
157
 
 
158
  {
 
159
    NC_attr **app = ncap->value;
 
160
    NC_attr *const *const end = &app[ncap->nelems];
 
161
    for( /*NADA*/; app < end; app++)
 
162
    {
 
163
      free_NC_attr(*app);
 
164
      *app = NULL;
 
165
    }
 
166
  }
 
167
  ncap->nelems = 0;
 
168
}
 
169
 
 
170
 
 
171
/*
 
172
 * Free NC_attrarray values.
 
173
 * formerly
 
174
NC_free_array()
 
175
 */
 
176
void
 
177
free_NC_attrarrayV(NC_attrarray *ncap)
 
178
{
 
179
  assert(ncap != NULL);
 
180
  
 
181
  if(ncap->nalloc == 0)
 
182
    return;
 
183
 
 
184
  assert(ncap->value != NULL);
 
185
 
 
186
  free_NC_attrarrayV0(ncap);
 
187
 
 
188
  free(ncap->value);
 
189
  ncap->value = NULL;
 
190
  ncap->nalloc = 0;
 
191
}
 
192
 
 
193
 
 
194
int
 
195
dup_NC_attrarrayV(NC_attrarray *ncap, const NC_attrarray *ref)
 
196
{
 
197
  int status = NC_NOERR;
 
198
 
 
199
  assert(ref != NULL);
 
200
  assert(ncap != NULL);
 
201
 
 
202
  if(ref->nelems != 0)
 
203
  {
 
204
    const size_t sz = ref->nelems * sizeof(NC_attr *);
 
205
    ncap->value = (NC_attr **) malloc(sz);
 
206
    if(ncap->value == NULL)
 
207
      return NC_ENOMEM;
 
208
 
 
209
    (void) memset(ncap->value, 0, sz);
 
210
    ncap->nalloc = ref->nelems;
 
211
  }
 
212
 
 
213
  ncap->nelems = 0;
 
214
  {
 
215
    NC_attr **app = ncap->value;
 
216
    const NC_attr **drpp = (const NC_attr **)ref->value;
 
217
    NC_attr *const *const end = &app[ref->nelems];
 
218
    for( /*NADA*/; app < end; drpp++, app++, ncap->nelems++)
 
219
    {
 
220
      *app = dup_NC_attr(*drpp);
 
221
      if(*app == NULL)
 
222
      {
 
223
        status = NC_ENOMEM;
 
224
        break;
 
225
      }
 
226
    }
 
227
  }
 
228
 
 
229
  if(status != NC_NOERR)
 
230
  {
 
231
    free_NC_attrarrayV(ncap);
 
232
    return status;
 
233
  }
 
234
 
 
235
  assert(ncap->nelems == ref->nelems);
 
236
 
 
237
  return NC_NOERR;
 
238
}
 
239
 
 
240
 
 
241
/*
 
242
 * Add a new handle on the end of an array of handles
 
243
 * Formerly
 
244
NC_incr_array(array, tail)
 
245
 */
 
246
static int
 
247
incr_NC_attrarray(NC_attrarray *ncap, NC_attr *newelemp)
 
248
{
 
249
  NC_attr **vp;
 
250
 
 
251
  assert(ncap != NULL);
 
252
 
 
253
  if(ncap->nalloc == 0)
 
254
  {
 
255
    assert(ncap->nelems == 0);
 
256
    vp = (NC_attr **) malloc(NC_ARRAY_GROWBY * sizeof(NC_attr *));
 
257
    if(vp == NULL)
 
258
      return NC_ENOMEM;
 
259
 
 
260
    ncap->value = vp;
 
261
    ncap->nalloc = NC_ARRAY_GROWBY;
 
262
  }
 
263
  else if(ncap->nelems +1 > ncap->nalloc)
 
264
  {
 
265
    vp = (NC_attr **) realloc(ncap->value,
 
266
      (ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_attr *));
 
267
    if(vp == NULL)
 
268
      return NC_ENOMEM;
 
269
  
 
270
    ncap->value = vp;
 
271
    ncap->nalloc += NC_ARRAY_GROWBY;
 
272
  }
 
273
 
 
274
  if(newelemp != NULL)
 
275
  {
 
276
    ncap->value[ncap->nelems] = newelemp;
 
277
    ncap->nelems++;
 
278
  }
 
279
  return NC_NOERR;
 
280
}
 
281
 
 
282
 
 
283
NC_attr *
 
284
elem_NC_attrarray(const NC_attrarray *ncap, size_t elem)
 
285
{
 
286
  assert(ncap != NULL);
 
287
    /* cast needed for braindead systems with signed size_t */
 
288
  if(ncap->nelems == 0 || (unsigned long) elem >= ncap->nelems)
 
289
    return NULL;
 
290
 
 
291
  assert(ncap->value != NULL);
 
292
 
 
293
  return ncap->value[elem];
 
294
}
 
295
 
 
296
/* End attarray per se */
 
297
 
 
298
/*
 
299
 * Given ncp and varid, return ptr to array of attributes
 
300
 *  else NULL on error
 
301
 */
 
302
static NC_attrarray *
 
303
NC_attrarray0( NC *ncp, int varid)
 
304
{
 
305
  NC_attrarray *ap;
 
306
 
 
307
  if(varid == NC_GLOBAL) /* Global attribute, attach to cdf */
 
308
  {
 
309
    ap = &ncp->attrs;
 
310
  }
 
311
  else if(varid >= 0 && (size_t) varid < ncp->vars.nelems)
 
312
  {
 
313
    NC_var **vpp;
 
314
    vpp = (NC_var **)ncp->vars.value;
 
315
    vpp += varid;
 
316
    ap = &(*vpp)->attrs;
 
317
  } else {
 
318
    ap = NULL;
 
319
  }
 
320
  return(ap);
 
321
}
 
322
 
 
323
 
 
324
/*
 
325
 * Step thru NC_ATTRIBUTE array, seeking match on name.
 
326
 *  return match or NULL if Not Found.
 
327
 */
 
328
NC_attr **
 
329
NC_findattr(const NC_attrarray *ncap, const char *name)
 
330
{
 
331
  NC_attr **attrpp;
 
332
  size_t attrid;
 
333
  size_t slen;
 
334
 
 
335
  assert(ncap != NULL);
 
336
 
 
337
  if(ncap->nelems == 0)
 
338
    return NULL;
 
339
 
 
340
  attrpp = (NC_attr **) ncap->value;
 
341
 
 
342
  slen = strlen(name);
 
343
 
 
344
  for(attrid = 0; attrid < ncap->nelems; attrid++, attrpp++)
 
345
  {
 
346
    if(strlen((*attrpp)->name->cp) == slen &&
 
347
      strncmp((*attrpp)->name->cp, name, slen) == 0)
 
348
    {
 
349
      return(attrpp); /* Normal return */
 
350
    }
 
351
  }
 
352
  return(NULL);
 
353
}
 
354
 
 
355
 
 
356
/*
 
357
 * Look up by ncid, varid and name, return NULL if not found
 
358
 */
 
359
static int 
 
360
NC_lookupattr(int ncid,
 
361
  int varid,
 
362
  const char *name, /* attribute name */
 
363
  NC_attr **attrpp) /* modified on return */
 
364
{
 
365
  int status;
 
366
  NC *ncp;
 
367
  NC_attrarray *ncap;
 
368
  NC_attr **tmp;
 
369
 
 
370
  status = NC_check_id(ncid, &ncp);
 
371
  if(status != NC_NOERR)
 
372
    return status;
 
373
 
 
374
  ncap = NC_attrarray0(ncp, varid);
 
375
  if(ncap == NULL)
 
376
    return NC_ENOTVAR;
 
377
 
 
378
  tmp = NC_findattr(ncap, name);
 
379
  if(tmp == NULL)
 
380
    return NC_ENOTATT;
 
381
 
 
382
  if(attrpp != NULL)
 
383
    *attrpp = *tmp;
 
384
 
 
385
  return ENOERR;
 
386
}
 
387
 
 
388
/* Public */
 
389
 
 
390
int
 
391
nc_inq_attname(int ncid, int varid, int attnum, char *name)
 
392
{
 
393
  int status;
 
394
  NC *ncp;
 
395
  NC_attrarray *ncap;
 
396
  NC_attr *attrp;
 
397
 
 
398
  status = NC_check_id(ncid, &ncp);
 
399
  if(status != NC_NOERR)
 
400
    return status;
 
401
 
 
402
  ncap = NC_attrarray0(ncp, varid);
 
403
  if(ncap == NULL)
 
404
    return NC_ENOTVAR;
 
405
 
 
406
  attrp = elem_NC_attrarray(ncap, (size_t)attnum);
 
407
  if(attrp == NULL)
 
408
    return NC_ENOTATT;
 
409
 
 
410
  (void) strncpy(name, attrp->name->cp, attrp->name->nchars);
 
411
  name[attrp->name->nchars] = 0;
 
412
 
 
413
  return NC_NOERR;
 
414
}
 
415
 
 
416
 
 
417
int 
 
418
nc_inq_attid(int ncid, int varid, const char *name, int *attnump)
 
419
{
 
420
  int status;
 
421
  NC *ncp;
 
422
  NC_attrarray *ncap;
 
423
  NC_attr **attrpp;
 
424
 
 
425
  status = NC_check_id(ncid, &ncp);
 
426
  if(status != NC_NOERR)
 
427
    return status;
 
428
 
 
429
  ncap = NC_attrarray0(ncp, varid);
 
430
  if(ncap == NULL)
 
431
    return NC_ENOTVAR;
 
432
  
 
433
 
 
434
  attrpp = NC_findattr(ncap, name);
 
435
  if(attrpp == NULL)
 
436
    return NC_ENOTATT;
 
437
 
 
438
  if(attnump != NULL)
 
439
    *attnump = (int)(attrpp - ncap->value);
 
440
 
 
441
  return NC_NOERR;
 
442
}
 
443
 
 
444
int 
 
445
nc_inq_atttype(int ncid, int varid, const char *name, nc_type *datatypep)
 
446
{
 
447
  int status;
 
448
  NC_attr *attrp;
 
449
 
 
450
  status = NC_lookupattr(ncid, varid, name, &attrp);
 
451
  if(status != NC_NOERR)
 
452
    return status;
 
453
 
 
454
  if(datatypep != NULL)
 
455
    *datatypep = attrp->type;
 
456
 
 
457
  return NC_NOERR;
 
458
}
 
459
 
 
460
int 
 
461
nc_inq_attlen(int ncid, int varid, const char *name, size_t *lenp)
 
462
{
 
463
  int status;
 
464
  NC_attr *attrp;
 
465
 
 
466
  status = NC_lookupattr(ncid, varid, name, &attrp);
 
467
  if(status != NC_NOERR)
 
468
    return status;
 
469
 
 
470
  if(lenp != NULL)
 
471
    *lenp = attrp->nelems;
 
472
 
 
473
  return NC_NOERR;
 
474
}
 
475
 
 
476
int
 
477
nc_inq_att(int ncid,
 
478
  int varid,
 
479
  const char *name, /* input, attribute name */
 
480
  nc_type *datatypep,
 
481
  size_t *lenp)
 
482
{
 
483
  int status;
 
484
  NC_attr *attrp;
 
485
 
 
486
  status = NC_lookupattr(ncid, varid, name, &attrp);
 
487
  if(status != NC_NOERR)
 
488
    return status;
 
489
 
 
490
  if(datatypep != NULL)
 
491
    *datatypep = attrp->type;
 
492
  if(lenp != NULL)
 
493
    *lenp = attrp->nelems;
 
494
 
 
495
  return NC_NOERR;
 
496
}
 
497
 
 
498
 
 
499
int
 
500
nc_rename_att( int ncid, int varid, const char *name, const char *newname)
 
501
{
 
502
  int status;
 
503
  NC *ncp;
 
504
  NC_attrarray *ncap;
 
505
  NC_attr **tmp;
 
506
  NC_attr *attrp;
 
507
  NC_string *newStr, *old;
 
508
 
 
509
      /* sortof inline clone of NC_lookupattr() */
 
510
  status = NC_check_id(ncid, &ncp);
 
511
  if(status != NC_NOERR)
 
512
    return status;
 
513
 
 
514
  if(NC_readonly(ncp))
 
515
    return NC_EPERM;
 
516
 
 
517
  ncap = NC_attrarray0(ncp, varid);
 
518
  if(ncap == NULL)
 
519
    return NC_ENOTVAR;
 
520
 
 
521
  status = NC_check_name(newname);
 
522
  if(status != NC_NOERR)
 
523
    return status;
 
524
 
 
525
  tmp = NC_findattr(ncap, name);
 
526
  if(tmp == NULL)
 
527
    return NC_ENOTATT;
 
528
  attrp = *tmp;
 
529
      /* end inline clone NC_lookupattr() */
 
530
 
 
531
  if(NC_findattr(ncap, newname) != NULL)
 
532
  {
 
533
    /* name in use */
 
534
    return NC_ENAMEINUSE;
 
535
  }
 
536
 
 
537
  old = attrp->name;
 
538
  if(NC_indef(ncp))
 
539
  {
 
540
    newStr = new_NC_string(strlen(newname), newname);
 
541
    if( newStr == NULL)
 
542
      return NC_ENOMEM;
 
543
    attrp->name = newStr;
 
544
    free_NC_string(old);
 
545
    return NC_NOERR;
 
546
  }
 
547
  /* else */
 
548
  status = set_NC_string(old, newname);
 
549
  if( status != NC_NOERR)
 
550
    return status;
 
551
 
 
552
  set_NC_hdirty(ncp);
 
553
 
 
554
  if(NC_doHsync(ncp))
 
555
  {
 
556
    status = NC_sync(ncp);
 
557
    if(status != NC_NOERR)
 
558
      return status;
 
559
  }
 
560
 
 
561
  return NC_NOERR;
 
562
}
 
563
 
 
564
 
 
565
int
 
566
nc_copy_att(int ncid_in, int varid_in, const char *name, int ncid_out, int ovarid)
 
567
{
 
568
  int status;
 
569
  NC_attr *iattrp;
 
570
  NC *ncp;
 
571
  NC_attrarray *ncap;
 
572
  NC_attr **attrpp;
 
573
  NC_attr *old = NULL;
 
574
  NC_attr *attrp;
 
575
 
 
576
  status = NC_lookupattr(ncid_in, varid_in, name, &iattrp);
 
577
  if(status != NC_NOERR)
 
578
    return status;
 
579
 
 
580
  status = NC_check_id(ncid_out, &ncp);
 
581
  if(status != NC_NOERR)
 
582
    return status;
 
583
 
 
584
  if(NC_readonly(ncp))
 
585
    return NC_EPERM;
 
586
 
 
587
  ncap = NC_attrarray0(ncp, ovarid);
 
588
  if(ncap == NULL)
 
589
    return NC_ENOTVAR;
 
590
 
 
591
  attrpp = NC_findattr(ncap, name);
 
592
  if(attrpp != NULL) /* name in use */
 
593
  {
 
594
    if(!NC_indef(ncp) )
 
595
    {
 
596
      attrp = *attrpp; /* convenience */
 
597
  
 
598
      if(iattrp->xsz > attrp->xsz)
 
599
        return NC_ENOTINDEFINE;
 
600
      /* else, we can reuse existing without redef */
 
601
      
 
602
      attrp->xsz = iattrp->xsz;
 
603
      attrp->type = iattrp->type;
 
604
      attrp->nelems = iattrp->nelems;
 
605
 
 
606
      (void) memcpy(attrp->xvalue, iattrp->xvalue,
 
607
        iattrp->xsz);
 
608
      
 
609
      set_NC_hdirty(ncp);
 
610
 
 
611
      if(NC_doHsync(ncp))
 
612
      {
 
613
        status = NC_sync(ncp);
 
614
        if(status != NC_NOERR)
 
615
          return status;
 
616
      }
 
617
 
 
618
      return NC_NOERR;
 
619
    }
 
620
    /* else, redefine using existing array slot */
 
621
    old = *attrpp;
 
622
  } 
 
623
  else
 
624
  {
 
625
    if(!NC_indef(ncp))
 
626
      return NC_ENOTINDEFINE;
 
627
 
 
628
    if(ncap->nelems >= NC_MAX_ATTRS)
 
629
      return NC_EMAXATTS;
 
630
  }
 
631
 
 
632
  attrp = new_NC_attr(name, iattrp->type, iattrp->nelems);
 
633
  if(attrp == NULL)
 
634
    return NC_ENOMEM;
 
635
 
 
636
  (void) memcpy(attrp->xvalue, iattrp->xvalue,
 
637
    iattrp->xsz);
 
638
 
 
639
  if(attrpp != NULL)
 
640
  {
 
641
    assert(old != NULL);
 
642
    *attrpp = attrp;
 
643
    free_NC_attr(old);
 
644
  }
 
645
  else
 
646
  {
 
647
    status = incr_NC_attrarray(ncap, attrp);
 
648
    if(status != NC_NOERR)
 
649
    {
 
650
      free_NC_attr(attrp);
 
651
      return status;
 
652
    }
 
653
  }
 
654
 
 
655
  return NC_NOERR;
 
656
}
 
657
 
 
658
 
 
659
int
 
660
nc_del_att(int ncid, int varid, const char *name)
 
661
{
 
662
  int status;
 
663
  NC *ncp;
 
664
  NC_attrarray *ncap;
 
665
  NC_attr **attrpp;
 
666
  NC_attr *old = NULL;
 
667
  int attrid;
 
668
  size_t slen;
 
669
 
 
670
  status = NC_check_id(ncid, &ncp);
 
671
  if(status != NC_NOERR)
 
672
    return status;
 
673
 
 
674
  if(!NC_indef(ncp))
 
675
    return NC_ENOTINDEFINE;
 
676
 
 
677
  ncap = NC_attrarray0(ncp, varid);
 
678
  if(ncap == NULL)
 
679
    return NC_ENOTVAR;
 
680
 
 
681
      /* sortof inline NC_findattr() */
 
682
  slen = strlen(name);
 
683
 
 
684
  attrpp = (NC_attr **) ncap->value;
 
685
  for(attrid = 0; (size_t) attrid < ncap->nelems; attrid++, attrpp++)
 
686
  {
 
687
    if( slen == (*attrpp)->name->nchars &&
 
688
      strncmp(name, (*attrpp)->name->cp, slen) == 0)
 
689
    {
 
690
      old = *attrpp;
 
691
      break;
 
692
    }
 
693
  }
 
694
  if( (size_t) attrid == ncap->nelems )
 
695
    return NC_ENOTATT;
 
696
      /* end inline NC_findattr() */
 
697
 
 
698
  /* shuffle down */
 
699
  for(attrid++; (size_t) attrid < ncap->nelems; attrid++)
 
700
  {
 
701
    *attrpp = *(attrpp + 1);
 
702
    attrpp++;
 
703
  }
 
704
  *attrpp = NULL;
 
705
  /* decrement count */
 
706
  ncap->nelems--;
 
707
 
 
708
  free_NC_attr(old);
 
709
 
 
710
  return NC_NOERR;
 
711
}
 
712
 
 
713
dnl
 
714
dnl XNCX_PAD_PUTN(Type)
 
715
dnl
 
716
define(`XNCX_PAD_PUTN',dnl
 
717
`dnl
 
718
static int
 
719
ncx_pad_putn_I$1(void **xpp, size_t nelems, const $1 *tp, nc_type type)
 
720
{
 
721
  switch(type) {
 
722
  case NC_CHAR:
 
723
    return NC_ECHAR;
 
724
  case NC_BYTE:
 
725
    return ncx_pad_putn_schar_$1(xpp, nelems, tp);
 
726
  case NC_SHORT:
 
727
    return ncx_pad_putn_short_$1(xpp, nelems, tp);
 
728
  case NC_INT:
 
729
    return ncx_putn_int_$1(xpp, nelems, tp);
 
730
  case NC_FLOAT:
 
731
    return ncx_putn_float_$1(xpp, nelems, tp);
 
732
  case NC_DOUBLE:
 
733
    return ncx_putn_double_$1(xpp, nelems, tp);
 
734
  case NC_NAT:
 
735
    break; /* Some compilers complain if enums are missing from a switch */
 
736
  }
 
737
  assert("ncx_pad_putn_I$1 invalid type" == 0);
 
738
  return NC_EBADTYPE;
 
739
}
 
740
')dnl
 
741
dnl
 
742
dnl XNCX_PAD_GETN(Type)
 
743
dnl
 
744
define(`XNCX_PAD_GETN',dnl
 
745
`dnl
 
746
static int
 
747
ncx_pad_getn_I$1(const void **xpp, size_t nelems, $1 *tp, nc_type type)
 
748
{
 
749
  switch(type) {
 
750
  case NC_CHAR:
 
751
    return NC_ECHAR;
 
752
  case NC_BYTE:
 
753
    return ncx_pad_getn_schar_$1(xpp, nelems, tp);
 
754
  case NC_SHORT:
 
755
    return ncx_pad_getn_short_$1(xpp, nelems, tp);
 
756
  case NC_INT:
 
757
    return ncx_getn_int_$1(xpp, nelems, tp);
 
758
  case NC_FLOAT:
 
759
    return ncx_getn_float_$1(xpp, nelems, tp);
 
760
  case NC_DOUBLE:
 
761
    return ncx_getn_double_$1(xpp, nelems, tp);
 
762
  case NC_NAT:
 
763
    break; /* Some compilers complain if enums are missing from a switch */
 
764
  }
 
765
  assert("ncx_pad_getn_I$1 invalid type" == 0);
 
766
  return NC_EBADTYPE;
 
767
}
 
768
')dnl
 
769
dnl Implement
 
770
 
 
771
XNCX_PAD_PUTN(uchar)
 
772
XNCX_PAD_GETN(uchar)
 
773
 
 
774
XNCX_PAD_PUTN(schar)
 
775
XNCX_PAD_GETN(schar)
 
776
 
 
777
XNCX_PAD_PUTN(short)
 
778
XNCX_PAD_GETN(short)
 
779
 
 
780
XNCX_PAD_PUTN(int)
 
781
XNCX_PAD_GETN(int)
 
782
 
 
783
XNCX_PAD_PUTN(long)
 
784
XNCX_PAD_GETN(long)
 
785
 
 
786
XNCX_PAD_PUTN(float)
 
787
XNCX_PAD_GETN(float)
 
788
 
 
789
XNCX_PAD_PUTN(double)
 
790
XNCX_PAD_GETN(double)
 
791
 
 
792
 
 
793
int
 
794
nc_put_att_text(int ncid, int varid, const char *name,
 
795
  size_t nelems, const char *value)
 
796
{
 
797
  int status;
 
798
  NC *ncp;
 
799
  NC_attrarray *ncap;
 
800
  NC_attr **attrpp;
 
801
  NC_attr *old = NULL;
 
802
  NC_attr *attrp;
 
803
 
 
804
  status = NC_check_id(ncid, &ncp);
 
805
  if(status != NC_NOERR)
 
806
    return status;
 
807
 
 
808
  if(NC_readonly(ncp))
 
809
    return NC_EPERM;
 
810
 
 
811
  ncap = NC_attrarray0(ncp, varid);
 
812
  if(ncap == NULL)
 
813
    return NC_ENOTVAR;
 
814
 
 
815
  status = NC_check_name(name);
 
816
  if(status != NC_NOERR)
 
817
    return status;
 
818
 
 
819
    /* cast needed for braindead systems with signed size_t */
 
820
  if((unsigned long) nelems > X_INT_MAX) /* backward compat */
 
821
    return NC_EINVAL; /* Invalid nelems */
 
822
 
 
823
  if(nelems != 0 && value == NULL)
 
824
    return NC_EINVAL; /* Null arg */
 
825
 
 
826
  attrpp = NC_findattr(ncap, name);
 
827
  if(attrpp != NULL) /* name in use */
 
828
  {
 
829
    if(!NC_indef(ncp) )
 
830
    {
 
831
      const size_t xsz = ncx_len_NC_attrV(NC_CHAR, nelems);
 
832
      attrp = *attrpp; /* convenience */
 
833
  
 
834
      if(xsz > attrp->xsz)
 
835
        return NC_ENOTINDEFINE;
 
836
      /* else, we can reuse existing without redef */
 
837
      
 
838
      attrp->xsz = xsz;
 
839
      attrp->type = NC_CHAR;
 
840
      attrp->nelems = nelems;
 
841
 
 
842
      if(nelems != 0)
 
843
      {
 
844
        void *xp = attrp->xvalue;
 
845
        status = ncx_pad_putn_text(&xp, nelems, value);
 
846
        if(status != NC_NOERR)
 
847
          return status;
 
848
      }
 
849
      
 
850
      set_NC_hdirty(ncp);
 
851
 
 
852
      if(NC_doHsync(ncp))
 
853
      {
 
854
        status = NC_sync(ncp);
 
855
        if(status != NC_NOERR)
 
856
          return status;
 
857
      }
 
858
 
 
859
      return NC_NOERR;
 
860
    }
 
861
    /* else, redefine using existing array slot */
 
862
    old = *attrpp;
 
863
  } 
 
864
  else
 
865
  {
 
866
    if(!NC_indef(ncp))
 
867
      return NC_ENOTINDEFINE;
 
868
 
 
869
    if(ncap->nelems >= NC_MAX_ATTRS)
 
870
      return NC_EMAXATTS;
 
871
  }
 
872
 
 
873
  attrp = new_NC_attr(name, NC_CHAR, nelems);
 
874
  if(attrp == NULL)
 
875
    return NC_ENOMEM;
 
876
 
 
877
  if(nelems != 0)
 
878
  {
 
879
    void *xp = attrp->xvalue;
 
880
    status = ncx_pad_putn_text(&xp, nelems, value);
 
881
    if(status != NC_NOERR)
 
882
      return status;
 
883
  }
 
884
 
 
885
  if(attrpp != NULL)
 
886
  {
 
887
    assert(old != NULL);
 
888
    *attrpp = attrp;
 
889
    free_NC_attr(old);
 
890
  }
 
891
  else
 
892
  {
 
893
    status = incr_NC_attrarray(ncap, attrp);
 
894
    if(status != NC_NOERR)
 
895
    {
 
896
      free_NC_attr(attrp);
 
897
      return status;
 
898
    }
 
899
  }
 
900
 
 
901
  return NC_NOERR;
 
902
}
 
903
 
 
904
 
 
905
int
 
906
nc_get_att_text(int ncid, int varid, const char *name, char *str)
 
907
{
 
908
  int status;
 
909
  NC_attr *attrp;
 
910
 
 
911
  status = NC_lookupattr(ncid, varid, name, &attrp);
 
912
  if(status != NC_NOERR)
 
913
    return status;
 
914
 
 
915
  if(attrp->nelems == 0)
 
916
    return NC_NOERR;
 
917
 
 
918
  if(attrp->type != NC_CHAR)
 
919
    return NC_ECHAR;
 
920
 
 
921
  /* else */
 
922
  {
 
923
    const void *xp = attrp->xvalue;
 
924
    return ncx_pad_getn_text(&xp, attrp->nelems, str);
 
925
  }
 
926
}
 
927
 
 
928
 
 
929
dnl
 
930
dnl NC_PUT_ATT(Abbrv, Type)
 
931
dnl
 
932
define(`NC_PUT_ATT',dnl
 
933
`dnl
 
934
int
 
935
nc_put_att_$1(int ncid, int varid, const char *name,
 
936
  nc_type type, size_t nelems, const $2 *value)
 
937
{
 
938
  int status;
 
939
  NC *ncp;
 
940
  NC_attrarray *ncap;
 
941
  NC_attr **attrpp;
 
942
  NC_attr *old = NULL;
 
943
  NC_attr *attrp;
 
944
 
 
945
  status = NC_check_id(ncid, &ncp);
 
946
  if(status != NC_NOERR)
 
947
    return status;
 
948
 
 
949
  if(NC_readonly(ncp))
 
950
    return NC_EPERM;
 
951
 
 
952
  ncap = NC_attrarray0(ncp, varid);
 
953
  if(ncap == NULL)
 
954
    return NC_ENOTVAR;
 
955
 
 
956
  status = nc_cktype(type);
 
957
  if(status != NC_NOERR)
 
958
    return status;
 
959
 
 
960
  if(type == NC_CHAR)
 
961
    return NC_ECHAR;
 
962
 
 
963
    /* cast needed for braindead systems with signed size_t */
 
964
  if((unsigned long) nelems > X_INT_MAX) /* backward compat */
 
965
    return NC_EINVAL; /* Invalid nelems */
 
966
 
 
967
  if(nelems != 0 && value == NULL)
 
968
    return NC_EINVAL; /* Null arg */
 
969
 
 
970
  attrpp = NC_findattr(ncap, name);
 
971
  if(attrpp != NULL) /* name in use */
 
972
  {
 
973
    if(!NC_indef(ncp) )
 
974
    {
 
975
      const size_t xsz = ncx_len_NC_attrV(type, nelems);
 
976
      attrp = *attrpp; /* convenience */
 
977
  
 
978
      if(xsz > attrp->xsz)
 
979
        return NC_ENOTINDEFINE;
 
980
      /* else, we can reuse existing without redef */
 
981
      
 
982
      attrp->xsz = xsz;
 
983
      attrp->type = type;
 
984
      attrp->nelems = nelems;
 
985
 
 
986
      if(nelems != 0)
 
987
      {
 
988
        void *xp = attrp->xvalue;
 
989
        status = ncx_pad_putn_I$1(&xp, nelems,
 
990
          value, type);
 
991
      }
 
992
      
 
993
      set_NC_hdirty(ncp);
 
994
 
 
995
      if(NC_doHsync(ncp))
 
996
      {
 
997
        const int lstatus = NC_sync(ncp);
 
998
        /*
 
999
         * N.B.: potentially overrides NC_ERANGE
 
1000
         * set by ncx_pad_putn_I$1
 
1001
         */
 
1002
        if(lstatus != ENOERR)
 
1003
          return lstatus;
 
1004
      }
 
1005
 
 
1006
      return status;
 
1007
    }
 
1008
    /* else, redefine using existing array slot */
 
1009
    old = *attrpp;
 
1010
  } 
 
1011
  else
 
1012
  {
 
1013
    if(!NC_indef(ncp))
 
1014
      return NC_ENOTINDEFINE;
 
1015
 
 
1016
    if(ncap->nelems >= NC_MAX_ATTRS)
 
1017
      return NC_EMAXATTS;
 
1018
  }
 
1019
 
 
1020
  status = NC_check_name(name);
 
1021
  if(status != NC_NOERR)
 
1022
    return status;
 
1023
 
 
1024
  attrp = new_NC_attr(name, type, nelems);
 
1025
  if(attrp == NULL)
 
1026
    return NC_ENOMEM;
 
1027
 
 
1028
  if(nelems != 0)
 
1029
  {
 
1030
    void *xp = attrp->xvalue;
 
1031
    status = ncx_pad_putn_I$1(&xp, nelems,
 
1032
      value, type);
 
1033
  }
 
1034
 
 
1035
  if(attrpp != NULL)
 
1036
  {
 
1037
    assert(old != NULL);
 
1038
    *attrpp = attrp;
 
1039
    free_NC_attr(old);
 
1040
  }
 
1041
  else
 
1042
  {
 
1043
    const int lstatus = incr_NC_attrarray(ncap, attrp);
 
1044
    /*
 
1045
     * N.B.: potentially overrides NC_ERANGE
 
1046
     * set by ncx_pad_putn_I$1
 
1047
     */
 
1048
    if(lstatus != NC_NOERR)
 
1049
    {
 
1050
      free_NC_attr(attrp);
 
1051
      return lstatus;
 
1052
    }
 
1053
  }
 
1054
 
 
1055
  return status;
 
1056
}
 
1057
')dnl
 
1058
dnl
 
1059
dnl NC_GET_ATT(Abbrv, Type)
 
1060
dnl
 
1061
define(`NC_GET_ATT',dnl
 
1062
`dnl
 
1063
int
 
1064
nc_get_att_$1(int ncid, int varid, const char *name, $2 *tp)
 
1065
{
 
1066
  int status;
 
1067
  NC_attr *attrp;
 
1068
 
 
1069
  status = NC_lookupattr(ncid, varid, name, &attrp);
 
1070
  if(status != NC_NOERR)
 
1071
    return status;
 
1072
 
 
1073
  if(attrp->nelems == 0)
 
1074
    return NC_NOERR;
 
1075
 
 
1076
  if(attrp->type == NC_CHAR)
 
1077
    return NC_ECHAR;
 
1078
 
 
1079
  {
 
1080
  const void *xp = attrp->xvalue;
 
1081
  return ncx_pad_getn_I$1(&xp, attrp->nelems, tp, attrp->type);
 
1082
  }
 
1083
}
 
1084
')dnl
 
1085
 
 
1086
 
 
1087
NC_PUT_ATT(schar, signed char)
 
1088
NC_GET_ATT(schar, signed char)
 
1089
 
 
1090
NC_PUT_ATT(uchar, unsigned char)
 
1091
NC_GET_ATT(uchar, unsigned char)
 
1092
 
 
1093
NC_PUT_ATT(short, short)
 
1094
NC_GET_ATT(short, short)
 
1095
 
 
1096
NC_PUT_ATT(int, int)
 
1097
NC_GET_ATT(int, int)
 
1098
 
 
1099
NC_PUT_ATT(long, long)
 
1100
NC_GET_ATT(long, long)
 
1101
 
 
1102
NC_PUT_ATT(float, float)
 
1103
NC_GET_ATT(float, float)
 
1104
 
 
1105
NC_PUT_ATT(double, double)
 
1106
NC_GET_ATT(double, double)