summaryrefslogtreecommitdiff
path: root/src/libicalss/icalset.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libicalss/icalset.c')
-rw-r--r--src/libicalss/icalset.c493
1 files changed, 493 insertions, 0 deletions
diff --git a/src/libicalss/icalset.c b/src/libicalss/icalset.c
new file mode 100644
index 00000000..cd38033b
--- /dev/null
+++ b/src/libicalss/icalset.c
@@ -0,0 +1,493 @@
+/* -*- Mode: C -*- */
+/*======================================================================
+ FILE: icalset.c
+ CREATOR: eric 17 Jul 2000
+
+
+ Icalset is the "base class" for representations of a collection of
+ iCal components. Derived classes (actually delegates) include:
+
+ icalfileset Store components in a single file
+ icaldirset Store components in multiple files in a directory
+ icalheapset Store components on the heap
+ icalmysqlset Store components in a mysql database.
+
+ $Id: icalset.c,v 1.18 2008-01-02 20:07:41 dothebart Exp $
+ $Locker: $
+
+ (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ The LGPL as published by the Free Software Foundation, version
+ 2.1, available at: http://www.fsf.org/copyleft/lesser.html
+
+ Or:
+
+ The Mozilla Public License Version 1.0. You may obtain a copy of
+ the License at http://www.mozilla.org/MPL/
+
+ The Original Code is eric. The Initial Developer of the Original
+ Code is Eric Busboom
+
+
+======================================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <libical/ical.h>
+#include "icalset.h"
+#include "icalfileset.h"
+#include "icalfilesetimpl.h"
+#include "icaldirset.h"
+#include "icaldirsetimpl.h"
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef WITH_BDB4
+#include "icalbdbset.h"
+#include "icalbdbsetimpl.h"
+#endif
+
+/* #define _DLOPEN_TEST */
+#ifdef _DLOPEN_TEST
+#include <sys/types.h>
+#include <dlfcn.h>
+#include <dirent.h>
+#endif
+
+static icalset icalset_dirset_init = {
+ ICAL_DIR_SET,
+ sizeof(icaldirset),
+ NULL,
+ icaldirset_init,
+ icaldirset_free,
+ icaldirset_path,
+ icaldirset_mark,
+ icaldirset_commit,
+ icaldirset_add_component,
+ icaldirset_remove_component,
+ icaldirset_count_components,
+ icaldirset_select,
+ icaldirset_clear,
+ icaldirset_fetch,
+ icaldirset_fetch_match,
+ icaldirset_has_uid,
+ icaldirset_modify,
+ icaldirset_get_current_component,
+ icaldirset_get_first_component,
+ icaldirset_get_next_component,
+ icaldirset_begin_component,
+ icaldirsetiter_to_next,
+ icaldirsetiter_to_prior
+};
+
+
+static icalset icalset_fileset_init = {
+ ICAL_FILE_SET,
+ sizeof(icalfileset),
+ NULL,
+ icalfileset_init,
+ icalfileset_free,
+ icalfileset_path,
+ icalfileset_mark,
+ icalfileset_commit,
+ icalfileset_add_component,
+ icalfileset_remove_component,
+ icalfileset_count_components,
+ icalfileset_select,
+ icalfileset_clear,
+ icalfileset_fetch,
+ icalfileset_fetch_match,
+ icalfileset_has_uid,
+ icalfileset_modify,
+ icalfileset_get_current_component,
+ icalfileset_get_first_component,
+ icalfileset_get_next_component,
+ icalfileset_begin_component,
+ icalfilesetiter_to_next,
+ NULL
+};
+
+#ifdef WITH_BDB4
+static icalset icalset_bdbset_init = {
+ ICAL_BDB_SET,
+ sizeof(icalbdbset),
+ NULL,
+ icalbdbset_init,
+ icalbdbset_free,
+ icalbdbset_path,
+ icalbdbset_mark,
+ icalbdbset_commit,
+ icalbdbset_add_component,
+ icalbdbset_remove_component,
+ icalbdbset_count_components,
+ icalbdbset_select,
+ icalbdbset_clear,
+ icalbdbset_fetch,
+ icalbdbset_fetch_match,
+ icalbdbset_has_uid,
+ icalbdbset_modify,
+ icalbdbset_get_current_component,
+ icalbdbset_get_first_component,
+ icalbdbset_get_next_component,
+ icalbdbset_begin_component,
+ icalbdbsetiter_to_next,
+ NULL
+};
+#endif
+
+#ifdef _DLOPEN_TEST
+static int icalset_init_done = 0;
+static pvl_list icalset_kinds = 0;
+
+typedef icalset *(*fptr)(void);
+
+/**
+ * Try to load the file and register any icalset found within.
+ */
+static int load(const char *file) {
+
+ void *modh;
+ fptr inith;
+ icalset *icalset_init_ptr;
+
+ if ((modh = dlopen(file, RTLD_NOW)) == 0) {
+ perror("dlopen");
+ return 0;
+ }
+
+ if ((inith = (fptr)dlsym(modh, "InitModule")) == 0) {
+ perror("dlsym");
+ return 0;
+ }
+
+ while ((icalset_init_ptr = ((inith)())) != 0) {
+ pvl_push(icalset_kinds, &icalset_init_ptr);
+ }
+
+ return 1;
+}
+
+/**
+ * Look in the given directory for files called mod_*.o and try to
+ * load them.
+ */
+int icalset_loaddir(const char *path) {
+ DIR *d;
+ struct dirent *dp;
+ char buf[PATH_MAX],
+ *bufptr;
+ int tot = 0;
+
+ strcpy(buf, path);
+ bufptr = buf + strlen(buf);
+
+ if (*(bufptr-1) != '/')
+ *bufptr++ = '/';
+
+ if ((d = opendir(path)) == 0) {
+ perror("opendir");
+ return 0;
+ }
+
+ while ((dp = readdir(d)) != 0) {
+ if (strncmp(dp->d_name, "mod_", 4)) continue;
+
+ strcpy(bufptr, dp->d_name);
+
+ load(buf);
+ tot++;
+ }
+ (void)closedir(d);
+
+ return 1;
+}
+
+int icalset_register_class(icalset *set);
+
+static void icalset_init(void) {
+ assert(icalset_kinds == 0);
+ icalset_kinds = pvl_newlist();
+
+ pvl_push(icalset_kinds, &icalset_fileset_init);
+ pvl_push(icalset_kinds, &icalset_dirset_init);
+#ifdef WITH_BDB4
+ pvl_push(icalset_kinds, &icalset_bdb4set_init);
+#endif
+
+#ifdef EXT_PATH
+ icalset_loaddir(EXT_PATH);
+#endif
+
+ icalset_init_done++;
+}
+
+int icalset_register_class(icalset *set) {
+
+ if (!icalset_init_done)
+ icalset_init();
+
+ pvl_push(icalset_kinds, set);
+ return 1;
+}
+
+#endif
+
+icalset* icalset_new(icalset_kind kind, const char* dsn, void* options) {
+ icalset *data = NULL;
+ icalset *ret = NULL;
+
+#ifdef _DLOPEN_TEST
+ pvl_elem e;
+ icalset *impl;
+
+ if (!icalset_init_done)
+ icalset_init();
+
+ for(e = pvl_head(icalset_kinds); e!=0; e = pvl_next(e)) {
+ impl = (icalset*)pvl_data(e);
+ if (impl->kind == kind)
+ break;
+ }
+ if (e == 0) {
+ icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
+ return(NULL);
+ }
+
+ data = (icalset*)malloc(impl->size);
+ if (data == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ errno = ENOMEM;
+ return 0;
+ }
+
+ /* The first member of the derived class must be an icalset. */
+ memset(data,0,impl->size);
+ /* *data = *impl; */
+ memcpy(data, impl, sizeof(icalset));
+
+ data->dsn = strdup(dsn);
+#else
+ switch(kind) {
+ case ICAL_FILE_SET:
+ data = (icalset*) malloc(sizeof(icalfileset));
+ if (data == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ errno = ENOMEM;
+ return 0;
+ }
+ memset(data,0,sizeof(icalfileset));
+ *data = icalset_fileset_init;
+ break;
+ case ICAL_DIR_SET:
+ data = (icalset*) malloc(sizeof(icaldirset));
+ if (data == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ errno = ENOMEM;
+ return 0;
+ }
+ memset(data,0,sizeof(icaldirset));
+ *data = icalset_dirset_init;
+ break;
+#ifdef WITH_BDB4
+ case ICAL_BDB_SET:
+ data = (icalset*) malloc(sizeof(icalbdbset));
+ if (data == 0) {
+ icalerror_set_errno(ICAL_NEWFAILED_ERROR);
+ errno = ENOMEM;
+ return 0;
+ }
+ memset(data,0,sizeof(icalbdbset));
+ *data = icalset_bdbset_init;
+ break;
+#endif
+
+ default:
+ icalerror_set_errno(ICAL_UNIMPLEMENTED_ERROR);
+ /** unimplemented **/
+ return(NULL);
+ }
+
+ data->kind = kind;
+ data->dsn = strdup(dsn);
+#endif
+
+ /** call the implementation specific initializer **/
+ if ((ret = data->init(data, dsn, options)) == NULL)
+ icalset_free(data);
+
+ return ret;
+}
+
+icalset* icalset_new_file(const char* path)
+{
+ return icalset_new(ICAL_FILE_SET, path, NULL);
+}
+
+icalset* icalset_new_file_writer(const char* path)
+{
+ return icalfileset_new_writer(path);
+}
+
+icalset* icalset_new_file_reader(const char* path)
+{
+ return icalfileset_new_reader(path);
+}
+
+
+icalset* icalset_new_dir(const char* path)
+{
+ return icalset_new(ICAL_DIR_SET, path, NULL);
+}
+
+icalset* icalset_new_dir_writer(const char* path)
+{
+ return icaldirset_new_writer(path);
+}
+
+icalset* icalset_new_dir_reader(const char* path)
+{
+ return icaldirset_new_reader(path);
+}
+
+
+
+/* Functions for built-in methods */
+
+/**
+ * free memory associated with this icalset
+ * automatically calls the implementation specific free routine
+ */
+
+void icalset_free(icalset* set)
+{
+ if (set->free)
+ set->free(set);
+
+ if (set->dsn)
+ free(set->dsn);
+
+ free(set);
+}
+
+
+const char* icalset_path(icalset* set) {
+ return set->path(set);
+}
+
+void icalset_mark(icalset* set) {
+ set->mark(set);
+}
+
+icalerrorenum icalset_commit(icalset* set) {
+ return set->commit(set);
+}
+
+icalerrorenum icalset_add_component(icalset* set, icalcomponent* comp) {
+ return set->add_component(set,comp);
+}
+
+icalerrorenum icalset_remove_component(icalset* set, icalcomponent* comp) {
+ return set->remove_component(set,comp);
+}
+
+int icalset_count_components(icalset* set,icalcomponent_kind kind) {
+ return set->count_components(set,kind);
+}
+
+icalerrorenum icalset_select(icalset* set, icalgauge* gauge) {
+ return set->select(set, gauge);
+}
+
+void icalset_clear(icalset* set) {
+ set->clear(set);
+}
+
+icalcomponent* icalset_fetch(icalset* set, const char* uid) {
+ return set->fetch(set, uid);
+}
+
+icalcomponent* icalset_fetch_match(icalset* set, icalcomponent *comp) {
+ return set->fetch_match(set, comp);
+}
+
+int icalset_has_uid(icalset* set, const char* uid) {
+ return set->has_uid(set, uid);
+}
+
+icalerrorenum icalset_modify(icalset* set, icalcomponent *old,
+ icalcomponent *new) {
+ return set->modify(set, old, new);
+}
+
+icalcomponent* icalset_get_current_component(icalset* set) {
+ return set->get_current_component(set);
+}
+
+icalcomponent* icalset_get_first_component(icalset* set) {
+ return set->get_first_component(set);
+}
+
+icalcomponent* icalset_get_next_component(icalset* set) {
+ return set->get_next_component(set);
+}
+
+icalsetiter icalsetiter_null = {{ICAL_NO_COMPONENT, 0}, 0};
+
+icalsetiter icalset_begin_component(icalset* set,
+ icalcomponent_kind kind, icalgauge* gauge) {
+ return set->icalset_begin_component(set, kind, gauge);
+}
+
+icalcomponent* icalsetiter_next(icalsetiter* itr) {
+
+ icalcomponent* c = 0;
+ icalerror_check_arg_rz( (itr != NULL), "i");
+
+ do {
+ c = icalcompiter_next(&(itr->iter));
+ if(c != 0 && (itr->gauge == 0 ||
+ icalgauge_compare(itr->gauge, c) == 1)){
+ return c;
+ }
+ } while (c != 0);
+
+ return 0;
+}
+
+icalcomponent* icalsetiter_prior(icalsetiter* i) {
+
+ icalcomponent* c = 0;
+ icalerror_check_arg_rz( (i != NULL), "i" );
+
+ do {
+ c = icalcompiter_prior(&(i->iter));
+ if(c != 0 && (i->gauge == 0 ||
+ icalgauge_compare(i->gauge, c) == 1)){
+ return c;
+ }
+ } while (c != 0);
+
+ return 0;
+}
+
+icalcomponent* icalsetiter_deref(icalsetiter* i) {
+ icalerror_check_arg_rz( (i != NULL), "i" );
+ return (icalcompiter_deref(&(i->iter)));
+}
+
+/* for subclasses that use multiple clusters that require specialized cluster traversal */
+icalcomponent* icalsetiter_to_next(icalset* set, icalsetiter* i)
+{
+ return set->icalsetiter_to_next(set, i);
+}
+
+icalcomponent* icalsetiter_to_prior(icalset* set, icalsetiter* i)
+{
+ return set->icalsetiter_to_prior(set, i);
+}