Merge branch 'master' of ssh://git.indexdata.com/home/git/pub/yaz
[yaz-moved-to-github.git] / src / zoom-opt.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2010 Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file zoom-opt.c
7  * \brief Implements ZOOM options handling
8  */
9 #include <assert.h>
10 #include "zoom-p.h"
11
12 #include <yaz/xmalloc.h>
13
14 struct ZOOM_options_entry {
15     char *name;
16     char *value;
17     int len;                  /* of `value', which may contain NULs */
18     struct ZOOM_options_entry *next;
19 };
20
21 struct ZOOM_options_p {
22     int refcount;
23     void *callback_handle;
24     ZOOM_options_callback callback_func;
25     struct ZOOM_options_entry *entries;
26     ZOOM_options parent1;
27     ZOOM_options parent2;
28 };
29
30 static void set_value(struct ZOOM_options_entry **e,
31                       const char *value, int len)
32 {
33     (*e)->value = 0;
34     (*e)->len = 0;
35     if (value)
36     {
37         (*e)->value = (char *) xmalloc(len+1);
38         memcpy((*e)->value, value, len);
39         (*e)->value[len] = '\0';
40         (*e)->len = len;
41     }
42 }
43
44 static void append_entry(struct ZOOM_options_entry **e,
45                          const char *name, const char *value, int len)
46 {
47     *e = (struct ZOOM_options_entry *) xmalloc(sizeof(**e));
48     (*e)->name = xstrdup(name);
49     set_value(e, value, len);
50     (*e)->next = 0;
51 }
52
53 ZOOM_API(ZOOM_options)
54     ZOOM_options_dup(ZOOM_options src)
55 {
56     if (!src)
57         return 0;
58     else
59     {
60         ZOOM_options dst = ZOOM_options_create();
61         struct ZOOM_options_entry *src_e = src->entries;
62         struct ZOOM_options_entry **dst_e = &dst->entries;
63         
64         while(src_e)
65         {
66             append_entry(dst_e, src_e->name, src_e->value, src_e->len);
67             dst_e = &(*dst_e)->next;
68             src_e = src_e->next;
69         }
70         dst->parent1 = ZOOM_options_dup(src->parent1);
71         dst->parent2 = ZOOM_options_dup(src->parent2);
72         return dst;
73     }
74 }
75
76 ZOOM_API(ZOOM_options)
77     ZOOM_options_create_with_parent(ZOOM_options parent)
78 {
79     return ZOOM_options_create_with_parent2(parent, 0);
80 }
81
82 ZOOM_API(ZOOM_options)
83     ZOOM_options_create(void)
84 {
85     return ZOOM_options_create_with_parent(0);
86 }
87
88
89 ZOOM_API(ZOOM_options)
90     ZOOM_options_create_with_parent2(ZOOM_options parent1,
91                                      ZOOM_options parent2)
92 {
93     ZOOM_options opt = (ZOOM_options) xmalloc(sizeof(*opt));
94
95     opt->refcount = 1;
96     opt->callback_func = 0;
97     opt->callback_handle = 0;
98     opt->entries = 0;
99     opt->parent1= parent1;
100     if (parent1)
101         (parent1->refcount)++;
102     opt->parent2= parent2;
103     if (parent2)
104         (parent2->refcount)++;
105     return opt;
106 }
107
108
109 void ZOOM_options_addref(ZOOM_options opt)
110 {
111     (opt->refcount)++;
112 }
113
114 ZOOM_API(ZOOM_options_callback)
115     ZOOM_options_set_callback (
116     ZOOM_options opt,
117     ZOOM_options_callback callback_func,
118     void *callback_handle)
119 {
120     ZOOM_options_callback callback_old;
121     
122     assert(opt);
123     callback_old = opt->callback_func;
124     opt->callback_func = callback_func;
125     opt->callback_handle = callback_handle;
126     return callback_old;
127 }
128
129 ZOOM_API(void)
130     ZOOM_options_destroy(ZOOM_options opt)
131 {
132     if (!opt)
133         return;
134     (opt->refcount)--;
135     if (opt->refcount == 0)
136     {
137         struct ZOOM_options_entry *e;
138         
139         ZOOM_options_destroy(opt->parent1);
140         ZOOM_options_destroy(opt->parent2);
141         e = opt->entries;
142         while (e)
143         {
144             struct ZOOM_options_entry *e0 = e;
145             xfree(e->name);
146             xfree(e->value);
147             e = e->next;
148             xfree(e0);
149         }
150         xfree(opt);
151     }
152 }
153
154
155 ZOOM_API(void)
156     ZOOM_options_setl(ZOOM_options opt, const char *name, const char *value,
157                       int len)
158 {
159     struct ZOOM_options_entry **e;
160
161     e = &opt->entries;
162     while (*e)
163     {
164         if (!strcmp((*e)->name, name))
165         {
166             xfree((*e)->value);
167             set_value(e, value, len);
168             return;
169         }
170         e = &(*e)->next;
171     }
172     append_entry(e, name, value, len);
173 }
174
175 ZOOM_API(void)
176     ZOOM_options_set(ZOOM_options opt, const char *name, const char *value)
177 {
178     ZOOM_options_setl(opt, name, value, value ? strlen(value): 0);
179 }
180
181 ZOOM_API(const char *)
182     ZOOM_options_getl(ZOOM_options opt, const char *name, int *lenp)
183 {
184     const char *v = 0;
185     if (!opt)
186         return 0;
187     if (opt->callback_func)
188     {
189         v = (*opt->callback_func)(opt->callback_handle, name);
190         if (v)
191             *lenp = strlen(v);
192     }
193     if (!v)
194     {
195         struct ZOOM_options_entry *e;
196         for (e = opt->entries; e; e = e->next)
197             if (!strcmp(e->name, name))
198             {
199                 v = e->value;
200                 *lenp = e->len;
201                 break;
202             }
203     }
204     if (!v)
205         v = ZOOM_options_getl(opt->parent1, name, lenp);
206     if (!v)
207         v = ZOOM_options_getl(opt->parent2, name, lenp);
208     return v;
209 }
210
211 ZOOM_API(const char *)
212     ZOOM_options_get(ZOOM_options opt, const char *name)
213 {
214     int dummy;
215     return ZOOM_options_getl(opt, name, &dummy);
216 }
217
218 ZOOM_API(int)
219     ZOOM_options_get_bool(ZOOM_options opt, const char *name, int defa)
220 {
221     const char *v = ZOOM_options_get(opt, name);
222     
223     if (!v)
224         return defa;
225     if (!strcmp(v, "1") || !strcmp(v, "T"))
226         return 1;
227     return 0;
228 }
229
230 ZOOM_API(int)
231     ZOOM_options_get_int(ZOOM_options opt, const char *name, int defa)
232 {
233     const char *v = ZOOM_options_get(opt, name);
234
235     if (!v || !*v)
236         return defa;
237     return atoi(v);
238 }
239
240 ZOOM_API(void)
241 ZOOM_options_set_int(ZOOM_options opt, const char *name, int value)
242 {
243     char s[40];
244
245     sprintf(s, "%d", value);
246     ZOOM_options_set(opt, name, s);
247 }
248 /*
249  * Local variables:
250  * c-basic-offset: 4
251  * c-file-style: "Stroustrup"
252  * indent-tabs-mode: nil
253  * End:
254  * vim: shiftwidth=4 tabstop=8 expandtab
255  */
256