source: XIOS/dev/branch_openmp/extern/src_netcdf4/attr.c @ 1501

Last change on this file since 1501 was 409, checked in by ymipsl, 11 years ago

Add improved nectdf internal library src

YM

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