source: npl/mediabox/lcdproc_edwin/src/old/cfg.c @ c5c522c

gcc484ntopperl-5.22
Last change on this file since c5c522c was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 8 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100644
File size: 8.6 KB
Line 
1/***********************************************
2**
3** cfg.c v0.01
4**
5** Generic config file handler
6** (c) Gareth Watts 1998
7**     gareth@omnipotent.net
8**
9** Alpha code as of 980601
10*/
11
12#include <stddef.h>
13#include <stdio.h>
14#include <errno.h>
15#include <stdlib.h>
16#include <string.h>
17
18#include "cfg.h"
19
20
21
22/**************************
23*  PUBLIC METHODS
24*/
25
26void cfg_free(cfg *self) {
27        struct cfg_node *ptr, *nextptr;
28        int i;
29
30        for(i=0;i<CFG_HASHSIZE;i++) {
31                if(self->cfg_hash[i]) {
32                        for(ptr=self->cfg_hash[i];ptr;ptr=nextptr) {
33                                nextptr=ptr->next;
34                                free(ptr->optname);
35                                free(ptr->optvalue);
36                                free(ptr);
37                        }
38                }
39        }
40        free(self->filename);
41        free(self->lasterror);
42        self->_queuefree(self);
43        free(self);
44}
45
46
47#define CFG_BUZSIZE 4096
48int cfg_openfile(cfg *self,char *fn,int mode) {
49        char buffer[CFG_BUZSIZE];
50        char *keyname,*keyvalue;
51        int  comment;
52        FILE *fh;
53
54        self->filename=strdup(fn);
55        fh=fopen(fn,"r");
56        if (!fh) {
57                if (mode==CFG_READONLY) {
58                        self->lasterror=strdup(strerror(errno));
59                        return(1);
60                }
61                return(0); /* read/write but file not found */
62        }
63
64        // READ AND PARSE FILE HERE
65        while(feof(fh)==0) {
66                fgets(buffer,CFG_BUZSIZE-1,fh);
67                if (strlen(buffer)) {
68                        if (buffer[strlen(buffer)-1]=='\n') {
69                                buffer[strlen(buffer)-1]='\0';
70                        }
71                        if (buffer[0]=='#') {
72                                comment=1;
73                        } else {
74                                comment=0;
75                        }
76                } else { comment=1;}
77                if (!comment&&self->_splitline(self,buffer,&keyname,&keyvalue)) {
78                        return(1); /* memory error or somesuch */
79                }
80                if (!comment&&keyname&&keyvalue) {
81                        if (!self->_lookup(self,keyname)) {
82                                self->_insert(self,keyname,keyvalue,0);
83                        }
84                }
85                       
86        }
87        return(0);
88}       
89
90
91char *cfg_getstring(cfg *self,char *keyname) {
92        return(self->_lookup(self,keyname));
93}
94
95
96int cfg_getint(cfg *self,char *keyname) {
97        int result=0;
98        char *keydata;
99
100        keydata=self->_lookup(self,keyname);
101        if (keydata)
102                sscanf(keydata,"%d",&result);
103        return(result);
104}
105
106
107/* This is virtually useless due to rounding errors */
108float cfg_getfloat(cfg *self,char *keyname) {
109        float result=0.0;
110        char *keydata;
111
112        keydata=self->_lookup(self,keyname);
113        if (keydata)
114                sscanf(keydata,"%f",&result);
115        return(result);
116}
117
118
119int cfg_setstring(cfg *self,char *keyname, char *keyvalue) {
120        return(self->_set(self,keyname,keyvalue));
121}
122
123
124int cfg_setint(cfg *self,char *keyname, int keyvalue) {
125        char buffer[200];
126
127        sprintf(buffer,"%d",keyvalue);
128        return(self->_set(self,keyname,buffer));
129}
130
131int cfg_setfloat(cfg *self,char *keyname, float keyvalue) {
132        char buffer[200];
133
134        sprintf(buffer,"%f",keyvalue);
135        return(self->_set(self,keyname,buffer));
136}
137
138int cfg_flush(cfg *self) {
139        if (self->filemode==CFG_READONLY) {
140                return(0);
141        } else {
142                return(self->_flush(self));
143        }
144}
145
146
147int cfg_autoflush(cfg *self,int aflush) {
148        self->aflush=(aflush>0);
149        return(0);
150}
151
152
153
154/**************************
155*  PRIVATE/INTERNAL METHODS
156*/
157
158int _cfg_init(cfg *self) {
159        memset(self->cfg_hash,0,sizeof(self->cfg_hash));
160        return(0);
161}
162
163
164int _cfg_queuepush(cfg *self, struct cfg_node *node) {
165        struct cfg_queuenode *ptr;
166
167        ptr=(struct cfg_queuenode *)calloc(1,sizeof(struct cfg_queuenode));
168        if (!ptr) return(1);
169        ptr->ref=node;
170        if (self->cfg_newsttail) {
171                self->cfg_newsttail->next=ptr;
172                self->cfg_newsttail=ptr;
173        } else {
174                self->cfg_newsthead=self->cfg_newsttail=ptr;
175        }
176        return(0);
177}
178
179
180struct cfg_queuenode *_cfg_queuenext(cfg *self, struct cfg_queuenode *last) {
181        if (last) {
182                return(last->next);
183        } else {
184                return(self->cfg_newsthead);
185        }
186}
187
188
189int _cfg_queuefree(cfg *self) {
190        struct cfg_queuenode *ptr,*next;
191
192        for(ptr=self->cfg_newsthead;ptr;ptr=next) {
193                next=ptr->next;
194                free(ptr);
195        }
196        self->cfg_newsthead=self->cfg_newsttail=NULL;
197        return(0);
198}
199
200
201int _cfg_getkey(cfg *self,char *str) {
202        unsigned int total;
203        int i=1;
204        int j=0;
205
206        total=(*str)-0x20;
207        str++;
208        while(*str) {
209                total+=i*((*str)-0x20);
210                str++;
211                i+=(33+j++)*j;
212        }
213        return(total % CFG_HASHSIZE); 
214}
215
216
217int _cfg_insert(cfg *self,char *keyname, char *keyval,int dirty) {
218        int key,match=0;
219        struct cfg_node *ptr,*nextptr;;
220
221        key=self->_getkey(self,keyname);
222        if (!self->cfg_hash[key]) {
223                self->cfg_hash[key]=(struct cfg_node *)calloc(1,sizeof(struct cfg_node));
224                if (!(self->cfg_hash[key]->optname=strdup(keyname))) {
225                        return(1);
226                }
227                if (!(self->cfg_hash[key]->optvalue=strdup(keyval))) {
228                        return(1);
229                }
230                if (dirty) self->_queuepush(self,self->cfg_hash[key]);
231        } else {
232                for(nextptr=self->cfg_hash[key];(nextptr)&&(!match);nextptr=ptr->next) {
233                        ptr=nextptr;
234                        match=(strcasecmp(ptr->optname,keyname)==0);
235                }
236
237                if (match) { /* node already exists / overwrite */
238                        free(ptr->optvalue);
239                        ptr->dirty=dirty;
240                } else { /* new node */
241                        ptr->next=(struct cfg_node *)calloc(1,sizeof(struct cfg_node));
242                        ptr=ptr->next;
243                        if (!(ptr->optname=strdup(keyname))) {
244                                return(1);
245                        }
246                        if (dirty) self->_queuepush(self,ptr);
247                }
248                if (!(ptr->optvalue=strdup(keyval))) {
249                        return(1);
250                }
251        }
252        return(0);
253}
254
255
256struct cfg_node *_cfg_getnode(cfg *self, char *keyname) {
257        int key;
258        struct cfg_node *ptr,*next;
259        int match=0;
260
261        key=self->_getkey(self,keyname);
262        if (!self->cfg_hash[key])
263                return(NULL);
264        for(next=self->cfg_hash[key];next&&!match;next=ptr->next) {
265                ptr=next;
266                match=(strcasecmp(ptr->optname,keyname)==0);
267        }
268        if (match)
269                return(ptr);
270        return(NULL);
271}
272
273
274char *_cfg_lookup(cfg *self,char *keyname) {
275        struct cfg_node *ptr;
276
277        ptr=self->_getnode(self,keyname);
278        if (ptr)
279                return(ptr->optvalue);
280        else
281                return(NULL);
282}
283
284
285int _cfg_cleardirty(cfg *self,struct cfg_node *ptr) {
286        ptr->dirty=0;
287        return(0);
288}
289
290
291int _cfg_set(cfg *self,char *keyname,char *keyvalue) {
292        int key;
293
294        key=self->_getkey(self,keyname);
295        if (self->_insert(self,keyname,keyvalue,1)!=0) {
296                return(1); /* error */
297        }
298        if (self->aflush) {
299                return(self->flush(self));
300        }
301        return(0);
302}
303
304int _cfg_splitline(cfg *self,char *src, char **f, char **s) {
305        char *brkpoint;
306        int offset,slen,fpos;
307        static char first[4096],second[4096];
308
309        *f=*s=NULL;
310        if ((brkpoint=strchr(src,'='))==NULL) {
311                return(0);
312        }
313        offset=brkpoint-src;
314        slen=strlen(src);
315        if (offset==slen-1) {
316                return(0);
317        }
318        if (offset>4094) {offset=4094;}
319       
320        memset(first,0,4096);
321        memset(second,0,4096);
322        strncpy(first,src,offset);
323        strncpy(second,brkpoint+1,4095);
324       
325        fpos=strlen(first)-1;
326        while((first[fpos]==' ')&&fpos) {
327                first[fpos]='\0';
328                fpos--;
329        }
330        *f=first;
331        for(*s=second;(**s)&&(**s==' ');(*s)++);
332        return(0);
333}
334
335
336
337#define CFGF_MAXLINES 50000
338#define CFGF_LINELEN 4096
339int _cfg_realflush(cfg *self) {
340        char *outbuf[CFGF_MAXLINES];
341        char buffer[CFGF_LINELEN];
342        int linenum=0;
343        int comment,i;
344        char *keyname,*keyvalue;
345        struct cfg_queuenode *qptr;
346        struct cfg_node *ptr;
347        FILE *fh;
348        char *rd;
349
350        fh=fopen(self->filename,"r");
351        if (fh) {
352                while((feof(fh)==0)&&(linenum<CFGF_MAXLINES)) {
353                        rd=fgets(buffer,CFGF_LINELEN-1,fh);
354                        if (rd&&strlen(buffer)) {
355                                if (buffer[strlen(buffer)-1]=='\n') {
356                                        buffer[strlen(buffer)-1]='\0';
357                                }
358                                if (buffer[0]=='#') {
359                                        comment=1;
360                                } else {
361                                        comment=0;
362                                }
363                                if (comment) {
364                                        outbuf[linenum]=strdup(buffer);
365                                } else {
366                                        if (self->_splitline(self,buffer,&keyname,&keyvalue)) {
367                                                fclose(fh);
368                                                return(1); /* memory error or somesuch */
369                                        }
370                                        if ((keyname)&&(ptr=self->_getnode(self,keyname))&&(ptr->dirty)) {
371                                                sprintf(buffer,"%s = %s",ptr->optname,ptr->optvalue);
372                                                outbuf[linenum]=strdup(buffer);
373                                                self->_cleardirty(self,ptr);
374                                        } else {
375                                                outbuf[linenum]=strdup(buffer);
376                                        }
377                                }
378                                linenum++;
379                        }
380                }
381                fclose(fh);
382        }
383        for(qptr=self->_queuenext(self,NULL);qptr;qptr=self->_queuenext(self,qptr)) {
384                sprintf(buffer,"%s=%s",qptr->ref->optname,qptr->ref->optvalue);
385                outbuf[linenum]=strdup(buffer);
386                linenum++;
387        }
388        fh=fopen(self->filename,"w");
389        if (!fh) {
390                self->lasterror=strdup(strerror(errno));
391                return(1);
392        }
393        for(i=0;i<linenum;i++) {
394                fprintf(fh,"%s\n",outbuf[i]);
395                free(outbuf[i]);
396        }
397        fclose(fh);
398        self->_queuefree(self);
399        return(0);
400}
401
402
403
404
405
406
407/*****************
408*  THE CONSTRUCTOR
409*/
410
411cfg *cfg_new() {
412        cfg *ptr;
413
414        ptr=(cfg *)calloc(1,sizeof(cfg));
415        if (!ptr) return(NULL);
416
417        ptr->getstring=cfg_getstring;
418        ptr->getint=cfg_getint;
419        ptr->getfloat=cfg_getfloat;
420        ptr->openfile=cfg_openfile;
421        ptr->setstring=cfg_setstring;
422        ptr->setint=cfg_setint;
423        ptr->setfloat=cfg_setfloat;
424        ptr->flush=cfg_flush;
425        ptr->autoflush=cfg_autoflush;
426        ptr->free=cfg_free;
427
428        ptr->_getkey=_cfg_getkey;
429        ptr->_insert=_cfg_insert;
430        ptr->_lookup=_cfg_lookup;
431        ptr->_cleardirty=_cfg_cleardirty;
432        ptr->_set=_cfg_set;
433        ptr->_splitline=_cfg_splitline;
434        ptr->_queuepush=_cfg_queuepush;
435        ptr->_queuenext=_cfg_queuenext;
436        ptr->_queuefree=_cfg_queuefree;
437        ptr->_getnode=_cfg_getnode;
438        ptr->_flush=_cfg_realflush;
439
440        if (_cfg_init(ptr)) return(NULL);
441        return(ptr);
442}
443
Note: See TracBrowser for help on using the repository browser.