1/* Do not edit this file. It is produced from the corresponding .m4 source */
2/*
3 * Copyright 1996, University Corporation for Atmospheric Research
4 *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
5 */
6
7#include "nc3internal.h"
8#include "ncdispatch.h"
9#include "nc3dispatch.h"
10#include <stdlib.h>
11#include <string.h>
12#include <assert.h>
13#include "ncx.h"
14#include "fbits.h"
15#include "rnd.h"
16#include "utf8proc.h"
17
18
19/*
20 * Free attr
21 * Formerly
22NC_free_attr()
23 */
24void
25free_NC_attr(NC_attr *attrp)
26{
27
28 if(attrp == NULL)
29 return;
30 free_NC_string(attrp->name);
31 free(attrp);
32}
33
34
35/*
36 * How much space will 'nelems' of 'type' take in
37 *  external representation (as the values of an attribute)?
38 */
39static size_t
40ncx_len_NC_attrV(nc_type type, size_t nelems)
41{
42 switch(type) {
43 case NC_BYTE:
44 case NC_CHAR:
45 return ncx_len_char(nelems);
46 case NC_SHORT:
47 return ncx_len_short(nelems);
48 case NC_INT:
49 return ncx_len_int(nelems);
50 case NC_FLOAT:
51 return ncx_len_float(nelems);
52 case NC_DOUBLE:
53 return ncx_len_double(nelems);
54 case NC_UBYTE:
55 return ncx_len_ubyte(nelems);
56 case NC_USHORT:
57 return ncx_len_ushort(nelems);
58 case NC_UINT:
59 return ncx_len_uint(nelems);
60 case NC_INT64:
61 return ncx_len_int64(nelems);
62 case NC_UINT64:
63 return ncx_len_uint64(nelems);
64 default:
65         assert("ncx_len_NC_attr bad type" == 0);
66 }
67 return 0;
68}
69
70
71NC_attr *
72new_x_NC_attr(
73 NC_string *strp,
74 nc_type type,
75 size_t nelems)
76{
77 NC_attr *attrp;
78 const size_t xsz = ncx_len_NC_attrV(typenelems);
79 size_t sz = M_RNDUP(sizeof(NC_attr));
80
81 assert(!(xsz == 0 && nelems != 0));
82
83 sz += xsz;
84
85 attrp = (NC_attr *) malloc(sz);
86 if(attrp == NULL )
87 return NULL;
88
89 attrp->xsz = xsz;
90
91 attrp->name = strp;
92 attrp->type = type;
93 attrp->nelems = nelems;
94 if(xsz != 0)
95 attrp->xvalue = (char *)attrp + M_RNDUP(sizeof(NC_attr));
96 else
97 attrp->xvalue = NULL;
98
99 return(attrp);
100}
101
102
103/*
104 * Formerly
105NC_new_attr(name,type,count,value)
106 */
107static NC_attr *
108new_NC_attr(
109 const char *uname,
110 nc_type type,
111 size_t nelems)
112{
113 NC_string *strp;
114 NC_attr *attrp;
115
116 char *name = (char *)utf8proc_NFC((const unsigned char *)uname);
117 if(name == NULL)
118     return NULL;
119 assert(name != NULL && *name != 0);
120
121 strp = new_NC_string(strlen(name), name);
122 free(name);
123 if(strp == NULL)
124 return NULL;
125
126 attrp = new_x_NC_attr(strptypenelems);
127 if(attrp == NULL)
128 {
129 free_NC_string(strp);
130 return NULL;
131 }
132
133 return(attrp);
134}
135
136
137static NC_attr *
138dup_NC_attr(const NC_attr *rattrp)
139{
140 NC_attr *attrp = new_NC_attr(rattrp->name->cp,
141  rattrp->typerattrp->nelems);
142 if(attrp == NULL)
143 return NULL;
144    if(attrp->xvalue != NULL && rattrp->xvalue != NULL)
145     (void) memcpy(attrp->xvaluerattrp->xvaluerattrp->xsz);
146 return attrp;
147}
148
149/* attrarray */
150
151/*
152 * Free the stuff "in" (referred to by) an NC_attrarray.
153 * Leaves the array itself allocated.
154 */
155void
156free_NC_attrarrayV0(NC_attrarray *ncap)
157{
158 assert(ncap != NULL);
159
160 if(ncap->nelems == 0)
161 return;
162
163 assert(ncap->value != NULL);
164
165 {
166 NC_attr **app = ncap->value;
167 NC_attr *const *const end = &app[ncap->nelems];
168 for( /*NADA*/; app < endapp++)
169 {
170 free_NC_attr(*app);
171 *app = NULL;
172 }
173 }
174 ncap->nelems = 0;
175}
176
177
178/*
179 * Free NC_attrarray values.
180 * formerly
181NC_free_array()
182 */
183void
184free_NC_attrarrayV(NC_attrarray *ncap)
185{
186 assert(ncap != NULL);
187
188 if(ncap->nalloc == 0)
189 return;
190
191 assert(ncap->value != NULL);
192
193 free_NC_attrarrayV0(ncap);
194
195 free(ncap->value);
196 ncap->value = NULL;
197 ncap->nalloc = 0;
198}
199
200
201int
202dup_NC_attrarrayV(NC_attrarray *ncap, const NC_attrarray *ref)
203{
204 int status = NC_NOERR;
205
206 assert(ref != NULL);
207 assert(ncap != NULL);
208
209 if(ref->nelems != 0)
210 {
211 const size_t sz = ref->nelems * sizeof(NC_attr *);
212 ncap->value = (NC_attr **) malloc(sz);
213 if(ncap->value == NULL)
214 return NC_ENOMEM;
215
216 (void) memset(ncap->value, 0, sz);
217 ncap->nalloc = ref->nelems;
218 }
219
220 ncap->nelems = 0;
221 {
222 NC_attr **app = ncap->value;
223 const NC_attr **drpp = (const NC_attr **)ref->value;
224 NC_attr *const *const end = &app[ref->nelems];
225 for( /*NADA*/; app < enddrpp++, app++, ncap->nelems++)
226 {
227 *app = dup_NC_attr(*drpp);
228 if(*app == NULL)
229 {
230 status = NC_ENOMEM;
231 break;
232 }
233 }
234 }
235
236 if(status != NC_NOERR)
237 {
238 free_NC_attrarrayV(ncap);
239 return status;
240 }
241
242 assert(ncap->nelems == ref->nelems);
243
244 return NC_NOERR;
245}
246
247
248/*
249 * Add a new handle on the end of an array of handles
250 * Formerly
251NC_incr_array(array, tail)
252 */
253static int
254incr_NC_attrarray(NC_attrarray *ncapNC_attr *newelemp)
255{
256 NC_attr **vp;
257
258 assert(ncap != NULL);
259
260 if(ncap->nalloc == 0)
261 {
262 assert(ncap->nelems == 0);
263 vp = (NC_attr **) malloc(NC_ARRAY_GROWBY * sizeof(NC_attr *));
264 if(vp == NULL)
265 return NC_ENOMEM;
266
267 ncap->value = vp;
268 ncap->nalloc = NC_ARRAY_GROWBY;
269 }
270 else if(ncap->nelems +1 > ncap->nalloc)
271 {
272 vp = (NC_attr **) realloc(ncap->value,
273 (ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_attr *));
274 if(vp == NULL)
275 return NC_ENOMEM;
276
277 ncap->value = vp;
278 ncap->nalloc += NC_ARRAY_GROWBY;
279 }
280
281 if(newelemp != NULL)
282 {
283 ncap->value[ncap->nelems] = newelemp;
284 ncap->nelems++;
285 }
286 return NC_NOERR;
287}
288
289
290NC_attr *
291elem_NC_attrarray(const NC_attrarray *ncap, size_t elem)
292{
293 assert(ncap != NULL);
294 /* cast needed for braindead systems with signed size_t */
295 if(ncap->nelems == 0 || (unsigned long) elem >= ncap->nelems)
296 return NULL;
297
298 assert(ncap->value != NULL);
299
300 return ncap->value[elem];
301}
302
303/* End attarray per se */
304
305/*
306 * Given ncp and varid, return ptr to array of attributes
307 *  else NULL on error
308 */
309static NC_attrarray *
310NC_attrarray0(NC3_INFOncp, int varid)
311{
312 NC_attrarray *ap;
313
314 if(varid == NC_GLOBAL) /* Global attribute, attach to cdf */
315 {
316 ap = &ncp->attrs;
317 }
318 else if(varid >= 0 && (size_t) varid < ncp->vars.nelems)
319 {
320 NC_var **vpp;
321 vpp = (NC_var **)ncp->vars.value;
322 vpp += varid;
323 ap = &(*vpp)->attrs;
324 } else {
325 ap = NULL;
326 }
327 return(ap);
328}
329
330
331/*
332 * Step thru NC_ATTRIBUTE array, seeking match on name.
333 *  return match or NULL if Not Found or out of memory.
334 */
335NC_attr **
336NC_findattr(const NC_attrarray *ncap, const char *uname)
337{
338 NC_attr **attrpp;
339 size_t attrid;
340 size_t slen;
341 char *name;
342
343 assert(ncap != NULL);
344
345 if(ncap->nelems == 0)
346 return NULL;
347
348 attrpp = (NC_attr **) ncap->value;
349
350 /* normalized version of uname */
351 name = (char *)utf8proc_NFC((const unsigned char *)uname);
352 if(name == NULL)
353     return NULL; /* TODO: need better way to indicate no memory */
354 slen = strlen(name);
355
356 for(attrid = 0; attrid < ncap->nelemsattrid++, attrpp++)
357 {
358 if(strlen((*attrpp)->name->cp) == slen &&
359 strncmp((*attrpp)->name->cpnameslen) == 0)
360 {
361         free(name);
362 return(attrpp); /* Normal return */
363 }
364 }
365 free(name);
366 return(NULL);
367}
368
369
370/*
371 * Look up by ncid, varid and name, return NULL if not found
372 */
373static int
374NC_lookupattr(int ncid,
375 int varid,
376 const char *name, /* attribute name */
377 NC_attr **attrpp) /* modified on return */
378{
379 int status;
380 NCnc;
381 NC3_INFO *ncp;
382 NC_attrarray *ncap;
383 NC_attr **tmp;
384
385 status = NC_check_id(ncid, &nc);
386 if(status != NC_NOERR)
387 return status;
388 ncp = NC3_DATA(nc);
389
390 ncap = NC_attrarray0(ncpvarid);
391 if(ncap == NULL)
392 return NC_ENOTVAR;
393
394 tmp = NC_findattr(ncapname);
395 if(tmp == NULL)
396 return NC_ENOTATT;
397
398 if(attrpp != NULL)
399 *attrpp = *tmp;
400
401 return NC_NOERR;
402}
403
404/* Public */
405
406int
407NC3_inq_attname(int ncid, int varid, int attnum, char *name)
408{
409 int status;
410 NCnc;
411 NC3_INFO *ncp;
412 NC_attrarray *ncap;
413 NC_attr *attrp;
414
415 status = NC_check_id(ncid, &nc);
416 if(status != NC_NOERR)
417 return status;
418 ncp = NC3_DATA(nc);
419
420 ncap = NC_attrarray0(ncpvarid);
421 if(ncap == NULL)
422 return NC_ENOTVAR;
423
424 attrp = elem_NC_attrarray(ncap, (size_t)attnum);
425 if(attrp == NULL)
426 return NC_ENOTATT;
427
428 (void) strncpy(nameattrp->name->cpattrp->name->nchars);
429 name[attrp->name->nchars] = 0;
430
431 return NC_NOERR;
432}
433
434
435int
436NC3_inq_attid(int ncid, int varid, const char *name, int *attnump)
437{
438 int status;
439 NC *nc;
440 NC3_INFOncp;
441 NC_attrarray *ncap;
442 NC_attr **attrpp;
443
444 status = NC_check_id(ncid, &nc);
445 if(status != NC_NOERR)
446 return status;
447 ncp = NC3_DATA(nc);
448
449 ncap = NC_attrarray0(ncpvarid);
450 if(ncap == NULL)
451 return NC_ENOTVAR;
452
453
454 attrpp = NC_findattr(ncapname);
455 if(attrpp == NULL)
456 return NC_ENOTATT;
457
458 if(attnump != NULL)
459 *attnump = (int)(attrpp - ncap->value);
460
461 return NC_NOERR;
462}
463
464int
465NC3_inq_att(int ncid,
466 int varid,
467 const char *name, /* input, attribute name */
468 nc_type *datatypep,
469 size_t *lenp)
470{
471 int status;
472 NC_attr *attrp;
473
474 status = NC_lookupattr(ncidvaridname, &attrp);
475 if(status != NC_NOERR)
476 return status;
477
478 if(datatypep != NULL)
479 *datatypep = attrp->type;
480 if(lenp != NULL)
481 *lenp = attrp->nelems;
482
483 return NC_NOERR;
484}
485
486
487int
488NC3_rename_att( int ncid, int varid, const char *name, const char *unewname)
489{
490 int status;
491 NC *nc;
492 NC3_INFOncp;
493 NC_attrarray *ncap;
494 NC_attr **tmp;
495 NC_attr *attrp;
496 NC_string *newStr, *old;
497 char *newname;  /* normalized version */
498
499 /* sortof inline clone of NC_lookupattr() */
500 status = NC_check_id(ncid, &nc);
501 if(status != NC_NOERR)
502 return status;
503 ncp = NC3_DATA(nc);
504
505 if(NC_readonly(ncp))
506 return NC_EPERM;
507
508 ncap = NC_attrarray0(ncpvarid);
509 if(ncap == NULL)
510 return NC_ENOTVAR;
511
512 status = NC_check_name(unewname);
513 if(status != NC_NOERR)
514 return status;
515
516 tmp = NC_findattr(ncapname);
517 if(tmp == NULL)
518 return NC_ENOTATT;
519 attrp = *tmp;
520 /* end inline clone NC_lookupattr() */
521
522 if(NC_findattr(ncapunewname) != NULL)
523 {
524 /* name in use */
525 return NC_ENAMEINUSE;
526 }
527
528 old = attrp->name;
529 newname = (char *)utf8proc_NFC((const unsigned char *)unewname);
530 if(newname == NULL)
531     return NC_EBADNAME;
532 if(NC_indef(ncp))
533 {
534 newStr = new_NC_string(strlen(newname), newname);
535 free(newname);
536 if( newStr == NULL)
537 return NC_ENOMEM;
538 attrp->name = newStr;
539 free_NC_string(old);
540 return NC_NOERR;
541 }
542 /* else */
543 status = set_NC_string(oldnewname);
544 free(newname);
545 if( status != NC_NOERR)
546 return status;
547
548 set_NC_hdirty(ncp);
549
550 if(NC_doHsync(ncp))
551 {
552 status = NC_sync(ncp);
553 if(status != NC_NOERR)
554 return status;
555 }
556
557 return NC_NOERR;
558}
559
560int
561NC3_del_att(int ncid, int varid, const char *uname)
562{
563 int status;
564 NC *nc;
565 NC3_INFOncp;
566 NC_attrarray *ncap;
567 NC_attr **attrpp;
568 NC_attr *old = NULL;
569 int attrid;
570 size_t slen;
571
572 status = NC_check_id(ncid, &nc);
573 if(status != NC_NOERR)
574 return status;
575 ncp = NC3_DATA(nc);
576
577 if(!NC_indef(ncp))
578 return NC_ENOTINDEFINE;
579
580 ncap = NC_attrarray0(ncpvarid);
581 if(ncap == NULL)
582 return NC_ENOTVAR;
583
584 {
585 char *name = (char *)utf8proc_NFC((const unsigned char *)uname);
586 if(name == NULL)
587     return NC_ENOMEM;
588
589 /* sortof inline NC_findattr() */
590 slen = strlen(name);
591
592 attrpp = (NC_attr **) ncap->value;
593 for(attrid = 0; (size_t) attrid < ncap->nelemsattrid++, attrpp++)
594     {
595 if( slen == (*attrpp)->name->nchars &&
596 strncmp(name, (*attrpp)->name->cpslen) == 0)
597 {
598 old = *attrpp;
599 break;
600 }
601     }
602 free(name);
603 }
604 if( (size_t) attrid == ncap->nelems )
605 return NC_ENOTATT;
606 /* end inline NC_findattr() */
607
608 /* shuffle down */
609 for(attrid++; (size_t) attrid < ncap->nelemsattrid++)
610 {
611 *attrpp = *(attrpp + 1);
612 attrpp++;
613 }
614 *attrpp = NULL;
615 /* decrement count */
616 ncap->nelems--;
617
618 free_NC_attr(old);
619
620 return NC_NOERR;
621}
622
623
624static int
625ncx_pad_putn_Iuchar(void **xpp, size_t nelems, const uchar *tpnc_type type)
626{
627 switch(type) {
628 case NC_CHAR:
629 return NC_ECHAR;
630 case NC_BYTE:
631 return ncx_pad_putn_schar_uchar(xppnelemstp);
632 case NC_SHORT:
633 return ncx_pad_putn_short_uchar(xppnelemstp);
634 case NC_INT:
635 return ncx_putn_int_uchar(xppnelemstp);
636 case NC_FLOAT:
637 return ncx_putn_float_uchar(xppnelemstp);
638 case NC_DOUBLE:
639 return ncx_putn_double_uchar(xppnelemstp);
640 case NC_UBYTE:
641 return ncx_pad_putn_uchar_uchar(xppnelemstp);
642 case NC_USHORT:
643 return ncx_putn_ushort_uchar(xppnelemstp);
644 case NC_UINT:
645 return ncx_putn_uint_uchar(xppnelemstp);
646 case NC_INT64:
647 return ncx_putn_longlong_uchar(xppnelemstp);
648 case NC_UINT64:
649 return ncx_putn_ulonglong_uchar(xppnelemstp);
650 default:
651                assert("ncx_pad_putn_Iuchar invalid type" == 0);
652 }
653 return NC_EBADTYPE;
654}
655
656static int
657ncx_pad_getn_Iuchar(const void **xpp, size_t nelemsuchar *tpnc_type type)
658{
659 switch(type) {
660 case NC_CHAR:
661 return NC_ECHAR;
662 case NC_BYTE:
663 return ncx_pad_getn_schar_uchar(xppnelemstp);
664 case NC_SHORT:
665 return ncx_pad_getn_short_uchar(xppnelemstp);
666 case NC_INT:
667 return ncx_getn_int_uchar(xppnelemstp);
668 case NC_FLOAT:
669 return ncx_getn_float_uchar(xppnelemstp);
670 case NC_DOUBLE:
671 return ncx_getn_double_uchar(xppnelemstp);
672 case NC_UBYTE:
673 return ncx_pad_getn_uchar_uchar(xppnelemstp);
674 case NC_USHORT:
675 return ncx_getn_ushort_uchar(xppnelemstp);
676 case NC_UINT:
677 return ncx_getn_uint_uchar(xppnelemstp);
678 case NC_INT64:
679 return ncx_getn_longlong_uchar(xppnelemstp);
680 case NC_UINT64:
681 return ncx_getn_ulonglong_uchar(xppnelemstp);
682 default:
683         assert("ncx_pad_getn_Iuchar invalid type" == 0);
684 }
685 return NC_EBADTYPE;
686}
687
688
689static int
690ncx_pad_putn_Ischar(void **xpp, size_t nelems, const schar *tpnc_type type)
691{
692 switch(type) {
693 case NC_CHAR:
694 return NC_ECHAR;
695 case NC_BYTE:
696 return ncx_pad_putn_schar_schar(xppnelemstp);
697 case NC_SHORT:
698 return ncx_pad_putn_short_schar(xppnelemstp);
699 case NC_INT:
700 return ncx_putn_int_schar(xppnelemstp);
701 case NC_FLOAT:
702 return ncx_putn_float_schar(xppnelemstp);
703 case NC_DOUBLE:
704 return ncx_putn_double_schar(xppnelemstp);
705 case NC_UBYTE:
706 return ncx_pad_putn_uchar_schar(xppnelemstp);
707 case NC_USHORT:
708 return ncx_putn_ushort_schar(xppnelemstp);
709 case NC_UINT:
710 return ncx_putn_uint_schar(xppnelemstp);
711 case NC_INT64:
712 return ncx_putn_longlong_schar(xppnelemstp);
713 case NC_UINT64:
714 return ncx_putn_ulonglong_schar(xppnelemstp);
715 default:
716                assert("ncx_pad_putn_Ischar invalid type" == 0);
717 }
718 return NC_EBADTYPE;
719}
720
721static int
722ncx_pad_getn_Ischar(const void **xpp, size_t nelemsschar *tpnc_type type)
723{
724 switch(type) {
725 case NC_CHAR:
726 return NC_ECHAR;
727 case NC_BYTE:
728 return ncx_pad_getn_schar_schar(xppnelemstp);
729 case NC_SHORT:
730 return ncx_pad_getn_short_schar(xppnelemstp);
731 case NC_INT:
732 return ncx_getn_int_schar(xppnelemstp);
733 case NC_FLOAT:
734 return ncx_getn_float_schar(xppnelemstp);
735 case NC_DOUBLE:
736 return ncx_getn_double_schar(xppnelemstp);
737 case NC_UBYTE:
738 return ncx_pad_getn_uchar_schar(xppnelemstp);
739 case NC_USHORT:
740 return ncx_getn_ushort_schar(xppnelemstp);
741 case NC_UINT:
742 return ncx_getn_uint_schar(xppnelemstp);
743 case NC_INT64:
744 return ncx_getn_longlong_schar(xppnelemstp);
745 case NC_UINT64:
746 return ncx_getn_ulonglong_schar(xppnelemstp);
747 default:
748         assert("ncx_pad_getn_Ischar invalid type" == 0);
749 }
750 return NC_EBADTYPE;
751}
752
753
754static int
755ncx_pad_putn_Ishort(void **xpp, size_t nelems, const short *tpnc_type type)
756{
757 switch(type) {
758 case NC_CHAR:
759 return NC_ECHAR;
760 case NC_BYTE:
761 return ncx_pad_putn_schar_short(xppnelemstp);
762 case NC_SHORT:
763 return ncx_pad_putn_short_short(xppnelemstp);
764 case NC_INT:
765 return ncx_putn_int_short(xppnelemstp);
766 case NC_FLOAT:
767 return ncx_putn_float_short(xppnelemstp);
768 case NC_DOUBLE:
769 return ncx_putn_double_short(xppnelemstp);
770 case NC_UBYTE:
771 return ncx_pad_putn_uchar_short(xppnelemstp);
772 case NC_USHORT:
773 return ncx_putn_ushort_short(xppnelemstp);
774 case NC_UINT:
775 return ncx_putn_uint_short(xppnelemstp);
776 case NC_INT64:
777 return ncx_putn_longlong_short(xppnelemstp);
778 case NC_UINT64:
779 return ncx_putn_ulonglong_short(xppnelemstp);
780 default:
781                assert("ncx_pad_putn_Ishort invalid type" == 0);
782 }
783 return NC_EBADTYPE;
784}
785
786static int
787ncx_pad_getn_Ishort(const void **xpp, size_t nelems, short *tpnc_type type)
788{
789 switch(type) {
790 case NC_CHAR:
791 return NC_ECHAR;
792 case NC_BYTE:
793 return ncx_pad_getn_schar_short(xppnelemstp);
794 case NC_SHORT:
795 return ncx_pad_getn_short_short(xppnelemstp);
796 case NC_INT:
797 return ncx_getn_int_short(xppnelemstp);
798 case NC_FLOAT:
799 return ncx_getn_float_short(xppnelemstp);
800 case NC_DOUBLE:
801 return ncx_getn_double_short(xppnelemstp);
802 case NC_UBYTE:
803 return ncx_pad_getn_uchar_short(xppnelemstp);
804 case NC_USHORT:
805 return ncx_getn_ushort_short(xppnelemstp);
806 case NC_UINT:
807 return ncx_getn_uint_short(xppnelemstp);
808 case NC_INT64:
809 return ncx_getn_longlong_short(xppnelemstp);
810 case NC_UINT64:
811 return ncx_getn_ulonglong_short(xppnelemstp);
812 default:
813         assert("ncx_pad_getn_Ishort invalid type" == 0);
814 }
815 return NC_EBADTYPE;
816}
817
818
819static int
820ncx_pad_putn_Iint(void **xpp, size_t nelems, const int *tpnc_type type)
821{
822 switch(type) {
823 case NC_CHAR:
824 return NC_ECHAR;
825 case NC_BYTE:
826 return ncx_pad_putn_schar_int(xppnelemstp);
827 case NC_SHORT:
828 return ncx_pad_putn_short_int(xppnelemstp);
829 case NC_INT:
830 return ncx_putn_int_int(xppnelemstp);
831 case NC_FLOAT:
832 return ncx_putn_float_int(xppnelemstp);
833 case NC_DOUBLE:
834 return ncx_putn_double_int(xppnelemstp);
835 case NC_UBYTE:
836 return ncx_pad_putn_uchar_int(xppnelemstp);
837 case NC_USHORT:
838 return ncx_putn_ushort_int(xppnelemstp);
839 case NC_UINT:
840 return ncx_putn_uint_int(xppnelemstp);
841 case NC_INT64:
842 return ncx_putn_longlong_int(xppnelemstp);
843 case NC_UINT64:
844 return ncx_putn_ulonglong_int(xppnelemstp);
845 default:
846                assert("ncx_pad_putn_Iint invalid type" == 0);
847 }
848 return NC_EBADTYPE;
849}
850
851static int
852ncx_pad_getn_Iint(const void **xpp, size_t nelems, int *tpnc_type type)
853{
854 switch(type) {
855 case NC_CHAR:
856 return NC_ECHAR;
857 case NC_BYTE:
858 return ncx_pad_getn_schar_int(xppnelemstp);
859 case NC_SHORT:
860 return ncx_pad_getn_short_int(xppnelemstp);
861 case NC_INT:
862 return ncx_getn_int_int(xppnelemstp);
863 case NC_FLOAT:
864 return ncx_getn_float_int(xppnelemstp);
865 case NC_DOUBLE:
866 return ncx_getn_double_int(xppnelemstp);
867 case NC_UBYTE:
868 return ncx_pad_getn_uchar_int(xppnelemstp);
869 case NC_USHORT:
870 return ncx_getn_ushort_int(xppnelemstp);
871 case NC_UINT:
872 return ncx_getn_uint_int(xppnelemstp);
873 case NC_INT64:
874 return ncx_getn_longlong_int(xppnelemstp);
875 case NC_UINT64:
876 return ncx_getn_ulonglong_int(xppnelemstp);
877 default:
878         assert("ncx_pad_getn_Iint invalid type" == 0);
879 }
880 return NC_EBADTYPE;
881}
882
883
884static int
885ncx_pad_putn_Ifloat(void **xpp, size_t nelems, const float *tpnc_type type)
886{
887 switch(type) {
888 case NC_CHAR:
889 return NC_ECHAR;
890 case NC_BYTE:
891 return ncx_pad_putn_schar_float(xppnelemstp);
892 case NC_SHORT:
893 return ncx_pad_putn_short_float(xppnelemstp);
894 case NC_INT:
895 return ncx_putn_int_float(xppnelemstp);
896 case NC_FLOAT:
897 return ncx_putn_float_float(xppnelemstp);
898 case NC_DOUBLE:
899 return ncx_putn_double_float(xppnelemstp);
900 case NC_UBYTE:
901 return ncx_pad_putn_uchar_float(xppnelemstp);
902 case NC_USHORT:
903 return ncx_putn_ushort_float(xppnelemstp);
904 case NC_UINT:
905 return ncx_putn_uint_float(xppnelemstp);
906 case NC_INT64:
907 return ncx_putn_longlong_float(xppnelemstp);
908 case NC_UINT64:
909 return ncx_putn_ulonglong_float(xppnelemstp);
910 default:
911                assert("ncx_pad_putn_Ifloat invalid type" == 0);
912 }
913 return NC_EBADTYPE;
914}
915
916static int
917ncx_pad_getn_Ifloat(const void **xpp, size_t nelems, float *tpnc_type type)
918{
919 switch(type) {
920 case NC_CHAR:
921 return NC_ECHAR;
922 case NC_BYTE:
923 return ncx_pad_getn_schar_float(xppnelemstp);
924 case NC_SHORT:
925 return ncx_pad_getn_short_float(xppnelemstp);
926 case NC_INT:
927 return ncx_getn_int_float(xppnelemstp);
928 case NC_FLOAT:
929 return ncx_getn_float_float(xppnelemstp);
930 case NC_DOUBLE:
931 return ncx_getn_double_float(xppnelemstp);
932 case NC_UBYTE:
933 return ncx_pad_getn_uchar_float(xppnelemstp);
934 case NC_USHORT:
935 return ncx_getn_ushort_float(xppnelemstp);
936 case NC_UINT:
937 return ncx_getn_uint_float(xppnelemstp);
938 case NC_INT64:
939 return ncx_getn_longlong_float(xppnelemstp);
940 case NC_UINT64:
941 return ncx_getn_ulonglong_float(xppnelemstp);
942 default:
943         assert("ncx_pad_getn_Ifloat invalid type" == 0);
944 }
945 return NC_EBADTYPE;
946}
947
948
949static int
950ncx_pad_putn_Idouble(void **xpp, size_t nelems, const double *tpnc_type type)
951{
952 switch(type) {
953 case NC_CHAR:
954 return NC_ECHAR;
955 case NC_BYTE:
956 return ncx_pad_putn_schar_double(xppnelemstp);
957 case NC_SHORT:
958 return ncx_pad_putn_short_double(xppnelemstp);
959 case NC_INT:
960 return ncx_putn_int_double(xppnelemstp);
961 case NC_FLOAT:
962 return ncx_putn_float_double(xppnelemstp);
963 case NC_DOUBLE:
964 return ncx_putn_double_double(xppnelemstp);
965 case NC_UBYTE:
966 return ncx_pad_putn_uchar_double(xppnelemstp);
967 case NC_USHORT:
968 return ncx_putn_ushort_double(xppnelemstp);
969 case NC_UINT:
970 return ncx_putn_uint_double(xppnelemstp);
971 case NC_INT64:
972 return ncx_putn_longlong_double(xppnelemstp);
973 case NC_UINT64:
974 return ncx_putn_ulonglong_double(xppnelemstp);
975 default:
976                assert("ncx_pad_putn_Idouble invalid type" == 0);
977 }
978 return NC_EBADTYPE;
979}
980
981static int
982ncx_pad_getn_Idouble(const void **xpp, size_t nelems, double *tpnc_type type)
983{
984 switch(type) {
985 case NC_CHAR:
986 return NC_ECHAR;
987 case NC_BYTE:
988 return ncx_pad_getn_schar_double(xppnelemstp);
989 case NC_SHORT:
990 return ncx_pad_getn_short_double(xppnelemstp);
991 case NC_INT:
992 return ncx_getn_int_double(xppnelemstp);
993 case NC_FLOAT:
994 return ncx_getn_float_double(xppnelemstp);
995 case NC_DOUBLE:
996 return ncx_getn_double_double(xppnelemstp);
997 case NC_UBYTE:
998 return ncx_pad_getn_uchar_double(xppnelemstp);
999 case NC_USHORT:
1000 return ncx_getn_ushort_double(xppnelemstp);
1001 case NC_UINT:
1002 return ncx_getn_uint_double(xppnelemstp);
1003 case NC_INT64:
1004 return ncx_getn_longlong_double(xppnelemstp);
1005 case NC_UINT64:
1006 return ncx_getn_ulonglong_double(xppnelemstp);
1007 default:
1008         assert("ncx_pad_getn_Idouble invalid type" == 0);
1009 }
1010 return NC_EBADTYPE;
1011}
1012
1013
1014#ifdef IGNORE
1015static int
1016ncx_pad_putn_Ilong(void **xpp, size_t nelems, const long *tpnc_type type)
1017{
1018 switch(type) {
1019 case NC_CHAR:
1020 return NC_ECHAR;
1021 case NC_BYTE:
1022 return ncx_pad_putn_schar_long(xppnelemstp);
1023 case NC_SHORT:
1024 return ncx_pad_putn_short_long(xppnelemstp);
1025 case NC_INT:
1026 return ncx_putn_int_long(xppnelemstp);
1027 case NC_FLOAT:
1028 return ncx_putn_float_long(xppnelemstp);
1029 case NC_DOUBLE:
1030 return ncx_putn_double_long(xppnelemstp);
1031 case NC_UBYTE:
1032 return ncx_pad_putn_uchar_long(xppnelemstp);
1033 case NC_USHORT:
1034 return ncx_putn_ushort_long(xppnelemstp);
1035 case NC_UINT:
1036 return ncx_putn_uint_long(xppnelemstp);
1037 case NC_INT64:
1038 return ncx_putn_longlong_long(xppnelemstp);
1039 case NC_UINT64:
1040 return ncx_putn_ulonglong_long(xppnelemstp);
1041 default:
1042                assert("ncx_pad_putn_Ilong invalid type" == 0);
1043 }
1044 return NC_EBADTYPE;
1045}
1046
1047static int
1048ncx_pad_getn_Ilong(const void **xpp, size_t nelems, long *tpnc_type type)
1049{
1050 switch(type) {
1051 case NC_CHAR:
1052 return NC_ECHAR;
1053 case NC_BYTE:
1054 return ncx_pad_getn_schar_long(xppnelemstp);
1055 case NC_SHORT:
1056 return ncx_pad_getn_short_long(xppnelemstp);
1057 case NC_INT:
1058 return ncx_getn_int_long(xppnelemstp);
1059 case NC_FLOAT:
1060 return ncx_getn_float_long(xppnelemstp);
1061 case NC_DOUBLE:
1062 return ncx_getn_double_long(xppnelemstp);
1063 case NC_UBYTE:
1064 return ncx_pad_getn_uchar_long(xppnelemstp);
1065 case NC_USHORT:
1066 return ncx_getn_ushort_long(xppnelemstp);
1067 case NC_UINT:
1068 return ncx_getn_uint_long(xppnelemstp);
1069 case NC_INT64:
1070 return ncx_getn_longlong_long(xppnelemstp);
1071 case NC_UINT64:
1072 return ncx_getn_ulonglong_long(xppnelemstp);
1073 default:
1074         assert("ncx_pad_getn_Ilong invalid type" == 0);
1075 }
1076 return NC_EBADTYPE;
1077}
1078
1079#endif
1080
1081static int
1082ncx_pad_putn_Ilonglong(void **xpp, size_t nelems, const longlong *tpnc_type type)
1083{
1084 switch(type) {
1085 case NC_CHAR:
1086 return NC_ECHAR;
1087 case NC_BYTE:
1088 return ncx_pad_putn_schar_longlong(xppnelemstp);
1089 case NC_SHORT:
1090 return ncx_pad_putn_short_longlong(xppnelemstp);
1091 case NC_INT:
1092 return ncx_putn_int_longlong(xppnelemstp);
1093 case NC_FLOAT:
1094 return ncx_putn_float_longlong(xppnelemstp);
1095 case NC_DOUBLE:
1096 return ncx_putn_double_longlong(xppnelemstp);
1097 case NC_UBYTE:
1098 return ncx_pad_putn_uchar_longlong(xppnelemstp);
1099 case NC_USHORT:
1100 return ncx_putn_ushort_longlong(xppnelemstp);
1101 case NC_UINT:
1102 return ncx_putn_uint_longlong(xppnelemstp);
1103 case NC_INT64:
1104 return ncx_putn_longlong_longlong(xppnelemstp);
1105 case NC_UINT64:
1106 return ncx_putn_ulonglong_longlong(xppnelemstp);
1107 default:
1108                assert("ncx_pad_putn_Ilonglong invalid type" == 0);
1109 }
1110 return NC_EBADTYPE;
1111}
1112
1113static int
1114ncx_pad_getn_Ilonglong(const void **xpp, size_t nelemslonglong *tpnc_type type)
1115{
1116 switch(type) {
1117 case NC_CHAR:
1118 return NC_ECHAR;
1119 case NC_BYTE:
1120 return ncx_pad_getn_schar_longlong(xppnelemstp);
1121 case NC_SHORT:
1122 return ncx_pad_getn_short_longlong(xppnelemstp);
1123 case NC_INT:
1124 return ncx_getn_int_longlong(xppnelemstp);
1125 case NC_FLOAT:
1126 return ncx_getn_float_longlong(xppnelemstp);
1127 case NC_DOUBLE:
1128 return ncx_getn_double_longlong(xppnelemstp);
1129 case NC_UBYTE:
1130 return ncx_pad_getn_uchar_longlong(xppnelemstp);
1131 case NC_USHORT:
1132 return ncx_getn_ushort_longlong(xppnelemstp);
1133 case NC_UINT:
1134 return ncx_getn_uint_longlong(xppnelemstp);
1135 case NC_INT64:
1136 return ncx_getn_longlong_longlong(xppnelemstp);
1137 case NC_UINT64:
1138 return ncx_getn_ulonglong_longlong(xppnelemstp);
1139 default:
1140         assert("ncx_pad_getn_Ilonglong invalid type" == 0);
1141 }
1142 return NC_EBADTYPE;
1143}
1144
1145
1146static int
1147ncx_pad_putn_Iushort(void **xpp, size_t nelems, const ushort *tpnc_type type)
1148{
1149 switch(type) {
1150 case NC_CHAR:
1151 return NC_ECHAR;
1152 case NC_BYTE:
1153 return ncx_pad_putn_schar_ushort(xppnelemstp);
1154 case NC_SHORT:
1155 return ncx_pad_putn_short_ushort(xppnelemstp);
1156 case NC_INT:
1157 return ncx_putn_int_ushort(xppnelemstp);
1158 case NC_FLOAT:
1159 return ncx_putn_float_ushort(xppnelemstp);
1160 case NC_DOUBLE:
1161 return ncx_putn_double_ushort(xppnelemstp);
1162 case NC_UBYTE:
1163 return ncx_pad_putn_uchar_ushort(xppnelemstp);
1164 case NC_USHORT:
1165 return ncx_putn_ushort_ushort(xppnelemstp);
1166 case NC_UINT:
1167 return ncx_putn_uint_ushort(xppnelemstp);
1168 case NC_INT64:
1169 return ncx_putn_longlong_ushort(xppnelemstp);
1170 case NC_UINT64:
1171 return ncx_putn_ulonglong_ushort(xppnelemstp);
1172 default:
1173                assert("ncx_pad_putn_Iushort invalid type" == 0);
1174 }
1175 return NC_EBADTYPE;
1176}
1177
1178static int
1179ncx_pad_getn_Iushort(const void **xpp, size_t nelemsushort *tpnc_type type)
1180{
1181 switch(type) {
1182 case NC_CHAR:
1183 return NC_ECHAR;
1184 case NC_BYTE:
1185 return ncx_pad_getn_schar_ushort(xppnelemstp);
1186 case NC_SHORT:
1187 return ncx_pad_getn_short_ushort(xppnelemstp);
1188 case NC_INT:
1189 return ncx_getn_int_ushort(xppnelemstp);
1190 case NC_FLOAT:
1191 return ncx_getn_float_ushort(xppnelemstp);
1192 case NC_DOUBLE:
1193 return ncx_getn_double_ushort(xppnelemstp);
1194 case NC_UBYTE:
1195 return ncx_pad_getn_uchar_ushort(xppnelemstp);
1196 case NC_USHORT:
1197 return ncx_getn_ushort_ushort(xppnelemstp);
1198 case NC_UINT:
1199 return ncx_getn_uint_ushort(xppnelemstp);
1200 case NC_INT64:
1201 return ncx_getn_longlong_ushort(xppnelemstp);
1202 case NC_UINT64:
1203 return ncx_getn_ulonglong_ushort(xppnelemstp);
1204 default:
1205         assert("ncx_pad_getn_Iushort invalid type" == 0);
1206 }
1207 return NC_EBADTYPE;
1208}
1209
1210
1211static int
1212ncx_pad_putn_Iuint(void **xpp, size_t nelems, const uint *tpnc_type type)
1213{
1214 switch(type) {
1215 case NC_CHAR:
1216 return NC_ECHAR;
1217 case NC_BYTE:
1218 return ncx_pad_putn_schar_uint(xppnelemstp);
1219 case NC_SHORT:
1220 return ncx_pad_putn_short_uint(xppnelemstp);
1221 case NC_INT:
1222 return ncx_putn_int_uint(xppnelemstp);
1223 case NC_FLOAT:
1224 return ncx_putn_float_uint(xppnelemstp);
1225 case NC_DOUBLE:
1226 return ncx_putn_double_uint(xppnelemstp);
1227 case NC_UBYTE:
1228 return ncx_pad_putn_uchar_uint(xppnelemstp);
1229 case NC_USHORT:
1230 return ncx_putn_ushort_uint(xppnelemstp);
1231 case NC_UINT:
1232 return ncx_putn_uint_uint(xppnelemstp);
1233 case NC_INT64:
1234 return ncx_putn_longlong_uint(xppnelemstp);
1235 case NC_UINT64:
1236 return ncx_putn_ulonglong_uint(xppnelemstp);
1237 default:
1238                assert("ncx_pad_putn_Iuint invalid type" == 0);
1239 }
1240 return NC_EBADTYPE;
1241}
1242
1243static int
1244ncx_pad_getn_Iuint(const void **xpp, size_t nelemsuint *tpnc_type type)
1245{
1246 switch(type) {
1247 case NC_CHAR:
1248 return NC_ECHAR;
1249 case NC_BYTE:
1250 return ncx_pad_getn_schar_uint(xppnelemstp);
1251 case NC_SHORT:
1252 return ncx_pad_getn_short_uint(xppnelemstp);
1253 case NC_INT:
1254 return ncx_getn_int_uint(xppnelemstp);
1255 case NC_FLOAT:
1256 return ncx_getn_float_uint(xppnelemstp);
1257 case NC_DOUBLE:
1258 return ncx_getn_double_uint(xppnelemstp);
1259 case NC_UBYTE:
1260 return ncx_pad_getn_uchar_uint(xppnelemstp);
1261 case NC_USHORT:
1262 return ncx_getn_ushort_uint(xppnelemstp);
1263 case NC_UINT:
1264 return ncx_getn_uint_uint(xppnelemstp);
1265 case NC_INT64:
1266 return ncx_getn_longlong_uint(xppnelemstp);
1267 case NC_UINT64:
1268 return ncx_getn_ulonglong_uint(xppnelemstp);
1269 default:
1270         assert("ncx_pad_getn_Iuint invalid type" == 0);
1271 }
1272 return NC_EBADTYPE;
1273}
1274
1275
1276static int
1277ncx_pad_putn_Iulonglong(void **xpp, size_t nelems, const ulonglong *tpnc_type type)
1278{
1279 switch(type) {
1280 case NC_CHAR:
1281 return NC_ECHAR;
1282 case NC_BYTE:
1283 return ncx_pad_putn_schar_ulonglong(xppnelemstp);
1284 case NC_SHORT:
1285 return ncx_pad_putn_short_ulonglong(xppnelemstp);
1286 case NC_INT:
1287 return ncx_putn_int_ulonglong(xppnelemstp);
1288 case NC_FLOAT:
1289 return ncx_putn_float_ulonglong(xppnelemstp);
1290 case NC_DOUBLE:
1291 return ncx_putn_double_ulonglong(xppnelemstp);
1292 case NC_UBYTE:
1293 return ncx_pad_putn_uchar_ulonglong(xppnelemstp);
1294 case NC_USHORT:
1295 return ncx_putn_ushort_ulonglong(xppnelemstp);
1296 case NC_UINT:
1297 return ncx_putn_uint_ulonglong(xppnelemstp);
1298 case NC_INT64:
1299 return ncx_putn_longlong_ulonglong(xppnelemstp);
1300 case NC_UINT64:
1301 return ncx_putn_ulonglong_ulonglong(xppnelemstp);
1302 default:
1303                assert("ncx_pad_putn_Iulonglong invalid type" == 0);
1304 }
1305 return NC_EBADTYPE;
1306}
1307
1308static int
1309ncx_pad_getn_Iulonglong(const void **xpp, size_t nelemsulonglong *tpnc_type type)
1310{
1311 switch(type) {
1312 case NC_CHAR:
1313 return NC_ECHAR;
1314 case NC_BYTE:
1315 return ncx_pad_getn_schar_ulonglong(xppnelemstp);
1316 case NC_SHORT:
1317 return ncx_pad_getn_short_ulonglong(xppnelemstp);
1318 case NC_INT:
1319 return ncx_getn_int_ulonglong(xppnelemstp);
1320 case NC_FLOAT:
1321 return ncx_getn_float_ulonglong(xppnelemstp);
1322 case NC_DOUBLE:
1323 return ncx_getn_double_ulonglong(xppnelemstp);
1324 case NC_UBYTE:
1325 return ncx_pad_getn_uchar_ulonglong(xppnelemstp);
1326 case NC_USHORT:
1327 return ncx_getn_ushort_ulonglong(xppnelemstp);
1328 case NC_UINT:
1329 return ncx_getn_uint_ulonglong(xppnelemstp);
1330 case NC_INT64:
1331 return ncx_getn_longlong_ulonglong(xppnelemstp);
1332 case NC_UINT64:
1333 return ncx_getn_ulonglong_ulonglong(xppnelemstp);
1334 default:
1335         assert("ncx_pad_getn_Iulonglong invalid type" == 0);
1336 }
1337 return NC_EBADTYPE;
1338}
1339
1340
1341
1342/* Common dispatcher for put cases */
1343static int
1344dispatchput(void **xpp, size_t nelems, const void* tp,
1345     nc_type atypenc_type memtype)
1346{
1347    switch (memtype) {
1348    case NC_CHAR:
1349        return ncx_pad_putn_text(xpp,nelems, (char *)tp);
1350    case NC_BYTE:
1351        return ncx_pad_putn_Ischar(xppnelems, (schar*)tpatype);
1352    case NC_SHORT:
1353        return ncx_pad_putn_Ishort(xppnelems, (short*)tpatype);
1354    case NC_INT:
1355          return ncx_pad_putn_Iint(xppnelems, (int*)tpatype);
1356    case NC_FLOAT:
1357        return ncx_pad_putn_Ifloat(xppnelems, (float*)tpatype);
1358    case NC_DOUBLE:
1359        return ncx_pad_putn_Idouble(xppnelems, (double*)tpatype);
1360    case NC_UBYTE: /*Synthetic*/
1361        return ncx_pad_putn_Iuchar(xpp,nelems, (uchar *)tpatype);
1362    case NC_INT64:
1363          return ncx_pad_putn_Ilonglong(xppnelems, (longlong*)tpatype);
1364    case NC_USHORT:
1365          return ncx_pad_putn_Iushort(xppnelems, (ushort*)tpatype);
1366    case NC_UINT:
1367          return ncx_pad_putn_Iuint(xppnelems, (uint*)tpatype);
1368    case NC_UINT64:
1369          return ncx_pad_putn_Iulonglong(xppnelems, (ulonglong*)tpatype);
1370    case NC_NAT:
1371        return NC_EBADTYPE;
1372    default:
1373        break;
1374    }
1375    return NC_EBADTYPE;
1376}
1377
1378int
1379NC3_put_att(
1380 int ncid,
1381 int varid,
1382 const char *name,
1383 nc_type type,
1384 size_t nelems,
1385 const void *value,
1386 nc_type memtype)
1387{
1388    int status;
1389    NC *nc;
1390    NC3_INFOncp;
1391    NC_attrarray *ncap;
1392    NC_attr **attrpp;
1393    NC_attr *old = NULL;
1394    NC_attr *attrp;
1395
1396    status = NC_check_id(ncid, &nc);
1397    if(status != NC_NOERR)
1398 return status;
1399    ncp = NC3_DATA(nc);
1400
1401    if(NC_readonly(ncp))
1402 return NC_EPERM;
1403
1404    ncap = NC_attrarray0(ncpvarid);
1405    if(ncap == NULL)
1406 return NC_ENOTVAR;
1407
1408    status = nc3_cktype(nc->modetype);
1409    if(status != NC_NOERR)
1410 return status;
1411
1412    if(memtype == NC_NATmemtype = type;
1413
1414    if(memtype != NC_CHAR && type == NC_CHAR)
1415 return NC_ECHAR;
1416    if(memtype == NC_CHAR && type != NC_CHAR)
1417 return NC_ECHAR;
1418
1419    /* cast needed for braindead systems with signed size_t */
1420    if((unsigned long) nelems > X_INT_MAX) /* backward compat */
1421 return NC_EINVAL; /* Invalid nelems */
1422
1423    if(nelems != 0 && value == NULL)
1424 return NC_EINVAL; /* Null arg */
1425
1426    attrpp = NC_findattr(ncapname);
1427
1428    /* 4 cases: exists X indef */
1429
1430    if(attrpp != NULL) { /* name in use */
1431        if(!NC_indef(ncp)) {
1432     const size_t xsz = ncx_len_NC_attrV(typenelems);
1433            attrp = *attrpp; /* convenience */
1434
1435     if(xsz > attrp->xsz) return NC_ENOTINDEFINE;
1436     /* else, we can reuse existing without redef */
1437
1438     attrp->xsz = xsz;
1439            attrp->type = type;
1440            attrp->nelems = nelems;
1441
1442            if(nelems != 0) {
1443                void *xp = attrp->xvalue;
1444                status = dispatchput(&xpnelems, (const void*)valuetypememtype);
1445            }
1446
1447            set_NC_hdirty(ncp);
1448
1449            if(NC_doHsync(ncp)) {
1450         const int lstatus = NC_sync(ncp);
1451                /*
1452                 * N.B.: potentially overrides NC_ERANGE
1453                 * set by ncx_pad_putn_I$1
1454                 */
1455                if(lstatus != NC_NOERR) return lstatus;
1456            }
1457
1458            return status;
1459        }
1460        /* else, redefine using existing array slot */
1461        old = *attrpp;
1462    } else {
1463        if(!NC_indef(ncp)) return NC_ENOTINDEFINE;
1464
1465        if(ncap->nelems >= NC_MAX_ATTRS) return NC_EMAXATTS;
1466    }
1467
1468    status = NC_check_name(name);
1469    if(status != NC_NOERR) return status;
1470
1471    attrp = new_NC_attr(nametypenelems);
1472    if(attrp == NULL) return NC_ENOMEM;
1473
1474    if(nelems != 0) {
1475        void *xp = attrp->xvalue;
1476        status = dispatchput(&xpnelems, (const void*)valuetypememtype);
1477    }
1478
1479    if(attrpp != NULL) {
1480        *attrpp = attrp;
1481 if(old != NULL)
1482         free_NC_attr(old);
1483    } else {
1484        const int lstatus = incr_NC_attrarray(ncapattrp);
1485        /*
1486         * N.B.: potentially overrides NC_ERANGE
1487         * set by ncx_pad_putn_I$1
1488         */
1489        if(lstatus != NC_NOERR) {
1490           free_NC_attr(attrp);
1491           return lstatus;
1492        }
1493    }
1494    return status;
1495}
1496
1497int
1498NC3_get_att(
1499 int ncid,
1500 int varid,
1501 const char *name,
1502 void *value,
1503 nc_type memtype)
1504{
1505    int status;
1506    NC_attr *attrp;
1507    const void *xp;
1508
1509    status = NC_lookupattr(ncidvaridname, &attrp);
1510    if(status != NC_NOERR) return status;
1511
1512    if(attrp->nelems == 0) return NC_NOERR;
1513
1514    if(memtype == NC_NATmemtype = attrp->type;
1515
1516    if(memtype != NC_CHAR && attrp->type == NC_CHAR)
1517 return NC_ECHAR;
1518    if(memtype == NC_CHAR && attrp->type != NC_CHAR)
1519 return NC_ECHAR;
1520
1521    xp = attrp->xvalue;
1522    switch (memtype) {
1523    case NC_CHAR:
1524        return ncx_pad_getn_text(&xpattrp->nelems , (char *)value);
1525    case NC_BYTE:
1526        return ncx_pad_getn_Ischar(&xp,attrp->nelems,(schar*)value,attrp->type);
1527    case NC_SHORT:
1528        return ncx_pad_getn_Ishort(&xp,attrp->nelems,(short*)value,attrp->type);
1529    case NC_INT:
1530          return ncx_pad_getn_Iint(&xp,attrp->nelems,(int*)value,attrp->type);
1531    case NC_FLOAT:
1532        return ncx_pad_getn_Ifloat(&xp,attrp->nelems,(float*)value,attrp->type);
1533    case NC_DOUBLE:
1534        return ncx_pad_getn_Idouble(&xp,attrp->nelems,(double*)value,attrp->type);
1535    case NC_INT64:
1536          return ncx_pad_getn_Ilonglong(&xp,attrp->nelems,(longlong*)value,attrp->type);
1537    case NC_UBYTE: /* Synthetic */
1538        return ncx_pad_getn_Iuchar(&xpattrp->nelems , (uchar *)valueattrp->type);
1539    case NC_USHORT:
1540          return ncx_pad_getn_Iushort(&xp,attrp->nelems,(ushort*)value,attrp->type);
1541    case NC_UINT:
1542          return ncx_pad_getn_Iuint(&xp,attrp->nelems,(uint*)value,attrp->type);
1543    case NC_UINT64:
1544          return ncx_pad_getn_Iulonglong(&xp,attrp->nelems,(ulonglong*)value,attrp->type);
1545
1546    case NC_NAT:
1547        return NC_EBADTYPE;
1548    default:
1549        break;
1550    }
1551    status =  NC_EBADTYPE;
1552    return status;
1553}


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed