ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/eplus_idf.c
Revision: 2.2
Committed: Sat Feb 1 02:13:24 2014 UTC (10 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.1: +20 -5 lines
Log Message:
Made sure parameter names are case-insensitive in lookups

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: eplus_idf.c,v 2.1 2014/02/01 01:28:43 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 /* Delete the specified parameter from loaded IDF */
101 int
102 idf_delparam(IDF_LOADED *idf, IDF_PARAMETER *param)
103 {
104 LUENT *pent;
105 IDF_PARAMETER *pptr, *plast;
106
107 if ((idf == NULL) | (param == NULL))
108 return(0);
109 /* remove from parameter table */
110 pent = lu_find(&idf->ptab, param->pname);
111 for (plast = NULL, pptr = (IDF_PARAMETER *)pent->data;
112 pptr != NULL; plast = pptr, pptr = pptr->pnext)
113 if (pptr == param)
114 break;
115 if (pptr == NULL)
116 return(0);
117 if (plast == NULL)
118 pent->data = (char *)param->pnext;
119 else
120 plast->pnext = param->pnext;
121 /* remove from global list */
122 for (plast = NULL, pptr = idf->pfirst;
123 pptr != NULL; plast = pptr, pptr = pptr->dnext)
124 if (pptr == param)
125 break;
126 if (pptr == NULL)
127 return(0);
128 if (plast == NULL)
129 idf->pfirst = param->dnext;
130 else
131 plast->dnext = param->dnext;
132 if (idf->plast == param)
133 idf->plast = plast;
134 /* free field list */
135 while (param->flist != NULL) {
136 IDF_FIELD *fdel = param->flist;
137 param->flist = fdel->next;
138 free(fdel);
139 }
140 free(param); /* free parameter struct */
141 return(1);
142 }
143
144 /* Get a named parameter list */
145 IDF_PARAMETER *
146 idf_getparam(IDF_LOADED *idf, const char *pname)
147 {
148 if ((idf == NULL) | (pname == NULL))
149 return(NULL);
150
151 return((IDF_PARAMETER *)lu_find(&idf->ptab,pname)->data);
152 }
153
154 /* Read an argument including terminating ',' or ';' -- return which */
155 static int
156 idf_read_argument(char *buf, FILE *fp, int trim)
157 {
158 int skipwhite = trim;
159 char *cp = buf;
160 int c;
161
162 while ((c = getc(fp)) != EOF && (c != ',') & (c != ';')) {
163 if (skipwhite && isspace(c))
164 continue;
165 skipwhite = 0;
166 if (cp-buf < IDF_MAXARGL-1)
167 *cp++ = c;
168 }
169 if (trim)
170 while (cp > buf && isspace(cp[-1]))
171 --cp;
172 *cp = '\0';
173 return(c);
174 }
175
176 /* Read a comment, including all white space up to next alpha character */
177 static void
178 idf_read_comment(char *buf, int len, FILE *fp)
179 {
180 int incomm = 0;
181 char *cp = buf;
182 char dummyc;
183 int c;
184
185 if ((buf == NULL) | (len <= 0)) {
186 buf = &dummyc;
187 len = 1;
188 }
189 while ((c = getc(fp)) != EOF && isspace(c) | incomm) {
190 if (c == '!')
191 ++incomm;
192 else if (c == '\n')
193 incomm = 0;
194 if (cp-buf < len-1)
195 *cp++ = c;
196 }
197 *cp = '\0';
198 if (c != EOF)
199 ungetc(c, fp);
200 }
201
202 /* Read a parameter and fields from an open file and add to end of list */
203 IDF_PARAMETER *
204 idf_readparam(IDF_LOADED *idf, FILE *fp)
205 {
206 char abuf[IDF_MAXARGL], cbuf[IDF_MAXLINE];
207 int delim;
208 IDF_PARAMETER *pnew;
209
210 if ((delim = idf_read_argument(abuf, fp, 1)) == EOF)
211 return(NULL);
212 idf_read_comment(cbuf, IDF_MAXLINE, fp);
213 pnew = idf_newparam(idf, abuf, cbuf, NULL);
214 while (delim == ',')
215 if ((delim = idf_read_argument(abuf, fp, 1)) != EOF) {
216 idf_read_comment(cbuf, IDF_MAXLINE, fp);
217 idf_addfield(pnew, abuf, cbuf);
218 }
219 if (delim != ';')
220 fprintf(stderr, "Expected ';' at end of parameter list\n");
221 return(pnew);
222 }
223
224 /* Upper-case string hashing function */
225 static unsigned long
226 strcasehash(const char *s)
227 {
228 char strup[IDF_MAXARGL];
229 char *cdst = strup;
230
231 while ((*cdst++ = toupper(*s++)))
232 if (cdst >= strup+(sizeof(strup)-1)) {
233 *cdst = '\0';
234 break;
235 }
236 return(lu_shash(strup));
237 }
238
239 /* Initialize an IDF struct */
240 IDF_LOADED *
241 idf_create(const char *hdrcomm)
242 {
243 IDF_LOADED *idf = (IDF_LOADED *)calloc(1, sizeof(IDF_LOADED));
244
245 if (idf == NULL)
246 return(NULL);
247 idf->ptab.hashf = &strcasehash;
248 idf->ptab.keycmp = &strcasecmp;
249 idf->ptab.freek = &free;
250 lu_init(&idf->ptab, 200);
251 if (hdrcomm != NULL && *hdrcomm) {
252 idf->hrem = (char *)malloc(strlen(hdrcomm)+1);
253 if (idf->hrem != NULL)
254 strcpy(idf->hrem, hdrcomm);
255 }
256 return(idf);
257 }
258
259 /* Load an Input Data File */
260 IDF_LOADED *
261 idf_load(const char *fname)
262 {
263 char *hdrcomm;
264 FILE *fp;
265 IDF_LOADED *idf;
266
267 if (fname == NULL)
268 fp = stdin; /* open file if not stdin */
269 else if ((fp = fopen(fname, "r")) == NULL)
270 return(NULL);
271 /* read header comments */
272 hdrcomm = (char *)malloc(100*IDF_MAXLINE);
273 idf_read_comment(hdrcomm, 100*IDF_MAXLINE, fp);
274 idf = idf_create(hdrcomm); /* create IDF struct */
275 free(hdrcomm);
276 if (idf == NULL)
277 return(NULL);
278 /* read each parameter */
279 while (idf_readparam(idf, fp) != NULL)
280 ;
281 if (fp != stdin) /* close file if not stdin */
282 fclose(fp);
283 return(idf); /* success! */
284 }
285
286 /* Write a parameter and fields to an open file */
287 int
288 idf_writeparam(IDF_PARAMETER *param, FILE *fp)
289 {
290 IDF_FIELD *fptr;
291
292 if ((param == NULL) | (fp == NULL))
293 return(0);
294 fputs(param->pname, fp);
295 fputc(',', fp);
296 fputs(param->rem, fp);
297 for (fptr = param->flist; fptr != NULL; fptr = fptr->next) {
298 fputs(fptr->arg, fp);
299 fputc((fptr->next==NULL ? ';' : ','), fp);
300 fputs(fptr->rem, fp);
301 }
302 return(!ferror(fp));
303 }
304
305 /* Write out an Input Data File */
306 int
307 idf_write(IDF_LOADED *idf, const char *fname)
308 {
309 FILE *fp;
310 IDF_PARAMETER *pptr;
311
312 if (idf == NULL)
313 return(0);
314 if (fname == NULL)
315 fp = stdout; /* open file if not stdout */
316 else if ((fp = fopen(fname, "w")) == NULL)
317 return(0);
318 fputs(idf->hrem, fp); /* write header then parameters */
319 for (pptr = idf->pfirst; pptr != NULL; pptr = pptr->dnext)
320 if (!idf_writeparam(pptr, fp)) {
321 fclose(fp);
322 return(0);
323 }
324 if (fp == stdout) /* flush/close file & check status */
325 return(fflush(fp) == 0);
326 return(fclose(fp) == 0);
327 }
328
329 /* Free a loaded IDF */
330 void
331 idf_free(IDF_LOADED *idf)
332 {
333 if (idf == NULL)
334 return;
335 if (idf->hrem != NULL)
336 free(idf->hrem);
337 while (idf->pfirst != NULL)
338 idf_delparam(idf, idf->pfirst);
339 lu_done(&idf->ptab);
340 }