diff options
| author | Christian Hilberg <chilberg@src.gnome.org> | 2012-06-22 17:16:50 +0200 |
|---|---|---|
| committer | Matthew Barnes <mbarnes@redhat.com> | 2012-06-26 11:20:28 -0400 |
| commit | bcd3df6764d454fb869cecb14947da1fb22cf22e (patch) | |
| tree | 98f83fc5875bc49f28284d470414d4431a645903 /camel/camel-imapx-utils.c | |
| parent | 4a7c65acba51766d5c260c49f886b8c91599f295 (diff) | |
| download | evolution-data-server-bcd3df6764d454fb869cecb14947da1fb22cf22e.tar.gz | |
IMAPX: (utils) made capabilities flags extensible
* added a hash table as an IMAP capabilities flags
lookup mechanism for the capabilities parser util
function
* added a capabilities strings registration function
(to add new capabilities flags, which will then be
known to the parser and assigned a new flag bit.
This is returned by the registration function so
the caller can test whether the bit is set in the
CamelIMAPXServer capabilities bitstring)
Diffstat (limited to 'camel/camel-imapx-utils.c')
| -rw-r--r-- | camel/camel-imapx-utils.c | 91 |
1 files changed, 86 insertions, 5 deletions
diff --git a/camel/camel-imapx-utils.c b/camel/camel-imapx-utils.c index 856600a5f..4a7f2cce5 100644 --- a/camel/camel-imapx-utils.c +++ b/camel/camel-imapx-utils.c @@ -354,7 +354,7 @@ imapx_update_store_summary (CamelFolder *folder) struct { const gchar *name; guint32 flag; -} capa_table[] = { +} capa_table[] = { /* used to create capa_htable only */ { "IMAP4", IMAPX_CAPABILITY_IMAP4 }, { "IMAP4REV1", IMAPX_CAPABILITY_IMAP4REV1 }, { "STATUS", IMAPX_CAPABILITY_STATUS } , @@ -369,14 +369,42 @@ struct { { "LIST-STATUS", IMAPX_CAPABILITY_LIST_STATUS }, }; +static GMutex capa_htable_lock; /* capabilities lookup table lock */ +static GHashTable *capa_htable = NULL; /* capabilities lookup table (extensible) */ + +static void +create_initial_capabilities_table (void) +{ + gint i = 0; + + /* call within g_init_once() only, + * or require table lock + */ + + /* TODO add imapx_utils_uninit() + * to free hash table + */ + capa_htable = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + NULL); + + for (i = 0; i < G_N_ELEMENTS (capa_table); i++) { + g_hash_table_insert (capa_htable, + g_strdup (capa_table[i].name), + GUINT_TO_POINTER (capa_table[i].flag)); + } +} + struct _capability_info * imapx_parse_capability (CamelIMAPXStream *stream, GCancellable *cancellable, GError **error) { - gint tok, i; + gint tok; guint len; guchar *token, *p, c; + gpointer pp = NULL; gboolean free_token = FALSE; struct _capability_info * cinfo; GError *local_error = NULL; @@ -408,9 +436,14 @@ imapx_parse_capability (CamelIMAPXStream *stream, } case IMAPX_TOK_INT: d(stream->tagprefix, " cap: '%s'\n", token); - for (i = 0; i < G_N_ELEMENTS (capa_table); i++) - if (!strcmp ((gchar *) token, capa_table[i].name)) - cinfo->capa |= capa_table[i].flag; + g_mutex_lock (&capa_htable_lock); + pp = g_hash_table_lookup (capa_htable, + (gchar*) token); + g_mutex_unlock (&capa_htable_lock); + if (pp != NULL) { + guint32 capa_id = GPOINTER_TO_UINT (pp); + cinfo->capa |= capa_id; + } if (free_token) { g_free (token); token = NULL; @@ -438,6 +471,53 @@ void imapx_free_capability (struct _capability_info *cinfo) g_free (cinfo); } +guint32 +imapx_register_capability (const gchar *capability) +{ + guint32 capa_id = 0; + guint64 check_id = 0; + GList *keys = NULL; + GList *tmp_keys = NULL; + + g_assert (capability != NULL); + + g_mutex_lock (&capa_htable_lock); + + /* we rely on IMAP being the first flag, non-zero value + * (1 << 0), so we can use GPOINTER_TO_UINT (NULL) as + * invalid value + */ + capa_id = GPOINTER_TO_UINT (g_hash_table_lookup (capa_htable, + capability)); + if (capa_id > 0) + goto exit; + + /* not yet there, find biggest flag so far */ + keys = g_hash_table_get_keys (capa_htable); + tmp_keys = keys; + while (tmp_keys != NULL) { + guint32 tmp_id = GPOINTER_TO_UINT (tmp_keys->data); + if (capa_id < tmp_id) + capa_id = tmp_id; + tmp_keys = g_list_next (tmp_keys); + } + + /* shift-left biggest-so-far, sanity-check */ + check_id = (capa_id << 1); + g_assert (check_id <= (guint64) G_MAXUINT32); + capa_id = (guint32) check_id; + + /* insert */ + g_hash_table_insert (capa_htable, + g_strdup (capability), + GUINT_TO_POINTER (capa_id)); + + exit: + g_mutex_unlock (&capa_htable_lock); + + return capa_id; +} + struct _CamelIMAPXNamespaceList * imapx_parse_namespace_list (CamelIMAPXStream *stream, GCancellable *cancellable, @@ -1993,6 +2073,7 @@ imapx_utils_init (void) imapx_specials[i] = v; } + create_initial_capabilities_table (); camel_imapx_set_debug_flags (); g_once_init_leave (&imapx_utils_initialized, 1); |
