no preallocating if there's no state file
[syren.git] / src / syren_cfg.c
blob025ecc02985df7254717acd8aad7d5bca6e8cf46
1 /*
2 Syren -- a lightweight downloader for Linux/BSD/MacOSX
3 inspired by Axel Copyright 2001-2002 Wilmer van der Gaast
4 version 0.0.6 (atomic alien)
5 coded by Ketmar // Avalon Group
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License with
18 the Debian GNU/Linux distribution in file /usr/doc/copyright/GPL;
19 if not, write to the Free Software Foundation, Inc., 59 Temple Place,
20 Suite 330, Boston, MA 02111-1307 USA
23 Syren config engine
25 #ifndef _SYREN_CFG_C
26 #define _SYREN_CFG_C
28 #include "syren_cfg.h"
31 TSyCfg *SyCfgNew (void) {
32 TSyCfg *cfg = calloc(1, sizeof(TSyCfg));
33 if (!cfg) return NULL;
34 cfg->opts = SyKVListNew();
35 if (!cfg->opts) { free(cfg); return NULL; }
36 return cfg;
40 void SyCfgFree (TSyCfg *cfg) {
41 if (cfg) { SyKVListFree(cfg->opts); free(cfg); }
45 void SyCfgClear (TSyCfg *cfg) {
46 SyKVListClear(cfg->opts);
50 static TSyKVListItem *SyCfgAddKey (TSyCfg *cfg, int ktype, const char *kname, const char *kdescr, void *var) {
51 TSyKVListItem *item;
52 char *s;
54 if (!cfg || !cfg->opts) return NULL;
55 item = SyKVListFind(cfg->opts, kname); if (item) return NULL;
56 s = SyStrDup(kdescr); if (!s) return NULL;
57 item = SyKVListSet(cfg->opts, kname, NULL, NULL);
58 if (!item) { free(s); return NULL; }
59 item->ustr = s;
60 item->uidata = ktype;
61 item->udata = var;
62 return item;
66 TSyResult SyCfgAddStrKey (TSyCfg *cfg, const char *kname, const char *kdescr, char **var) {
67 TSyKVListItem *item;
69 if (!cfg || !cfg->opts || !var) return SY_ERROR;
70 item = SyCfgAddKey(cfg, SY_CI_STRING, kname, kdescr, var);
71 if (!item) return SY_ERROR;
72 return SY_OK;
76 TSyResult SyCfgAddBoolKey (TSyCfg *cfg, const char *kname, const char *kdescr, TSyBool *var) {
77 TSyKVListItem *item;
79 if (!cfg || !cfg->opts || !(var)) return SY_ERROR;
80 item = SyCfgAddKey(cfg, SY_CI_BOOL, kname, kdescr, var);
81 if (!item) return SY_ERROR;
82 return SY_OK;
86 TSyResult SyCfgAddIntKey (TSyCfg *cfg, const char *kname, const char *kdescr, int *var) {
87 TSyKVListItem *item;
89 if (!cfg || !cfg->opts || !var) return SY_ERROR;
90 item = SyCfgAddKey(cfg, SY_CI_INT, kname, kdescr, var);
91 if (!item) return SY_ERROR;
92 return SY_OK;
96 int SyCfgGetKeyType (const TSyCfg *cfg, const char *kname) {
97 TSyKVListItem *item;
99 if (!cfg || !cfg->opts) return SY_CI_ERROR;
100 item = SyKVListFind(cfg->opts, kname);
101 if (!item) return SY_CI_ERROR;
102 return item->uidata;
106 char *SyCfgGetKeyValue (const TSyCfg *cfg, const char *kname) {
107 TSyKVListItem *item;
109 item = SyKVListFind(cfg->opts, kname);
110 if (!item) return NULL;
111 switch (item->uidata) {
112 case SY_CI_STRING:
113 return SyStrNew(*((char **)(item->udata)), -1);
114 break;
115 case SY_CI_INT:
116 return SySPrintf("%i", *((int *)(item->udata)));
117 break;
118 case SY_CI_BOOL:
119 return (*((TSyBool *)(item->udata))!=SY_FALSE)?SyStrNew("tan", -1):SyStrNew("ona", -1);
120 break;
121 default: ;
123 return NULL;
127 TSyResult SyCfgSetKeyValue (TSyCfg *cfg, const char *kname, const char *value) {
128 int n;
129 char *s, **v;
130 int *i; TSyBool *b;
131 TSyKVListItem *item;
133 item = SyKVListFind(cfg->opts, kname);
134 if (!item) return SY_ERROR;
135 if (item->uidata == SY_CI_STRING) {
136 s = SyStrNew(value, -1); if (!s) return SY_ERROR;
137 v = (char **)item->udata;
138 if (*v) free(*v);
139 *v = s;
140 } else {
141 n = SyStr2Int(value);
142 if (item->uidata == SY_CI_INT) {
143 if (n < 0) return SY_ERROR;
144 i = (int *)item->udata; *i = n;
145 } else { /* SY_CI_BOOL */
146 b = (TSyBool *)item->udata;
147 if (n >= 0) *b = n?SY_TRUE:SY_FALSE;
148 else {
149 s = SyStrNew(value, -1); if (!s) return SY_ERROR;
150 SyStrTrim(s);
151 *b = (*s && strchr("tTyYsS", *s))?SY_TRUE:SY_FALSE;
152 free(s);
156 return SY_OK;
160 TSyResult SyCfgSet (TSyCfg *cfg, const char *optline) {
161 char *s, *buf, *c, ch;
162 TSyKVListItem *item;
164 if (!cfg) return SY_ERROR;
165 if (!optline || !optline[0]) return SY_OK;
166 s = SyStrNew(optline, -1); if (!s) return SY_ERROR;
167 buf = s; SyStrTrim(s); c = s;
168 while ((unsigned char)*c > ' ' && *c != '=') c++;
169 ch = *c; *c = '\0';
170 item = SyKVListFind(cfg->opts, s);
171 if (item) {
172 if (ch) {
173 c++; while (*c && (unsigned char)*c <= ' ') c++;
174 if (*c == '=') { c++; while (*c && (unsigned char)*c <= ' ') c++; }
176 SyCfgSetKeyValue(cfg, s, c);
177 free(buf);
178 return SY_OK;
179 } else { free(buf); return SY_ERROR; }
183 TSyResult SyCfgLoad (TSyCfg *cfg, const char *filename, const TSyPrintStr *pfn) {
184 FILE *fl;
185 char s[1024];
186 int lineno = 0;
188 if (!cfg || !cfg->opts || !filename || !filename[0]) return SY_ERROR;
189 fl = fopen(filename, "r");
190 if (!fl) return SY_ERROR;
191 while (fgets(s, sizeof(s), fl)) {
192 lineno++;
193 SyStrTrim(s);
194 if (!s[0] || *s == '#' || *s == ';') continue;
195 if (SyCfgSet(cfg, s) != SY_OK) SyMessage(pfn, SY_MSG_WARNING, "unknown config option at line %i: %s", lineno, s);
197 fclose(fl);
198 return SY_OK;
202 TSyResult SyCfgSave (const TSyCfg *cfg, const char *filename, const TSyPrintStr *pfn) {
203 FILE *fl;
204 TSyKVListItem *item;
205 char *s;
207 if (!cfg || !cfg->opts || !filename || !filename[0]) return SY_ERROR;
208 fl = fopen(filename, "w");
209 if (!fl) return SY_ERROR;
210 fprintf(fl, "%s\n", "# configuration file for Syren -- a lightweight downloader for Linux/BSD/Win/MacOSX");
211 item = cfg->opts->first;
212 while (item) {
213 s = SyCfgGetKeyValue(cfg, item->key);
214 if (s) { fprintf(fl, "\n# %s\n%s = %s\n", item->ustr, item->key, s); free(s); }
215 item = item->next;
217 fclose(fl);
218 return SY_OK;
222 #endif