summaryrefslogtreecommitdiffabout
path: root/libical/src/libicalss/icalset.c
Unidiff
Diffstat (limited to 'libical/src/libicalss/icalset.c') (more/less context) (show whitespace changes)
-rw-r--r--libical/src/libicalss/icalset.c510
1 files changed, 318 insertions, 192 deletions
diff --git a/libical/src/libicalss/icalset.c b/libical/src/libicalss/icalset.c
index 2120609..0ad2269 100644
--- a/libical/src/libicalss/icalset.c
+++ b/libical/src/libicalss/icalset.c
@@ -20,348 +20,474 @@
20 This program is free software; you can redistribute it and/or modify 20 This program is free software; you can redistribute it and/or modify
21 it under the terms of either: 21 it under the terms of either:
22 22
23 The LGPL as published by the Free Software Foundation, version 23 The LGPL as published by the Free Software Foundation, version
24 2.1, available at: http://www.fsf.org/copyleft/lesser.html 24 2.1, available at: http://www.fsf.org/copyleft/lesser.html
25 25
26 Or: 26 Or:
27 27
28 The Mozilla Public License Version 1.0. You may obtain a copy of 28 The Mozilla Public License Version 1.0. You may obtain a copy of
29 the License at http://www.mozilla.org/MPL/ 29 the License at http://www.mozilla.org/MPL/
30 30
31 The Original Code is eric. The Initial Developer of the Original 31 The Original Code is eric. The Initial Developer of the Original
32 Code is Eric Busboom 32 Code is Eric Busboom
33 33
34 34
35======================================================================*/ 35======================================================================*/
36 36
37#include "ical.h" 37#include "ical.h"
38#include "icalset.h" 38#include "icalset.h"
39#include "icalfileset.h" 39#include "icalfileset.h"
40#include "icalfilesetimpl.h" 40#include "icalfilesetimpl.h"
41#include "icaldirset.h" 41#include "icaldirset.h"
42#include "icaldirsetimpl.h" 42#include "icaldirsetimpl.h"
43#include <stdlib.h> 43#include <stdlib.h>
44/*#include "icalheapset.h"*/ 44#include <string.h>
45/*#include "icalmysqlset.h"*/ 45#include <errno.h>
46 46
47#define ICALSET_ID "set " 47#ifdef WITH_BDB4
48 48#include "icalbdbset.h"
49struct icalset_fp { 49#include "icalbdbsetimpl.h"
50 void (*free)(icalset* set); 50#endif
51 const char* (*path)(icalset* set); 51
52 void (*mark)(icalset* set); 52/* #define _DLOPEN_TEST */
53 icalerrorenum (*commit)(icalset* set); 53#ifdef _DLOPEN_TEST
54 icalerrorenum (*add_component)(icalset* set, icalcomponent* comp); 54#include <sys/types.h>
55 icalerrorenum (*remove_component)(icalset* set, icalcomponent* comp); 55#include <dlfcn.h>
56 int (*count_components)(icalset* set, 56#include <dirent.h>
57 icalcomponent_kind kind); 57#endif
58 icalerrorenum (*select)(icalset* set, icalcomponent* gauge); 58
59 void (*clear)(icalset* set); 59static icalset icalset_dirset_init = {
60 icalcomponent* (*fetch)(icalset* set, const char* uid); 60 ICAL_DIR_SET,
61 icalcomponent* (*fetch_match)(icalset* set, icalcomponent *comp); 61 sizeof(icaldirset),
62 int (*has_uid)(icalset* set, const char* uid); 62 NULL,
63 icalerrorenum (*modify)(icalset* set, icalcomponent *old, 63 icaldirset_init,
64 icalcomponent *new);
65 icalcomponent* (*get_current_component)(icalset* set);
66 icalcomponent* (*get_first_component)(icalset* set);
67 icalcomponent* (*get_next_component)(icalset* set);
68};
69
70struct icalset_fp icalset_dirset_fp = {
71 icaldirset_free, 64 icaldirset_free,
72 icaldirset_path, 65 icaldirset_path,
73 icaldirset_mark, 66 icaldirset_mark,
74 icaldirset_commit, 67 icaldirset_commit,
75 icaldirset_add_component, 68 icaldirset_add_component,
76 icaldirset_remove_component, 69 icaldirset_remove_component,
77 icaldirset_count_components, 70 icaldirset_count_components,
78 icaldirset_select, 71 icaldirset_select,
79 icaldirset_clear, 72 icaldirset_clear,
80 icaldirset_fetch, 73 icaldirset_fetch,
81 icaldirset_fetch_match, 74 icaldirset_fetch_match,
82 icaldirset_has_uid, 75 icaldirset_has_uid,
83 icaldirset_modify, 76 icaldirset_modify,
84 icaldirset_get_current_component, 77 icaldirset_get_current_component,
85 icaldirset_get_first_component, 78 icaldirset_get_first_component,
86 icaldirset_get_next_component 79 icaldirset_get_next_component,
80 icaldirset_begin_component,
81 icaldirsetiter_to_next,
82 icaldirsetiter_to_prior
87}; 83};
88 84
89 85
90struct icalset_fp icalset_fileset_fp = { 86static icalset icalset_fileset_init = {
87 ICAL_FILE_SET,
88 sizeof(icalfileset),
89 NULL,
90 icalfileset_init,
91 icalfileset_free, 91 icalfileset_free,
92 icalfileset_path, 92 icalfileset_path,
93 icalfileset_mark, 93 icalfileset_mark,
94 icalfileset_commit, 94 icalfileset_commit,
95 icalfileset_add_component, 95 icalfileset_add_component,
96 icalfileset_remove_component, 96 icalfileset_remove_component,
97 icalfileset_count_components, 97 icalfileset_count_components,
98 icalfileset_select, 98 icalfileset_select,
99 icalfileset_clear, 99 icalfileset_clear,
100 icalfileset_fetch, 100 icalfileset_fetch,
101 icalfileset_fetch_match, 101 icalfileset_fetch_match,
102 icalfileset_has_uid, 102 icalfileset_has_uid,
103 icalfileset_modify, 103 icalfileset_modify,
104 icalfileset_get_current_component, 104 icalfileset_get_current_component,
105 icalfileset_get_first_component, 105 icalfileset_get_first_component,
106 icalfileset_get_next_component 106 icalfileset_get_next_component,
107 icalfileset_begin_component,
108 icalfilesetiter_to_next,
109 NULL
107}; 110};
108 111
109struct icalset_impl { 112#ifdef WITH_BDB4
113static icalset icalset_bdbset_init = {
114 ICAL_BDB_SET,
115 sizeof(icalbdbset),
116 NULL,
117 icalbdbset_init,
118 icalbdbset_free,
119 icalbdbset_path,
120 icalbdbset_mark,
121 icalbdbset_commit,
122 icalbdbset_add_component,
123 icalbdbset_remove_component,
124 icalbdbset_count_components,
125 icalbdbset_select,
126 icalbdbset_clear,
127 icalbdbset_fetch,
128 icalbdbset_fetch_match,
129 icalbdbset_has_uid,
130 icalbdbset_modify,
131 icalbdbset_get_current_component,
132 icalbdbset_get_first_component,
133 icalbdbset_get_next_component,
134 icalbdbset_begin_component,
135 icalbdbsetiter_to_next,
136 NULL
137};
138#endif
110 139
111 char id[5]; /* "set " */ 140#ifdef _DLOPEN_TEST
141 static inticalset_init_done = 0;
142static pvl_list icalset_kinds = 0;
112 143
113 void *derived_impl; 144typedef icalset *(*fptr)(void);
114 struct icalset_fp *fp;
115};
116 145
117/* Figure out what was actually passed in as the set. This could be a 146/**
118 set or and of the derived types such as dirset or fileset. Note 147 * Try to load the file and register any icalset found within.
119 this routine returns a value, not a reference, to avoid memory 148 */
120 leaks in the methods */ 149static int load(const char *file) {
121struct icalset_impl icalset_get_impl(icalset* set)
122{
123 struct icalset_impl impl;
124
125 memset(&impl,0,sizeof(impl));
126 icalerror_check_arg_re( (set!=0),"set",impl);
127
128 if(strcmp((char*)set,ICALSET_ID)==0) {
129 /* It is actually a set, so just sent the reference back out. */
130 return *(struct icalset_impl*)set;
131 } else if(strcmp((char*)set,ICALFILESET_ID)==0) {
132 /* Make a new set from the fileset */
133 impl.fp = &icalset_fileset_fp;
134 impl.derived_impl = set;
135 strcpy(impl.id,ICALFILESET_ID);/* HACK. Is this necessary? */
136 return impl;
137 } else if(strcmp((char*)set,ICALDIRSET_ID)==0) {
138 /* Make a new set from the dirset */
139 impl.fp = &icalset_dirset_fp;
140 impl.derived_impl = set;
141 strcpy(impl.id,ICALDIRSET_ID);/* HACK. Is this necessary? */
142 return impl;
143 } else {
144 /* The type of set is unknown, so throw an error */
145 icalerror_assert((0),"Unknown set type");
146 return impl;
147 }
148}
149
150
151struct icalset_impl* icalset_new_impl()
152{
153 150
154 struct icalset_impl* impl; 151 void *modh;
152 fptr inith;
153 icalset *icalset_init_ptr;
155 154
156 if ( ( impl = (struct icalset_impl*) 155 if ((modh = dlopen(file, RTLD_NOW)) == 0) {
157 malloc(sizeof(struct icalset_impl))) == 0) { 156 perror("dlopen");
158 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
159 return 0; 157 return 0;
160 } 158 }
161 159
162 strcpy(impl->id,ICALSET_ID); 160 if ((inith = (fptr)dlsym(modh, "InitModule")) == 0) {
161 perror("dlsym");
162 return 0;
163 }
163 164
164 impl->derived_impl = 0; 165 while ((icalset_init_ptr = ((inith)())) != 0) {
165 impl->fp = 0; 166 pvl_push(icalset_kinds, &icalset_init_ptr);
167 }
166 168
167 return impl; 169 return 1;
168} 170}
169 171
170struct icalset_impl* icalset_new_file_from_ref(icalfileset *fset) 172/**
171{ 173 * Look in the given directory for files called mod_*.o and try to
172 struct icalset_impl *impl = icalset_new_impl(); 174 * load them.
175 */
176int icalset_loaddir(const char *path) {
177 DIR *d;
178 struct dirent *dp;
179 char buf[PATH_MAX],
180 *bufptr;
181 int tot = 0;
182
183 strcpy(buf, path);
184 bufptr = buf + strlen(buf);
173 185
174 icalerror_check_arg_rz( (fset!=0),"fset"); 186 if (*(bufptr-1) != '/')
187 *bufptr++ = '/';
175 188
176 if(impl == 0){ 189 if ((d = opendir(path)) == 0) {
177 free(impl); 190 perror("opendir");
178 return 0; 191 return 0;
179 } 192 }
180 193
181 impl->derived_impl = fset; 194 while ((dp = readdir(d)) != 0) {
195 if (strncmp(dp->d_name, "mod_", 4)) continue;
182 196
183 if (impl->derived_impl == 0){ 197 strcpy(bufptr, dp->d_name);
184 free(impl);
185 return 0;
186 }
187 198
188 impl->fp = &icalset_fileset_fp; 199 load(buf);
200 tot++;
201 }
202 (void)closedir(d);
189 203
190 return (struct icalset_impl*)impl; 204 return 1;
191} 205}
192 206
193icalset* icalset_new_file(const char* path) 207int icalset_register_class(icalset *set);
194{
195 icalfileset *fset = icalfileset_new(path);
196 208
197 if(fset == 0){ 209static void icalset_init(void) {
198 return 0; 210 assert(icalset_kinds == 0);
211 icalset_kinds = pvl_newlist();
212
213 pvl_push(icalset_kinds, &icalset_fileset_init);
214 pvl_push(icalset_kinds, &icalset_dirset_init);
215#ifdef WITH_BDB4
216 pvl_push(icalset_kinds, &icalset_bdb4set_init);
217#endif
218
219#ifdef EXT_PATH
220 icalset_loaddir(EXT_PATH);
221#endif
222
223 icalset_init_done++;
199 } 224 }
200 225
201 return (icalset*)icalset_new_file_from_ref(fset); 226int icalset_register_class(icalset *set) {
227
228 if (!icalset_init_done)
229 icalset_init();
230
231 pvl_push(icalset_kinds, set);
232 return 1;
202} 233}
203 234
204icalset* icalset_new_dir_from_ref(icaldirset *dset) 235#endif
205{
206 236
207 struct icalset_impl *impl = icalset_new_impl(); 237icalset* icalset_new(icalset_kind kind, const char* dsn, void* options) {
238 icalset *data = NULL;
239 icalset *ret = NULL;
208 240
209 icalerror_check_arg_rz( (dset!=0),"dset"); 241#ifdef _DLOPEN_TEST
242 pvl_eleme;
243 icalset *impl;
210 244
211 if(impl == 0){ 245 if (!icalset_init_done)
212 return 0; 246 icalset_init();
213 }
214 247
215 impl->derived_impl = dset; 248 for(e = pvl_head(icalset_kinds); e!=0; e = pvl_next(e)) {
249 impl = (icalset*)pvl_data(e);
250 if (impl->kind == kind)
251 break;
252 }
253 if (e == 0) {
254 icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
255 return(NULL);
256 }
216 257
217 if (impl->derived_impl == 0){ 258 data = (icalset*)malloc(impl->size);
218 free(impl); 259 if (data == 0) {
260 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
261 errno = ENOMEM;
219 return 0; 262 return 0;
220 } 263 }
221 264
222 impl->fp = &icalset_dirset_fp; 265 /* The first member of the derived class must be an icalset. */
266 memset(data,0,impl->size);
267 /* *data = *impl; */
268 memcpy(data, impl, sizeof(icalset));
223 269
224 return impl; 270 data->dsn = strdup(dsn);
271#else
272 switch(kind) {
273 case ICAL_FILE_SET:
274 data = (icalset*) malloc(sizeof(icalfileset));
275 if (data == 0) {
276 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
277 errno = ENOMEM;
278 return 0;
279 }
280 memset(data,0,sizeof(icalfileset));
281 *data = icalset_fileset_init;
282 break;
283 case ICAL_DIR_SET:
284 data = (icalset*) malloc(sizeof(icaldirset));
285 if (data == 0) {
286 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
287 errno = ENOMEM;
288 return 0;
289 }
290 memset(data,0,sizeof(icaldirset));
291 *data = icalset_dirset_init;
292 break;
293#ifdef WITH_BDB4
294 case ICAL_BDB_SET:
295 data = (icalset*) malloc(sizeof(icalbdbset));
296 if (data == 0) {
297 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
298 errno = ENOMEM;
299 return 0;
225} 300}
301 memset(data,0,sizeof(icalbdbset));
302 *data = icalset_bdbset_init;
303 break;
304#endif
226 305
227icalset* icalset_new_dir(const char* path) 306 default:
228{ 307 icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
229 icaldirset *dset = icaldirset_new(path); 308 /** unimplemented **/
309 return(NULL);
310 }
230 311
231 if(dset == 0){ 312 if ( data == 0) {
313 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
232 return 0; 314 return 0;
233 } 315 }
316 data->kind = kind;
317 data->dsn = strdup(dsn);
318#endif
319
320 /** call the implementation specific initializer **/
321 if ((ret = data->init(data, dsn, options)) == NULL)
322 icalset_free(data);
234 323
235 return icalset_new_dir_from_ref(dset); 324 return ret;
236} 325}
237 326
238icalset* icalset_new_heap(void) 327icalset* icalset_new_file(const char* path)
239{ 328{
240 struct icalset_impl *impl = icalset_new_impl(); 329 return icalset_new(ICAL_FILE_SET, path, NULL);
241 330}
242 331
243 if(impl == 0){ 332icalset* icalset_new_file_writer(const char* path)
244 free(impl); 333{
245 return 0; 334 return icalfileset_new_writer(path);
246 } 335 }
247 336
248 return 0; 337icalset* icalset_new_file_reader(const char* path)
338{
339 return icalfileset_new_reader(path);
249} 340}
250 341
251icalset* icalset_new_mysql(const char* path) 342
343icalset* icalset_new_dir(const char* path)
252{ 344{
253 struct icalset_impl *impl = icalset_new_impl(); 345 return icalset_new(ICAL_DIR_SET, path, NULL);
346}
254 347
255 if(impl == 0){ 348icalset* icalset_new_dir_writer(const char* path)
256 free(impl); 349{
257 return 0; 350 return icaldirset_new_writer(path);
258 } 351 }
259 352
260 return 0; 353icalset* icalset_new_dir_reader(const char* path)
354{
355 return icaldirset_new_reader(path);
261} 356}
262 357
358
359
360/* Functions for built-in methods */
361
362/**
363 * free memory associated with this icalset
364 * automatically calls the implementation specific free routine
365 */
366
263void icalset_free(icalset* set) 367void icalset_free(icalset* set)
264{ 368{
265 struct icalset_impl impl = icalset_get_impl(set); 369 if (set->free)
266 (*(impl.fp->free))(impl.derived_impl); 370 set->free(set);
371
372 if (set->dsn)
373 free(set->dsn);
267 374
268 if(strcmp((char*)set,ICALSET_ID)) {
269 free(set); 375 free(set);
270 } 376 }
377
378
379const char* icalset_path(icalset* set) {
380 return set->path(set);
271} 381}
272 382
273const char* icalset_path(icalset* set) 383void icalset_mark(icalset* set) {
274{ 384 set->mark(set);
275 struct icalset_impl impl = icalset_get_impl(set);
276 return (*(impl.fp->path))(impl.derived_impl);
277} 385}
278 386
279void icalset_mark(icalset* set) 387icalerrorenum icalset_commit(icalset* set) {
280{ 388 return set->commit(set);
281 struct icalset_impl impl = icalset_get_impl(set);
282 (*(impl.fp->mark))(impl.derived_impl);
283} 389}
284 390
285icalerrorenum icalset_commit(icalset* set) 391icalerrorenum icalset_add_component(icalset* set, icalcomponent* comp) {
286{ 392 return set->add_component(set,comp);
287 struct icalset_impl impl = icalset_get_impl(set);
288 return (*(impl.fp->commit))(impl.derived_impl);
289} 393}
290 394
291icalerrorenum icalset_add_component(icalset* set, icalcomponent* comp) 395icalerrorenum icalset_remove_component(icalset* set, icalcomponent* comp) {
292{ 396 return set->remove_component(set,comp);
293 struct icalset_impl impl = icalset_get_impl(set);
294 return (*(impl.fp->add_component))(impl.derived_impl,comp);
295} 397}
296 398
297icalerrorenum icalset_remove_component(icalset* set, icalcomponent* comp) 399int icalset_count_components(icalset* set,icalcomponent_kind kind) {
298{ 400 return set->count_components(set,kind);
299 struct icalset_impl impl = icalset_get_impl(set);
300 return (*(impl.fp->remove_component))(impl.derived_impl,comp);
301} 401}
302 402
303int icalset_count_components(icalset* set,icalcomponent_kind kind) 403icalerrorenum icalset_select(icalset* set, icalgauge* gauge) {
304{ 404 return set->select(set, gauge);
305 struct icalset_impl impl = icalset_get_impl(set);
306 return (*(impl.fp->count_components))(impl.derived_impl,kind);
307} 405}
308 406
309icalerrorenum icalset_select(icalset* set, icalcomponent* gauge) 407void icalset_clear(icalset* set) {
310{ 408 set->clear(set);
311 struct icalset_impl impl = icalset_get_impl(set);
312 return (*(impl.fp->select))(impl.derived_impl,gauge);
313} 409}
314 410
315void icalset_clear(icalset* set) 411icalcomponent* icalset_fetch(icalset* set, const char* uid) {
316{ 412 return set->fetch(set, uid);
317 struct icalset_impl impl = icalset_get_impl(set);
318 (*(impl.fp->clear))(impl.derived_impl);
319} 413}
320 414
321icalcomponent* icalset_fetch(icalset* set, const char* uid) 415icalcomponent* icalset_fetch_match(icalset* set, icalcomponent *comp) {
322{ 416 return set->fetch_match(set, comp);
323 struct icalset_impl impl = icalset_get_impl(set);
324 return (*(impl.fp->fetch))(impl.derived_impl,uid);
325} 417}
326 418
327icalcomponent* icalset_fetch_match(icalset* set, icalcomponent *comp) 419int icalset_has_uid(icalset* set, const char* uid) {
328{ 420 return set->has_uid(set, uid);
329 struct icalset_impl impl = icalset_get_impl(set);
330 return (*(impl.fp->fetch_match))(impl.derived_impl,comp);
331} 421}
332 422
423icalerrorenum icalset_modify(icalset* set, icalcomponent *old,
424 icalcomponent *new) {
425 return set->modify(set, old, new);
426}
333 427
334int icalset_has_uid(icalset* set, const char* uid) 428icalcomponent* icalset_get_current_component(icalset* set) {
335{ 429 return set->get_current_component(set);
336 struct icalset_impl impl = icalset_get_impl(set);
337 return (*(impl.fp->has_uid))(impl.derived_impl,uid);
338} 430}
339 431
340icalerrorenum icalset_modify(icalset* set, icalcomponent *old, 432icalcomponent* icalset_get_first_component(icalset* set) {
341 icalcomponent *new) 433 return set->get_first_component(set);
342{
343 struct icalset_impl impl = icalset_get_impl(set);
344 return (*(impl.fp->modify))(impl.derived_impl,old,new);
345} 434}
346 435
347icalcomponent* icalset_get_current_component(icalset* set) 436icalcomponent* icalset_get_next_component(icalset* set) {
348{ 437 return set->get_next_component(set);
349 struct icalset_impl impl = icalset_get_impl(set);
350 return (*(impl.fp->get_current_component))(impl.derived_impl);
351} 438}
352 439
353icalcomponent* icalset_get_first_component(icalset* set) 440icalsetiter icalsetiter_null = {{ICAL_NO_COMPONENT, 0}, 0};
354{ 441
355 struct icalset_impl impl = icalset_get_impl(set); 442icalsetiter icalset_begin_component(icalset* set,
356 return (*(impl.fp->get_first_component))(impl.derived_impl); 443 icalcomponent_kind kind, icalgauge* gauge) {
444 return set->icalset_begin_component(set, kind, gauge);
357} 445}
358 446
359icalcomponent* icalset_get_next_component(icalset* set) 447icalcomponent* icalsetiter_next(icalsetiter* itr) {
360{ 448
361 struct icalset_impl impl = icalset_get_impl(set); 449 icalcomponent* c = 0;
362 return (*(impl.fp->get_next_component))(impl.derived_impl); 450 icalerror_check_arg_rz( (itr != NULL), "i");
451
452 do {
453 c = icalcompiter_next(&(itr->iter));
454 if(c != 0 && (itr->gauge == 0 ||
455 icalgauge_compare(itr->gauge, c) == 1)){
456 return c;
457 }
458 } while (c != 0);
459
460 return 0;
461}
462
463icalcomponent* icalsetiter_prior(icalsetiter* i) {
464
465 icalcomponent* c = 0;
466 icalerror_check_arg_rz( (i != NULL), "i" );
467
468 do {
469 c = icalcompiter_prior(&(i->iter));
470 if(c != 0 && (i->gauge == 0 ||
471 icalgauge_compare(i->gauge, c) == 1)){
472 return c;
363} 473}
474 } while (c != 0);
364 475
476 return 0;
477}
365 478
479icalcomponent* icalsetiter_deref(icalsetiter* i) {
480 icalerror_check_arg_rz( (i != NULL), "i" );
481 return (icalcompiter_deref(&(i->iter)));
482}
366 483
484/* for subclasses that use multiple clusters that require specialized cluster traversal */
485icalcomponent* icalsetiter_to_next(icalset* set, icalsetiter* i)
486{
487 return set->icalsetiter_to_next(set, i);
488}
367 489
490icalcomponent* icalsetiter_to_prior(icalset* set, icalsetiter* i)
491{
492 return set->icalsetiter_to_prior(set, i);
493}