1 /*********************************************************************
2  *   Copyright 1993, UCAR/Unidata
3  *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4  *   $Id$
5  *********************************************************************/
6 
7 /*
8  * utility functions to update in-memory netcdf by adding new
9  * dimensions, variables, and attributes.
10  */
11 #include <stdio.h>
12 #include <string.h>
13 
14 #include "h4config.h"
15 #ifdef H4_HAVE_NETCDF
16 #include "netcdf.h"
17 #else
18 #include "hdf4_netcdf.h"
19 #endif
20 
21 #include "testcdf.h"
22 #include "add.h"
23 #include "alloc.h"
24 #include "emalloc.h"
25 #ifdef HDF
26 #include "hdf.h"
27 #endif
28 
29 struct netcdf test;		/*
30 				 * in-memory netcdf structure, kept in sync
31 				 * with disk netcdf
32 				 */
33 
34 void
add_dim(test,idim)35 add_dim (test, idim)		/* add the dimension idim to the netcdf test */
36      struct netcdf *test;
37      struct cdfdim *idim;
38 {
39     static char pname[] = "add_dim";
40 
41     if (test->ndims >= H4_MAX_NC_DIMS) {
42 	(void)fprintf(stderr,
43 		      "%s: too many dimensions (%d)", pname, test->ndims);
44 	return;
45     }
46     test->dims[test->ndims].size = idim->size;
47     test->dims[test->ndims].name = (char *) emalloc(strlen(idim->name) + 1);
48     (void) strcpy(test->dims[test->ndims].name, idim->name);
49     if (idim->size == NC_UNLIMITED)
50       test->xdimid = test->ndims;
51     test->ndims++;
52 }
53 
54 void
add_var(test,ivar)55 add_var (test, ivar)		/* add the variable ivar to the netcdf test */
56      struct netcdf *test;
57      struct cdfvar *ivar;
58 {
59     static char pname[] = "add_var";
60     int i;
61 
62     if (test->nvars >= H4_MAX_NC_VARS) {
63 	(void)fprintf(stderr,
64 		      "%s: too many variables (%d)", pname, test->nvars);
65 	return;
66     }
67 
68     test->vars[test->nvars].name = (char *) emalloc(strlen(ivar->name) + 1);
69     (void) strcpy(test->vars[test->nvars].name, ivar->name);
70     test->vars[test->nvars].type = ivar->type;
71     test->vars[test->nvars].ndims = ivar->ndims;
72     test->vars[test->nvars].dims = (int *) emalloc(sizeof(int)*ivar->ndims);
73     for (i = 0; i < ivar->ndims; i++)
74       test->vars[test->nvars].dims[i] = ivar->dims[i];
75     test->vars[test->nvars].natts = 0;
76     test->nvars++;
77 }
78 
79 void
add_att(test,varid,iatt)80 add_att (test, varid, iatt)	/* add attribute iatt to the netcdf test */
81      struct netcdf *test;
82      int varid;			/* variable id */
83      struct cdfatt *iatt;
84 {
85     static char pname[] = "add_att";
86     int ia;			/* attribute number */
87 
88     if (test->natts >= MAX_TEST_ATTS) {
89 	(void)fprintf(stderr,
90 		      "%s: too many attributes (%d)", pname, test->natts);
91 	return;
92     }
93 
94     /* if already defined, change existing attribute and return */
95     for (ia = 0; ia < test->natts ; ia++) {
96 	if (test->atts[ia].var == varid &&
97 	    strcmp(test->atts[ia].name, iatt->name) == 0) {
98 	    test->atts[ia].type = iatt->type;
99 	    test->atts[ia].len = iatt->len;
100 	    test->atts[ia].val = iatt->val;
101 	    return;
102 	}
103     }
104     /* otherwise, add new attribute to list */
105     test->atts[test->natts].var = varid;
106     test->atts[test->natts].name = (char *) emalloc(strlen(iatt->name) + 1);
107     (void) strcpy(test->atts[test->natts].name, iatt->name);
108     test->atts[test->natts].type = iatt->type;
109     test->atts[test->natts].len = iatt->len;
110     test->atts[test->natts].val = iatt->val;
111     test->natts++;
112     if (varid == NC_GLOBAL)
113       test->ngatts++;
114     else
115       test->vars[varid].natts++;
116 }
117 
118 
119 void
add_reset(test)120 add_reset(test)			/* reset in-memory netcdf test to empty */
121      struct netcdf *test;
122 {
123     test->ndims = 0;
124     test->nvars = 0;
125     test->natts = 0;
126     test->ngatts = 0;
127     test->xdimid = -1;		/* no unlimited dimension */
128 }
129 
130 
131 void
del_att(test,varid,iatt)132 del_att (test, varid, iatt)	/* delete attribute iatt in the netcdf test */
133      struct netcdf *test;
134      int varid;			/* variable id */
135      struct cdfatt *iatt;
136 {
137     static char pname[] = "del_att";
138     int ia, ib;			/* attribute number */
139 
140     for (ia = 0; ia < test->natts ; ia++) { /* find attribute to delete */
141 	if (test->atts[ia].var == varid &&
142 	    strcmp(test->atts[ia].name, iatt->name) == 0) {
143 	    Free(test->atts[ia].name);
144             for (ib = ia+1; ib < test->natts; ib++) { /* move down */
145 		test->atts[ib-1].var =   test->atts[ib].var;
146 		test->atts[ib-1].name =  test->atts[ib].name;
147 		test->atts[ib-1].type =  test->atts[ib].type;
148 		test->atts[ib-1].len =   test->atts[ib].len;
149 		test->atts[ib-1].val =   test->atts[ib].val;
150 	    }
151 	    test->natts--;
152 	    if (varid == NC_GLOBAL)
153 	      test->ngatts--;
154 	    else
155 	      test->vars[varid].natts--;
156 	    return;
157 	}
158     }
159     /* not found */
160     (void) fprintf(stderr, "%s: no such attribute as (%s, %s)", pname,
161 		   test->vars[varid].name, iatt->name);
162 }
163 
164 void
add_data(test,varid,start,edges)165 add_data(test, varid, start, edges) /* keep max record written updated */
166      struct netcdf *test;
167      int varid;
168      long start[];
169      long edges[];
170 {
171     if (varid != test->xdimid)	/* not a record variable */
172       return;
173     if (start[0] + edges[0] > test->dims[test->xdimid].size)
174       test->dims[test->xdimid].size = start[0] + edges[0];
175 }
176 
177 
178 void
errvar(cdfp,varp)179 errvar(cdfp, varp)
180      struct netcdf *cdfp;
181      struct cdfvar *varp;
182 {
183     const char *types;
184     int id;
185 
186     switch (varp->type) {
187       case NC_BYTE:
188 	types = "NC_BYTE";
189 	break;
190       case NC_CHAR:
191 	types = "NC_CHAR";
192 	break;
193       case NC_SHORT:
194 	types = "NC_SHORT";
195 	break;
196       case NC_LONG:
197 	types = "NC_LONG";
198 	break;
199       case NC_FLOAT:
200 	types = "NC_FLOAT";
201 	break;
202       case NC_DOUBLE:
203 	types = "NC_DOUBLE	";
204 	break;
205       default:
206 	types = "UNKNOWN";
207 	break;
208     }
209 
210     (void) fprintf(stderr,"  name=%s  type=%s  dims=(",
211 		   varp->name, types);
212     for (id = 0; id < varp->ndims; id++)
213       (void) fprintf(stderr, "%d%s",
214 		     (int)cdfp->dims[varp->dims[id]].size,
215 		     id < varp->ndims - 1 ? ", " : "");
216     (void) fprintf(stderr, ")\n");
217 }
218