summaryrefslogtreecommitdiffabout
path: root/libical/src/libicalss/icalset.c
Unidiff
Diffstat (limited to 'libical/src/libicalss/icalset.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libical/src/libicalss/icalset.c528
1 files changed, 327 insertions, 201 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
@@ -41,33 +41,26 @@
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,
@@ -83,11 +76,18 @@ struct icalset_fp icalset_dirset_fp = {
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,
@@ -103,265 +103,391 @@ struct icalset_fp icalset_fileset_fp = {
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) 150
122{ 151 void *modh;
123 struct icalset_impl impl; 152 fptr inith;
124 153 icalset *icalset_init_ptr;
125 memset(&impl,0,sizeof(impl)); 154
126 icalerror_check_arg_re( (set!=0),"set",impl); 155 if ((modh = dlopen(file, RTLD_NOW)) == 0) {
127 156 perror("dlopen");
128 if(strcmp((char*)set,ICALSET_ID)==0) { 157 return 0;
129 /* It is actually a set, so just sent the reference back out. */ 158 }
130 return *(struct icalset_impl*)set; 159
131 } else if(strcmp((char*)set,ICALFILESET_ID)==0) { 160 if ((inith = (fptr)dlsym(modh, "InitModule")) == 0) {
132 /* Make a new set from the fileset */ 161 perror("dlsym");
133 impl.fp = &icalset_fileset_fp; 162 return 0;
134 impl.derived_impl = set; 163 }
135 strcpy(impl.id,ICALFILESET_ID);/* HACK. Is this necessary? */ 164
136 return impl; 165 while ((icalset_init_ptr = ((inith)())) != 0) {
137 } else if(strcmp((char*)set,ICALDIRSET_ID)==0) { 166 pvl_push(icalset_kinds, &icalset_init_ptr);
138 /* Make a new set from the dirset */ 167 }
139 impl.fp = &icalset_dirset_fp; 168
140 impl.derived_impl = set; 169 return 1;
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} 170}
149 171
172/**
173 * Look in the given directory for files called mod_*.o and try to
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;
150 182
151struct icalset_impl* icalset_new_impl() 183 strcpy(buf, path);
152{ 184 bufptr = buf + strlen(buf);
153
154 struct icalset_impl* impl;
155 185
156 if ( ( impl = (struct icalset_impl*) 186 if (*(bufptr-1) != '/')
157 malloc(sizeof(struct icalset_impl))) == 0) { 187 *bufptr++ = '/';
158 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
159 return 0;
160 }
161 188
162 strcpy(impl->id,ICALSET_ID); 189 if ((d = opendir(path)) == 0) {
190 perror("opendir");
191 return 0;
192 }
163 193
164 impl->derived_impl = 0; 194 while ((dp = readdir(d)) != 0) {
165 impl->fp = 0; 195 if (strncmp(dp->d_name, "mod_", 4)) continue;
166 196
167 return impl; 197 strcpy(bufptr, dp->d_name);
168}
169 198
170struct icalset_impl* icalset_new_file_from_ref(icalfileset *fset) 199 load(buf);
171{ 200 tot++;
172 struct icalset_impl *impl = icalset_new_impl(); 201 }
202 (void)closedir(d);
173 203
174 icalerror_check_arg_rz( (fset!=0),"fset"); 204 return 1;
205}
175 206
176 if(impl == 0){ 207int icalset_register_class(icalset *set);
177 free(impl);
178 return 0;
179 }
180 208
181 impl->derived_impl = fset; 209static void icalset_init(void) {
210 assert(icalset_kinds == 0);
211 icalset_kinds = pvl_newlist();
182 212
183 if (impl->derived_impl == 0){ 213 pvl_push(icalset_kinds, &icalset_fileset_init);
184 free(impl); 214 pvl_push(icalset_kinds, &icalset_dirset_init);
185 return 0; 215#ifdef WITH_BDB4
186 } 216 pvl_push(icalset_kinds, &icalset_bdb4set_init);
217#endif
187 218
188 impl->fp = &icalset_fileset_fp; 219#ifdef EXT_PATH
220 icalset_loaddir(EXT_PATH);
221#endif
189 222
190 return (struct icalset_impl*)impl; 223 icalset_init_done++;
191} 224}
192 225
193icalset* icalset_new_file(const char* path) 226int icalset_register_class(icalset *set) {
194{
195 icalfileset *fset = icalfileset_new(path);
196 227
197 if(fset == 0){ 228 if (!icalset_init_done)
198 return 0; 229 icalset_init();
199 }
200 230
201 return (icalset*)icalset_new_file_from_ref(fset); 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();
247
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);
213 } 256 }
214 257
215 impl->derived_impl = dset; 258 data = (icalset*)malloc(impl->size);
259 if (data == 0) {
260 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
261 errno = ENOMEM;
262 return 0;
263 }
216 264
217 if (impl->derived_impl == 0){ 265 /* The first member of the derived class must be an icalset. */
218 free(impl); 266 memset(data,0,impl->size);
267 /* *data = *impl; */
268 memcpy(data, impl, sizeof(icalset));
269
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;
219 return 0; 299 return 0;
220 } 300 }
301 memset(data,0,sizeof(icalbdbset));
302 *data = icalset_bdbset_init;
303 break;
304#endif
305
306 default:
307 icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
308 /** unimplemented **/
309 return(NULL);
310 }
311
312 if ( data == 0) {
313 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
314 return 0;
315 }
316 data->kind = kind;
317 data->dsn = strdup(dsn);
318#endif
221 319
222 impl->fp = &icalset_dirset_fp; 320 /** call the implementation specific initializer **/
321 if ((ret = data->init(data, dsn, options)) == NULL)
322 icalset_free(data);
223 323
224 return impl; 324 return ret;
225} 325}
226 326
227icalset* icalset_new_dir(const char* path) 327icalset* icalset_new_file(const char* path)
228{ 328{
229 icaldirset *dset = icaldirset_new(path); 329 return icalset_new(ICAL_FILE_SET, path, NULL);
230 330}
231 if(dset == 0){
232 return 0;
233 }
234 331
235 return icalset_new_dir_from_ref(dset); 332icalset* icalset_new_file_writer(const char* path)
333{
334 return icalfileset_new_writer(path);
236} 335}
237 336
238icalset* icalset_new_heap(void) 337icalset* icalset_new_file_reader(const char* path)
239{ 338{
240 struct icalset_impl *impl = icalset_new_impl(); 339 return icalfileset_new_reader(path);
340}
241 341
242 342
243 if(impl == 0){ 343icalset* icalset_new_dir(const char* path)
244 free(impl); 344{
245 return 0; 345 return icalset_new(ICAL_DIR_SET, path, NULL);
246 } 346}
247 347
248 return 0; 348icalset* icalset_new_dir_writer(const char* path)
349{
350 return icaldirset_new_writer(path);
249} 351}
250 352
251icalset* icalset_new_mysql(const char* path) 353icalset* icalset_new_dir_reader(const char* path)
252{ 354{
253 struct icalset_impl *impl = icalset_new_impl(); 355 return icaldirset_new_reader(path);
356}
254 357
255 if(impl == 0){
256 free(impl);
257 return 0;
258 }
259 358
260 return 0; 359
261} 360/* Functions for built-in methods */
361
362/**
363 * free memory associated with this icalset
364 * automatically calls the implementation specific free routine
365 */
262 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);
267 371
268 if(strcmp((char*)set,ICALSET_ID)) { 372 if (set->dsn)
269 free(set); 373 free(set->dsn);
270 }
271}
272 374
273const char* icalset_path(icalset* set) 375 free(set);
274{
275 struct icalset_impl impl = icalset_get_impl(set);
276 return (*(impl.fp->path))(impl.derived_impl);
277} 376}
278 377
279void icalset_mark(icalset* set) 378
280{ 379const char* icalset_path(icalset* set) {
281 struct icalset_impl impl = icalset_get_impl(set); 380 return set->path(set);
282 (*(impl.fp->mark))(impl.derived_impl);
283} 381}
284 382
285icalerrorenum icalset_commit(icalset* set) 383void icalset_mark(icalset* set) {
286{ 384 set->mark(set);
287 struct icalset_impl impl = icalset_get_impl(set);
288 return (*(impl.fp->commit))(impl.derived_impl);
289} 385}
290 386
291icalerrorenum icalset_add_component(icalset* set, icalcomponent* comp) 387icalerrorenum icalset_commit(icalset* set) {
292{ 388 return set->commit(set);
293 struct icalset_impl impl = icalset_get_impl(set);
294 return (*(impl.fp->add_component))(impl.derived_impl,comp);
295} 389}
296 390
297icalerrorenum icalset_remove_component(icalset* set, icalcomponent* comp) 391icalerrorenum icalset_add_component(icalset* set, icalcomponent* comp) {
298{ 392 return set->add_component(set,comp);
299 struct icalset_impl impl = icalset_get_impl(set);
300 return (*(impl.fp->remove_component))(impl.derived_impl,comp);
301} 393}
302 394
303int icalset_count_components(icalset* set,icalcomponent_kind kind) 395icalerrorenum icalset_remove_component(icalset* set, icalcomponent* comp) {
304{ 396 return set->remove_component(set,comp);
305 struct icalset_impl impl = icalset_get_impl(set);
306 return (*(impl.fp->count_components))(impl.derived_impl,kind);
307} 397}
308 398
309icalerrorenum icalset_select(icalset* set, icalcomponent* gauge) 399int icalset_count_components(icalset* set,icalcomponent_kind kind) {
310{ 400 return set->count_components(set,kind);
311 struct icalset_impl impl = icalset_get_impl(set);
312 return (*(impl.fp->select))(impl.derived_impl,gauge);
313} 401}
314 402
315void icalset_clear(icalset* set) 403icalerrorenum icalset_select(icalset* set, icalgauge* gauge) {
316{ 404 return set->select(set, gauge);
317 struct icalset_impl impl = icalset_get_impl(set);
318 (*(impl.fp->clear))(impl.derived_impl);
319} 405}
320 406
321icalcomponent* icalset_fetch(icalset* set, const char* uid) 407void icalset_clear(icalset* set) {
322{ 408 set->clear(set);
323 struct icalset_impl impl = icalset_get_impl(set);
324 return (*(impl.fp->fetch))(impl.derived_impl,uid);
325} 409}
326 410
327icalcomponent* icalset_fetch_match(icalset* set, icalcomponent *comp) 411icalcomponent* icalset_fetch(icalset* set, const char* uid) {
328{ 412 return set->fetch(set, uid);
329 struct icalset_impl impl = icalset_get_impl(set);
330 return (*(impl.fp->fetch_match))(impl.derived_impl,comp);
331} 413}
332 414
415icalcomponent* icalset_fetch_match(icalset* set, icalcomponent *comp) {
416 return set->fetch_match(set, comp);
417}
333 418
334int icalset_has_uid(icalset* set, const char* uid) 419int icalset_has_uid(icalset* set, const char* uid) {
335{ 420 return set->has_uid(set, uid);
336 struct icalset_impl impl = icalset_get_impl(set);
337 return (*(impl.fp->has_uid))(impl.derived_impl,uid);
338} 421}
339 422
340icalerrorenum icalset_modify(icalset* set, icalcomponent *old, 423icalerrorenum icalset_modify(icalset* set, icalcomponent *old,
341 icalcomponent *new) 424 icalcomponent *new) {
342{ 425 return set->modify(set, old, new);
343 struct icalset_impl impl = icalset_get_impl(set);
344 return (*(impl.fp->modify))(impl.derived_impl,old,new);
345} 426}
346 427
347icalcomponent* icalset_get_current_component(icalset* set) 428icalcomponent* icalset_get_current_component(icalset* set) {
348{ 429 return set->get_current_component(set);
349 struct icalset_impl impl = icalset_get_impl(set);
350 return (*(impl.fp->get_current_component))(impl.derived_impl);
351} 430}
352 431
353icalcomponent* icalset_get_first_component(icalset* set) 432icalcomponent* icalset_get_first_component(icalset* set) {
354{ 433 return set->get_first_component(set);
355 struct icalset_impl impl = icalset_get_impl(set);
356 return (*(impl.fp->get_first_component))(impl.derived_impl);
357} 434}
358 435
359icalcomponent* icalset_get_next_component(icalset* set) 436icalcomponent* icalset_get_next_component(icalset* set) {
360{ 437 return set->get_next_component(set);
361 struct icalset_impl impl = icalset_get_impl(set); 438}
362 return (*(impl.fp->get_next_component))(impl.derived_impl); 439
440icalsetiter icalsetiter_null = {{ICAL_NO_COMPONENT, 0}, 0};
441
442icalsetiter icalset_begin_component(icalset* set,
443 icalcomponent_kind kind, icalgauge* gauge) {
444 return set->icalset_begin_component(set, kind, gauge);
445}
446
447icalcomponent* icalsetiter_next(icalsetiter* itr) {
448
449 icalcomponent* c = 0;
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;
363} 461}
364 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;
473 }
474 } while (c != 0);
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}