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