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