1 #include <assert.h>
2 #include <limits.h>
3
4 #include "dmemory.h"
5 #include "cdi.h"
6 #include "cdi_int.h"
7 #include "resource_handle.h"
8 #include "resource_unpack.h"
9 #include "namespace.h"
10 #include "serialize.h"
11 #include "institution.h"
12
13
14 typedef struct
15 {
16 int self;
17 int used;
18 int center;
19 int subcenter;
20 char *name;
21 char *longname;
22 }
23 institute_t;
24
25
26 static int instituteCompareKernel(institute_t *ip1, institute_t *ip2);
27 static void instituteDestroyP(institute_t *instituteptr);
28 static void institutePrintP(institute_t *instituteptr, FILE * fp);
29 static int instituteGetPackSize(institute_t *instituteptr, void *context);
30 static void institutePackP ( void * instituteptr, void *buf, int size, int *position, void *context );
31 static int instituteTxCode ( void );
32
33 static const resOps instituteOps = {
34 (int (*)(void *, void *))instituteCompareKernel,
35 (void (*)(void *))instituteDestroyP,
36 (void (*)(void *, FILE *))institutePrintP,
37 (int (*)(void *, void *))instituteGetPackSize,
38 institutePackP,
39 instituteTxCode
40 };
41
42 static
instituteDefaultValue(institute_t * instituteptr)43 void instituteDefaultValue(institute_t *instituteptr)
44 {
45 instituteptr->self = CDI_UNDEFID;
46 instituteptr->used = 0;
47 instituteptr->center = CDI_UNDEFID;
48 instituteptr->subcenter = CDI_UNDEFID;
49 instituteptr->name = NULL;
50 instituteptr->longname = NULL;
51 }
52
instituteDefaultEntries(void)53 void instituteDefaultEntries(void)
54 {
55 cdiResH resH[]
56 = { institutDef( 98, 0, "ECMWF", "European Centre for Medium-Range Weather Forecasts"),
57 institutDef(252, 1, "MPIMET", "Max Planck Institute for Meteorology"),
58 institutDef( 98, 232, "MPIMET", "Max Planck Institute for Meteorology"),
59 institutDef( 98, 255, "MPIMET", "Max-Planck-Institute for Meteorology"),
60 institutDef( 78, 255, "DWD", "Deutscher Wetterdienst"),
61 institutDef( 78, 0, "DWD", "Deutscher Wetterdienst"),
62 institutDef(215, 255, "MCH", "MeteoSwiss"),
63 institutDef( 7, 0, "NCEP", "National Centers for Environmental Prediction"),
64 institutDef( 7, 1, "NCEP", "National Centers for Environmental Prediction"),
65 institutDef( 60, 0, "NCAR", "National Center for Atmospheric Research"),
66 institutDef( 74, 0, "METOFFICE", "U.K. Met Office"),
67 institutDef( 97, 0, "ESA", "European Space Agency"),
68 institutDef( 99, 0, "KNMI", "Royal Netherlands Meteorological Institute"),
69 institutDef( 80, 0, "CNMC", "Reparto per la Meteorologia, Rome (REMET)"),
70 // institutDef( 0, 0, "IPSL", "IPSL (Institut Pierre Simon Laplace, Paris, France)");
71 };
72
73 const size_t n = sizeof(resH)/sizeof(*resH);
74 for (size_t i = 0; i < n ; i++ )
75 reshSetStatus(resH[i], &instituteOps, RESH_IN_USE);
76 }
77
78
79 static int
instituteCompareKernel(institute_t * ip1,institute_t * ip2)80 instituteCompareKernel(institute_t *ip1, institute_t *ip2)
81 {
82 int differ = 0;
83
84 if ( ip1->name )
85 {
86 if ( ip1->center > 0 && ip2->center != ip1->center ) differ = 1;
87 if ( ip1->subcenter > 0 && ip2->subcenter != ip1->subcenter ) differ = 1;
88
89 if ( !differ )
90 {
91 if ( ip2->name )
92 {
93 const size_t len1 = strlen(ip1->name);
94 const size_t len2 = strlen(ip2->name);
95 if ( (len1 != len2) || memcmp(ip2->name, ip1->name, len2) ) differ = 1;
96 }
97 }
98 }
99 else if ( ip1->longname )
100 {
101 if ( ip2->longname )
102 {
103 const size_t len1 = strlen(ip1->longname);
104 const size_t len2 = strlen(ip2->longname);
105 if ( (len1 != len2) || memcmp(ip2->longname, ip1->longname, len2) ) differ = 1;
106 }
107 }
108 else
109 {
110 if ( !( ip2->center == ip1->center &&
111 ip2->subcenter == ip1->subcenter )) differ = 1;
112 if (ip1->subcenter > 0 && ip1->subcenter != 255 && ip2->subcenter != ip1->subcenter) differ = 1;
113 }
114
115 return differ;
116 }
117
118
119 struct instLoc
120 {
121 institute_t *ip;
122 int id;
123 };
124
125 static enum cdiApplyRet
findInstitute(int id,void * res,void * data)126 findInstitute(int id, void *res, void *data)
127 {
128 institute_t *ip1 = ((struct instLoc *)data)->ip;
129 institute_t *ip2 = (institute_t*) res;
130 if (ip2->used && !instituteCompareKernel(ip1, ip2))
131 {
132 ((struct instLoc *)data)->id = id;
133 return CDI_APPLY_STOP;
134 }
135 else
136 return CDI_APPLY_GO_ON;
137 }
138
139
institutInq(int center,int subcenter,const char * name,const char * longname)140 int institutInq(int center, int subcenter, const char *name, const char *longname)
141 {
142 institute_t ip_ref;
143 ip_ref.self = CDI_UNDEFID;
144 ip_ref.used = 0;
145 ip_ref.center = center;
146 ip_ref.subcenter = subcenter;
147 ip_ref.name = (name && name[0]) ? (char *)name : NULL;
148 ip_ref.longname = (longname && longname[0]) ? (char *)longname : NULL;
149
150 struct instLoc state = { .ip = &ip_ref, .id = CDI_UNDEFID };
151 cdiResHFilterApply(&instituteOps, findInstitute, &state);
152
153 return state.id;
154 }
155
156 static
instituteNewEntry(cdiResH resH,int center,int subcenter,const char * name,const char * longname)157 institute_t *instituteNewEntry(cdiResH resH, int center, int subcenter,
158 const char *name, const char *longname)
159 {
160 institute_t *instituteptr = (institute_t*) Malloc(sizeof(institute_t));
161 instituteDefaultValue(instituteptr);
162 if (resH == CDI_UNDEFID)
163 instituteptr->self = reshPut(instituteptr, &instituteOps);
164 else
165 {
166 instituteptr->self = resH;
167 reshReplace(resH, instituteptr, &instituteOps);
168 }
169 instituteptr->used = 1;
170 instituteptr->center = center;
171 instituteptr->subcenter = subcenter;
172 if ( name && *name )
173 instituteptr->name = strdupx(name);
174 if (longname && *longname)
175 instituteptr->longname = strdupx(longname);
176 return instituteptr;
177 }
178
179
institutDef(int center,int subcenter,const char * name,const char * longname)180 int institutDef(int center, int subcenter, const char *name, const char *longname)
181 {
182 institute_t *instituteptr = instituteNewEntry(CDI_UNDEFID, center, subcenter, name, longname);
183 return instituteptr->self;
184 }
185
186
institutInqCenter(int instID)187 int institutInqCenter(int instID)
188 {
189 institute_t * instituteptr = NULL;
190
191 if ( instID != CDI_UNDEFID )
192 instituteptr = ( institute_t * ) reshGetVal ( instID, &instituteOps );
193
194 return instituteptr ? instituteptr->center : CDI_UNDEFID;
195 }
196
197
institutInqSubcenter(int instID)198 int institutInqSubcenter(int instID)
199 {
200 institute_t * instituteptr = NULL;
201
202 if ( instID != CDI_UNDEFID )
203 instituteptr = ( institute_t * ) reshGetVal ( instID, &instituteOps );
204
205 return instituteptr ? instituteptr->subcenter: CDI_UNDEFID;
206 }
207
208
institutInqNamePtr(int instID)209 const char *institutInqNamePtr(int instID)
210 {
211 institute_t * instituteptr = NULL;
212
213 if ( instID != CDI_UNDEFID )
214 instituteptr = ( institute_t * ) reshGetVal ( instID, &instituteOps );
215
216 return instituteptr ? instituteptr->name : NULL;
217 }
218
219
institutInqLongnamePtr(int instID)220 const char *institutInqLongnamePtr(int instID)
221 {
222 institute_t * instituteptr = NULL;
223
224 if ( instID != CDI_UNDEFID )
225 instituteptr = ( institute_t * ) reshGetVal ( instID, &instituteOps );
226
227 return instituteptr ? instituteptr->longname : NULL;
228 }
229
230 static enum cdiApplyRet
activeInstitutes(int id,void * res,void * data)231 activeInstitutes(int id, void *res, void *data)
232 {
233 (void)id;
234 if (res && ((institute_t *)res)->used)
235 ++(*(int *)data);
236 return CDI_APPLY_GO_ON;
237 }
238
institutInqNumber(void)239 int institutInqNumber(void)
240 {
241 int instNum = 0;
242
243 cdiResHFilterApply(&instituteOps, activeInstitutes, &instNum);
244 return instNum;
245 }
246
247
248 static void
instituteDestroyP(institute_t * instituteptr)249 instituteDestroyP(institute_t *instituteptr)
250 {
251 xassert(instituteptr);
252
253 int instituteID = instituteptr->self;
254 Free(instituteptr->name);
255 Free(instituteptr->longname);
256 reshRemove(instituteID, &instituteOps);
257 Free(instituteptr);
258 }
259
260
institutePrintP(institute_t * ip,FILE * fp)261 static void institutePrintP(institute_t *ip, FILE * fp )
262 {
263 if (ip)
264 fprintf(fp, "#\n"
265 "# instituteID %d\n"
266 "#\n"
267 "self = %d\n"
268 "used = %d\n"
269 "center = %d\n"
270 "subcenter = %d\n"
271 "name = %s\n"
272 "longname = %s\n",
273 ip->self, ip->self, ip->used, ip->center, ip->subcenter,
274 ip->name ? ip->name : "NN",
275 ip->longname ? ip->longname : "NN");
276 }
277
278
279 static int
instituteTxCode(void)280 instituteTxCode ( void )
281 {
282 return INSTITUTE;
283 }
284
285 enum {
286 institute_nints = 5,
287 };
288
instituteGetPackSize(institute_t * ip,void * context)289 static int instituteGetPackSize(institute_t *ip, void *context)
290 {
291 size_t namelen = strlen(ip->name), longnamelen = strlen(ip->longname);
292 xassert(namelen < INT_MAX && longnamelen < INT_MAX);
293 size_t txsize = (size_t)serializeGetSize(institute_nints, CDI_DATATYPE_INT, context)
294 + (size_t)serializeGetSize((int)namelen + 1, CDI_DATATYPE_TXT, context)
295 + (size_t)serializeGetSize((int)longnamelen + 1, CDI_DATATYPE_TXT, context);
296 xassert(txsize <= INT_MAX);
297 return (int)txsize;
298 }
299
institutePackP(void * instituteptr,void * buf,int size,int * position,void * context)300 static void institutePackP(void * instituteptr, void *buf, int size, int *position, void *context)
301 {
302 institute_t *p = (institute_t*) instituteptr;
303 int tempbuf[institute_nints];
304 tempbuf[0] = p->self;
305 tempbuf[1] = p->center;
306 tempbuf[2] = p->subcenter;
307 tempbuf[3] = (int)strlen(p->name) + 1;
308 tempbuf[4] = (int)strlen(p->longname) + 1;
309 serializePack(tempbuf, institute_nints, CDI_DATATYPE_INT, buf, size, position, context);
310 serializePack(p->name, tempbuf[3], CDI_DATATYPE_TXT, buf, size, position, context);
311 serializePack(p->longname, tempbuf[4], CDI_DATATYPE_TXT, buf, size, position, context);
312 }
313
instituteUnpack(void * buf,int size,int * position,int originNamespace,void * context,int force_id)314 int instituteUnpack(void *buf, int size, int *position, int originNamespace,
315 void *context, int force_id)
316 {
317 int tempbuf[institute_nints];
318 int instituteID;
319 serializeUnpack(buf, size, position, tempbuf, institute_nints, CDI_DATATYPE_INT, context);
320 char *name = (char *) Malloc((size_t)tempbuf[3] + (size_t)tempbuf[4]);
321 char *longname = name + tempbuf[3];
322 serializeUnpack(buf, size, position, name, tempbuf[3], CDI_DATATYPE_TXT, context);
323 serializeUnpack(buf, size, position, longname, tempbuf[4], CDI_DATATYPE_TXT, context);
324 int targetID = namespaceAdaptKey(tempbuf[0], originNamespace);
325 institute_t *ip = instituteNewEntry(force_id?targetID:CDI_UNDEFID,
326 tempbuf[1], tempbuf[2], name, longname);
327 instituteID = ip->self;
328 xassert(!force_id || instituteID == targetID);
329 Free(name);
330 reshSetStatus(instituteID, &instituteOps,
331 reshGetStatus(instituteID, &instituteOps) & ~RESH_SYNC_BIT);
332 return instituteID;
333 }
334
335 /*
336 * Local Variables:
337 * c-file-style: "Java"
338 * c-basic-offset: 2
339 * indent-tabs-mode: nil
340 * show-trailing-whitespace: t
341 * require-trailing-newline: t
342 * End:
343 */
344