ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/eplus_idf.c
Revision: 2.3
Committed: Sun Feb 9 02:18:16 2014 UTC (10 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.2: +21 -10 lines
Log Message:
Fixed bug in comment reader and added idf_getfield() call

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: eplus_idf.c,v 2.2 2014/02/01 02:13:24 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 parameter with empty field list (comment optional) */
24 IDF_PARAMETER *
25 idf_newparam(IDF_LOADED *idf, const char *pname, const char *comm,
26 IDF_PARAMETER *prev)
27 {
28 LUENT *pent;
29 IDF_PARAMETER *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 parameter 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_PARAMETER *)malloc(sizeof(IDF_PARAMETER)+strlen(comm));
44 if (pnew == NULL)
45 return(NULL);
46 strcpy(pnew->rem, comm);
47 pnew->flist = NULL;
48 pnew->pname = pent->key; /* add to table */
49 pnew->pnext = (IDF_PARAMETER *)pent->data;
50 pent->data = (char *)pnew;
51 pnew->dnext = NULL; /* add to file list */
52 if (prev != NULL || (prev = idf->plast) != NULL) {
53 pnew->dnext = prev->dnext;
54 if (prev == idf->plast)
55 idf->plast = pnew;
56 }
57 if (idf->pfirst == NULL)
58 idf->pfirst = idf->plast = pnew;
59 else
60 prev->dnext = pnew;
61 return(pnew);
62 }
63
64 /* Add a field to the given parameter and follow with the given text */
65 int
66 idf_addfield(IDF_PARAMETER *param, const char *fval, const char *comm)
67 {
68 int fnum = 1; /* returned argument number */
69 IDF_FIELD *fnew, *flast;
70 char *cp;
71
72 if ((param == NULL) | (fval == NULL))
73 return(0);
74 if (comm == NULL) comm = "";
75 fnew = (IDF_FIELD *)malloc(sizeof(IDF_FIELD)+strlen(fval)+strlen(comm));
76 if (fnew == NULL)
77 return(0);
78 fnew->next = NULL;
79 cp = fnew->arg; /* copy argument and comments */
80 while ((*cp++ = *fval++))
81 ;
82 fnew->rem = cp;
83 while ((*cp++ = *comm++))
84 ;
85 /* add to parameter's field list */
86 if ((flast = param->flist) != NULL) {
87 ++fnum;
88 while (flast->next != NULL) {
89 flast = flast->next;
90 ++fnum;
91 }
92 }
93 if (flast == NULL)
94 param->flist = fnew;
95 else
96 flast->next = fnew;
97 return(fnum);
98 }
99
100 /* Retrieve the indexed field from parameter (first field index is 1) */
101 IDF_FIELD *
102 idf_getfield(IDF_PARAMETER *param, int fn)
103 {
104 IDF_FIELD *fld;
105
106 if ((param == NULL) | (fn <= 0))
107 return(NULL);
108 fld = param->flist;
109 while ((--fn > 0) & (fld != NULL))
110 fld = fld->next;
111 return(fld);
112 }
113
114 /* Delete the specified parameter from loaded IDF */
115 int
116 idf_delparam(IDF_LOADED *idf, IDF_PARAMETER *param)
117 {
118 LUENT *pent;
119 IDF_PARAMETER *pptr, *plast;
120
121 if ((idf == NULL) | (param == NULL))
122 return(0);
123 /* remove from parameter table */
124 pent = lu_find(&idf->ptab, param->pname);
125 for (plast = NULL, pptr = (IDF_PARAMETER *)pent->data;
126 pptr != NULL; plast = pptr, pptr = pptr->pnext)
127 if (pptr == param)
128 break;
129 if (pptr == NULL)
130 return(0);
131 if (plast == NULL)
132 pent->data = (char *)param->pnext;
133 else
134 plast->pnext = param->pnext;
135 /* remove from global list */
136 for (plast = NULL, pptr = idf->pfirst;
137 pptr != NULL; plast = pptr, pptr = pptr->dnext)
138 if (pptr == param)
139 break;
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 parameter struct */
155 return(1);
156 }
157
158 /* Get a named parameter list */
159 IDF_PARAMETER *
160 idf_getparam(IDF_LOADED *idf, const char *pname)
161 {
162 if ((idf == NULL) | (pname == NULL))
163 return(NULL);
164
165 return((IDF_PARAMETER *)lu_find(&idf->ptab,pname)->data);
166 }
167
168 /* Read an argument including terminating ',' or ';' -- return which */
169 static int
170 idf_read_argument(char *buf, FILE *fp, int trim)
171 {
172 int skipwhite = trim;
173 char *cp = buf;
174 int c;
175
176 while ((c = getc(fp)) != EOF && (c != ',') & (c != ';')) {
177 if (skipwhite && isspace(c))
178 continue;
179 skipwhite = 0;
180 if (cp-buf < IDF_MAXARGL-1)
181 *cp++ = c;
182 }
183 if (trim)
184 while (cp > buf && isspace(cp[-1]))
185 --cp;
186 *cp = '\0';
187 return(c);
188 }
189
190 /* Read a comment, including all white space up to next alpha character */
191 static void
192 idf_read_comment(char *buf, int len, FILE *fp)
193 {
194 int incomm = 0;
195 char *cp = buf;
196 char dummyc;
197 int c;
198
199 if ((buf == NULL) | (len <= 0)) {
200 buf = &dummyc;
201 len = 1;
202 }
203 while ((c = getc(fp)) != EOF &&
204 (isspace(c) || (incomm += (c == '!')))) {
205 if (c == '\n')
206 incomm = 0;
207 if (cp-buf < len-1)
208 *cp++ = c;
209 }
210 *cp = '\0';
211 if (c != EOF)
212 ungetc(c, fp);
213 }
214
215 /* Read a parameter and fields from an open file and add to end of list */
216 IDF_PARAMETER *
217 idf_readparam(IDF_LOADED *idf, FILE *fp)
218 {
219 char abuf[IDF_MAXARGL], cbuf[IDF_MAXLINE];
220 int delim;
221 IDF_PARAMETER *pnew;
222
223 if ((delim = idf_read_argument(abuf, fp, 1)) == EOF)
224 return(NULL);
225 idf_read_comment(cbuf, IDF_MAXLINE, fp);
226 pnew = idf_newparam(idf, abuf, cbuf, NULL);
227 while (delim == ',')
228 if ((delim = idf_read_argument(abuf, fp, 1)) != EOF) {
229 idf_read_comment(cbuf, IDF_MAXLINE, fp);
230 idf_addfield(pnew, abuf, cbuf);
231 }
232 if (delim != ';')
233 fputs("Expected ';' at end of parameter list!\n", stderr);
234 return(pnew);
235 }
236
237 /* Upper-case string hashing function */
238 static unsigned long
239 strcasehash(const char *s)
240 {
241 char strup[IDF_MAXARGL];
242 char *cdst = strup;
243
244 while ((*cdst++ = toupper(*s++)))
245 if (cdst >= strup+(sizeof(strup)-1)) {
246 *cdst = '\0';
247 break;
248 }
249 return(lu_shash(strup));
250 }
251
252 /* Initialize an IDF struct */
253 IDF_LOADED *
254 idf_create(const char *hdrcomm)
255 {
256 IDF_LOADED *idf = (IDF_LOADED *)calloc(1, sizeof(IDF_LOADED));
257
258 if (idf == NULL)
259 return(NULL);
260 idf->ptab.hashf = &strcasehash;
261 idf->ptab.keycmp = &strcasecmp;
262 idf->ptab.freek = &free;
263 lu_init(&idf->ptab, 200);
264 if (hdrcomm != NULL && *hdrcomm) {
265 idf->hrem = (char *)malloc(strlen(hdrcomm)+1);
266 if (idf->hrem != NULL)
267 strcpy(idf->hrem, hdrcomm);
268 }
269 return(idf);
270 }
271
272 /* Load an Input Data File */
273 IDF_LOADED *
274 idf_load(const char *fname)
275 {
276 char hdrcomm[300*IF_MAXLINE];
277 FILE *fp;
278 IDF_LOADED *idf;
279
280 if (fname == NULL)
281 fp = stdin; /* open file if not stdin */
282 else if ((fp = fopen(fname, "r")) == NULL)
283 return(NULL);
284 /* read header comments */
285 idf_read_comment(hdrcomm, sizeof(hdrcomm), fp);
286 idf = idf_create(hdrcomm); /* create IDF struct */
287 if (idf == NULL)
288 return(NULL);
289 /* read each parameter */
290 while (idf_readparam(idf, fp) != NULL)
291 ;
292 if (fp != stdin) /* close file if not stdin */
293 fclose(fp);
294 return(idf); /* success! */
295 }
296
297 /* Write a parameter and fields to an open file */
298 int
299 idf_writeparam(IDF_PARAMETER *param, FILE *fp)
300 {
301 IDF_FIELD *fptr;
302
303 if ((param == NULL) | (fp == NULL))
304 return(0);
305 fputs(param->pname, fp);
306 fputc(',', fp);
307 fputs(param->rem, fp);
308 for (fptr = param->flist; fptr != NULL; fptr = fptr->next) {
309 fputs(fptr->arg, fp);
310 fputc((fptr->next==NULL ? ';' : ','), fp);
311 fputs(fptr->rem, fp);
312 }
313 return(!ferror(fp));
314 }
315
316 /* Write out an Input Data File */
317 int
318 idf_write(IDF_LOADED *idf, const char *fname)
319 {
320 FILE *fp;
321 IDF_PARAMETER *pptr;
322
323 if (idf == NULL)
324 return(0);
325 if (fname == NULL)
326 fp = stdout; /* open file if not stdout */
327 else if ((fp = fopen(fname, "w")) == NULL)
328 return(0);
329 fputs(idf->hrem, fp); /* write header then parameters */
330 for (pptr = idf->pfirst; pptr != NULL; pptr = pptr->dnext)
331 if (!idf_writeparam(pptr, fp)) {
332 fclose(fp);
333 return(0);
334 }
335 if (fp == stdout) /* flush/close file & check status */
336 return(fflush(fp) == 0);
337 return(fclose(fp) == 0);
338 }
339
340 /* Free a loaded IDF */
341 void
342 idf_free(IDF_LOADED *idf)
343 {
344 if (idf == NULL)
345 return;
346 if (idf->hrem != NULL)
347 free(idf->hrem);
348 while (idf->pfirst != NULL)
349 idf_delparam(idf, idf->pfirst);
350 lu_done(&idf->ptab);
351 }