ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/eplus_idf.c
Revision: 2.12
Committed: Wed Mar 5 19:49:39 2014 UTC (10 years ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, rad5R2, rad4R2P2, rad5R0, rad5R1, rad4R2, rad4R2P1, rad5R3, HEAD
Changes since 2.11: +13 -4 lines
Log Message:
Changed idf_free() to make it faster

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: eplus_idf.c,v 2.11 2014/03/04 17:06:42 greg Exp $";
3 #endif
4 /*
5 * eplus_idf.c
6 *
7 * EnergyPlus Input Data File i/o routines
8 *
9 * Created by Greg Ward on 1/31/14.
10 */
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <ctype.h>
15 #include <stdlib.h>
16 #include "eplus_idf.h"
17
18 #ifdef getc_unlocked /* avoid horrendous overhead of flockfile */
19 #undef getc
20 #define getc getc_unlocked
21 #endif
22
23 /* Create a new object with empty field list (comment optional) */
24 IDF_OBJECT *
25 idf_newobject(IDF_LOADED *idf, const char *pname, const char *comm,
26 IDF_OBJECT *prev)
27 {
28 LUENT *pent;
29 IDF_OBJECT *pnew;
30
31 if ((idf == NULL) | (pname == NULL))
32 return(NULL);
33 if (comm == NULL) comm = "";
34 pent = lu_find(&idf->ptab, pname);
35 if (pent == NULL)
36 return(NULL);
37 if (pent->key == NULL) { /* new object name/type? */
38 pent->key = (char *)malloc(strlen(pname)+1);
39 if (pent->key == NULL)
40 return(NULL);
41 strcpy(pent->key, pname);
42 }
43 pnew = (IDF_OBJECT *)malloc(sizeof(IDF_OBJECT)+strlen(comm));
44 if (pnew == NULL)
45 return(NULL);
46 strcpy(pnew->rem, comm);
47 pnew->nfield = 0;
48 pnew->flist = NULL;
49 pnew->pname = pent->key; /* add to table */
50 pnew->pnext = (IDF_OBJECT *)pent->data;
51 pent->data = (char *)pnew;
52 pnew->dnext = NULL; /* add to file list */
53 if (prev != NULL || (prev = idf->plast) != NULL) {
54 pnew->dnext = prev->dnext;
55 if (prev == idf->plast)
56 idf->plast = pnew;
57 }
58 if (idf->pfirst == NULL)
59 idf->pfirst = idf->plast = pnew;
60 else
61 prev->dnext = pnew;
62 return(pnew);
63 }
64
65 /* Add a field to the given object and follow with the given text */
66 int
67 idf_addfield(IDF_OBJECT *param, const char *fval, const char *comm)
68 {
69 int fnum = 1; /* returned argument number */
70 IDF_FIELD *fnew, *flast;
71 char *cp;
72
73 if ((param == NULL) | (fval == NULL))
74 return(0);
75 if (comm == NULL) comm = "";
76 fnew = (IDF_FIELD *)malloc(sizeof(IDF_FIELD)+strlen(fval)+strlen(comm));
77 if (fnew == NULL)
78 return(0);
79 fnew->next = NULL;
80 cp = fnew->val; /* copy value and comments */
81 while ((*cp++ = *fval++))
82 ;
83 fnew->rem = cp;
84 while ((*cp++ = *comm++))
85 ;
86 /* add to object's field list */
87 if ((flast = param->flist) != NULL) {
88 ++fnum;
89 while (flast->next != NULL) {
90 flast = flast->next;
91 ++fnum;
92 }
93 }
94 if (flast == NULL)
95 param->flist = fnew;
96 else
97 flast->next = fnew;
98 param->nfield++;
99 return(fnum);
100 }
101
102 /* Retrieve the indexed field from object (first field index is 1) */
103 IDF_FIELD *
104 idf_getfield(IDF_OBJECT *param, int fn)
105 {
106 IDF_FIELD *fld;
107
108 if ((param == NULL) | (fn <= 0))
109 return(NULL);
110 fld = param->flist;
111 while ((--fn > 0) & (fld != NULL))
112 fld = fld->next;
113 return(fld);
114 }
115
116 /* Delete the specified object from loaded IDF */
117 int
118 idf_delobject(IDF_LOADED *idf, IDF_OBJECT *param)
119 {
120 LUENT *pent;
121 IDF_OBJECT *pptr, *plast;
122
123 if ((idf == NULL) | (param == NULL))
124 return(0);
125 /* remove from object table */
126 pent = lu_find(&idf->ptab, param->pname);
127 for (plast = NULL, pptr = (IDF_OBJECT *)pent->data;
128 pptr != NULL; plast = pptr, pptr = pptr->pnext)
129 if (pptr == param)
130 break;
131 if (pptr == NULL)
132 return(0);
133 if (plast == NULL)
134 pent->data = (char *)param->pnext;
135 else
136 plast->pnext = param->pnext;
137 /* remove from global list */
138 for (plast = NULL, pptr = idf->pfirst;
139 pptr != param; plast = pptr, pptr = pptr->dnext)
140 if (pptr == NULL)
141 return(0);
142 if (plast == NULL)
143 idf->pfirst = param->dnext;
144 else
145 plast->dnext = param->dnext;
146 if (idf->plast == param)
147 idf->plast = plast;
148 /* free field list */
149 while (param->flist != NULL) {
150 IDF_FIELD *fdel = param->flist;
151 param->flist = fdel->next;
152 free(fdel);
153 }
154 free(param); /* free object struct */
155 return(1);
156 }
157
158 /* Move the specified object to the given position in the IDF */
159 int
160 idf_movobject(IDF_LOADED *idf, IDF_OBJECT *param, IDF_OBJECT *prev)
161 {
162 IDF_OBJECT *pptr, *plast;
163
164 if ((idf == NULL) | (param == NULL))
165 return(0);
166 /* quick check if already there */
167 if (param == (prev==NULL ? idf->pfirst : prev->dnext))
168 return(1);
169 /* find in IDF list, first*/
170 for (plast = NULL, pptr = idf->pfirst;
171 pptr != param; plast = pptr, pptr = pptr->dnext)
172 if (pptr == NULL)
173 return(0);
174 if (plast == NULL)
175 idf->pfirst = param->dnext;
176 else
177 plast->dnext = param->dnext;
178 if (idf->plast == param)
179 idf->plast = plast;
180 if (prev == NULL) { /* means they want it at beginning */
181 param->dnext = idf->pfirst;
182 idf->pfirst = param;
183 } else {
184 param->dnext = prev->dnext;
185 prev->dnext = param;
186 }
187 return(1);
188 }
189
190 /* Get a named object list */
191 IDF_OBJECT *
192 idf_getobject(IDF_LOADED *idf, const char *pname)
193 {
194 if ((idf == NULL) | (pname == NULL))
195 return(NULL);
196
197 return((IDF_OBJECT *)lu_find(&idf->ptab,pname)->data);
198 }
199
200 /* Read an argument including terminating ',' or ';' -- return which */
201 static int
202 idf_read_argument(char *buf, FILE *fp, int trim)
203 {
204 int skipwhite = trim;
205 char *cp = buf;
206 int c;
207
208 while ((c = getc(fp)) != EOF && (c != ',') & (c != ';')) {
209 if (skipwhite && isspace(c))
210 continue;
211 skipwhite = 0;
212 if (cp-buf < IDF_MAXARGL-1)
213 *cp++ = c;
214 }
215 if (trim)
216 while (cp > buf && isspace(cp[-1]))
217 --cp;
218 *cp = '\0';
219 return(c);
220 }
221
222 /* Read a comment, including all white space up to next alpha character */
223 static void
224 idf_read_comment(char *buf, int len, FILE *fp)
225 {
226 int incomm = 0;
227 char *cp = buf;
228 char dummys[2];
229 int c;
230
231 if ((buf == NULL) | (len <= 0)) {
232 buf = dummys;
233 len = sizeof(dummys);
234 }
235 while ((c = getc(fp)) != EOF &&
236 (isspace(c) || (incomm += (c == '!')))) {
237 if (c == '\n')
238 incomm = 0;
239 if (cp-buf < len-2)
240 *cp++ = c;
241 else if (cp-buf == len-2)
242 *cp++ = '\n';
243 }
244 *cp = '\0';
245 if (c != EOF)
246 ungetc(c, fp);
247 }
248
249 /* Read a object and fields from an open file and add to end of list */
250 IDF_OBJECT *
251 idf_readobject(IDF_LOADED *idf, FILE *fp)
252 {
253 char abuf[IDF_MAXARGL], cbuf[100*IDF_MAXLINE];
254 int delim;
255 IDF_OBJECT *pnew;
256
257 if ((delim = idf_read_argument(abuf, fp, 1)) == EOF)
258 return(NULL);
259 idf_read_comment(cbuf, sizeof(cbuf), fp);
260 pnew = idf_newobject(idf, abuf, cbuf, NULL);
261 while (delim == ',')
262 if ((delim = idf_read_argument(abuf, fp, 1)) != EOF) {
263 idf_read_comment(cbuf, sizeof(cbuf), fp);
264 idf_addfield(pnew, abuf, cbuf);
265 }
266 if (delim != ';')
267 fputs("Expected ';' at end of object list!\n", stderr);
268 return(pnew);
269 }
270
271 /* Upper-case string hashing function */
272 static unsigned long
273 strcasehash(const char *s)
274 {
275 char strup[IDF_MAXARGL];
276 char *cdst = strup;
277
278 while ((*cdst++ = toupper(*s++)))
279 if (cdst >= strup+(sizeof(strup)-1)) {
280 *cdst = '\0';
281 break;
282 }
283 return(lu_shash(strup));
284 }
285
286 /* Initialize an IDF struct */
287 IDF_LOADED *
288 idf_create(const char *hdrcomm)
289 {
290 IDF_LOADED *idf = (IDF_LOADED *)calloc(1, sizeof(IDF_LOADED));
291
292 if (idf == NULL)
293 return(NULL);
294 idf->ptab.hashf = &strcasehash;
295 idf->ptab.keycmp = &strcasecmp;
296 idf->ptab.freek = &free;
297 lu_init(&idf->ptab, 200);
298 if (hdrcomm != NULL && *hdrcomm) {
299 idf->hrem = (char *)malloc(strlen(hdrcomm)+1);
300 if (idf->hrem != NULL)
301 strcpy(idf->hrem, hdrcomm);
302 }
303 return(idf);
304 }
305
306 /* Add comment(s) to header */
307 int
308 idf_add2hdr(IDF_LOADED *idf, const char *hdrcomm)
309 {
310 int olen, len;
311
312 if ((idf == NULL) | (hdrcomm == NULL))
313 return(0);
314 len = strlen(hdrcomm);
315 if (!len)
316 return(0);
317 if (idf->hrem == NULL)
318 olen = 0;
319 else
320 olen = strlen(idf->hrem);
321 if (olen)
322 idf->hrem = (char *)realloc(idf->hrem, olen+len+1);
323 else
324 idf->hrem = (char *)malloc(len+1);
325 if (idf->hrem == NULL)
326 return(0);
327 strcpy(idf->hrem+olen, hdrcomm);
328 return(1);
329 }
330
331 /* Load an Input Data File */
332 IDF_LOADED *
333 idf_load(const char *fname)
334 {
335 char hdrcomm[256*IDF_MAXLINE];
336 FILE *fp;
337 IDF_LOADED *idf;
338
339 if (fname == NULL)
340 fp = stdin; /* open file if not stdin */
341 else if ((fp = fopen(fname, "r")) == NULL)
342 return(NULL);
343 /* read header comments */
344 idf_read_comment(hdrcomm, sizeof(hdrcomm), fp);
345 idf = idf_create(hdrcomm); /* create IDF struct */
346 if (idf == NULL)
347 return(NULL);
348 /* read each object */
349 while (idf_readobject(idf, fp) != NULL)
350 ;
351 if (fp != stdin) /* close file if not stdin */
352 fclose(fp);
353 return(idf); /* success! */
354 }
355
356 /* Check string for end-of-line */
357 static int
358 idf_hasEOL(const char *s)
359 {
360 while (*s)
361 if (*s++ == '\n')
362 return(1);
363 return(0);
364 }
365
366 /* Write a object and fields to an open file */
367 int
368 idf_writeparam(IDF_OBJECT *param, FILE *fp, int incl_comm)
369 {
370 IDF_FIELD *fptr;
371
372 if ((param == NULL) | (fp == NULL))
373 return(0);
374 fputs(param->pname, fp);
375 fputc(',', fp);
376 if (incl_comm)
377 fputs(param->rem, fp);
378 else
379 fputc('\n', fp);
380 for (fptr = param->flist; fptr != NULL; fptr = fptr->next) {
381 if (!incl_comm)
382 fputs(" ", fp);
383 fputs(fptr->val, fp);
384 if (fptr->next == NULL) {
385 fputc(';', fp);
386 if (incl_comm && !idf_hasEOL(fptr->rem))
387 fputc('\n', fp);
388 } else
389 fputc(',', fp);
390 if (incl_comm)
391 fputs(fptr->rem, fp);
392 else
393 fputc('\n', fp);
394 }
395 if (!incl_comm)
396 fputc('\n', fp);
397 return(!ferror(fp));
398 }
399
400 /* Write out an Input Data File */
401 int
402 idf_write(IDF_LOADED *idf, const char *fname, int incl_comm)
403 {
404 FILE *fp;
405 IDF_OBJECT *pptr;
406
407 if (idf == NULL)
408 return(0);
409 if (fname == NULL)
410 fp = stdout; /* open file if not stdout */
411 else if ((fp = fopen(fname, "w")) == NULL)
412 return(0);
413 if (incl_comm)
414 fputs(idf->hrem, fp); /* write header then parameters */
415 for (pptr = idf->pfirst; pptr != NULL; pptr = pptr->dnext)
416 if (!idf_writeparam(pptr, fp, incl_comm>0)) {
417 fclose(fp);
418 return(0);
419 }
420 if (fp == stdout) /* flush/close file & check status */
421 return(fflush(fp) == 0);
422 return(fclose(fp) == 0);
423 }
424
425 /* Free a loaded IDF */
426 void
427 idf_free(IDF_LOADED *idf)
428 {
429 if (idf == NULL)
430 return;
431 while (idf->pfirst != NULL) {
432 IDF_OBJECT *pdel = idf->pfirst;
433 idf->pfirst = pdel->dnext;
434 while (pdel->flist != NULL) {
435 IDF_FIELD *fdel = pdel->flist;
436 pdel->flist = fdel->next;
437 free(fdel);
438 }
439 free(pdel);
440 }
441 lu_done(&idf->ptab);
442 if (idf->hrem != NULL)
443 free(idf->hrem);
444 free(idf);
445 }