Mercurial > dovecot > core-2.2
view src/lib-storage/mailbox-tree.c @ 14629:c93ca5e46a8a
Marked functions parameters that are allowed to be NULL. Some APIs were also changed.
The non-obvious APIs where NULL parameter was changed to "" are
master_service_init() and auth_master_user_list_init().
These checks can currently be enabled only on a patched clang:
http://llvm.org/bugs/show_bug.cgi?id=6786
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 24 Jun 2012 00:52:57 +0300 |
parents | 4cea936d57f2 |
children | acc60089da4f |
line wrap: on
line source
/* Copyright (c) 2003-2012 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "array.h" #include "str.h" #include "mailbox-tree.h" struct mailbox_tree_context { pool_t pool; char separator; bool parents_nonexistent; struct mailbox_node *nodes; }; struct mailbox_tree_iterate_context { struct mailbox_node *root, *next_node; unsigned int flags_mask; char separator; ARRAY_DEFINE(node_path, struct mailbox_node *); string_t *path_str; size_t parent_pos; unsigned int first_child:1; }; struct mailbox_tree_context *mailbox_tree_init(char separator) { struct mailbox_tree_context *tree; tree = i_new(struct mailbox_tree_context, 1); tree->pool = pool_alloconly_create(MEMPOOL_GROWING"mailbox_tree", 10240); tree->separator = separator; return tree; } void mailbox_tree_deinit(struct mailbox_tree_context **_tree) { struct mailbox_tree_context *tree = *_tree; *_tree = NULL; pool_unref(&tree->pool); i_free(tree); } void mailbox_tree_set_separator(struct mailbox_tree_context *tree, char separator) { tree->separator = separator; } void mailbox_tree_set_parents_nonexistent(struct mailbox_tree_context *tree) { tree->parents_nonexistent = TRUE; } void mailbox_tree_clear(struct mailbox_tree_context *tree) { p_clear(tree->pool); tree->nodes = NULL; } static struct mailbox_node * ATTR_NULL(2) mailbox_tree_traverse(struct mailbox_tree_context *tree, const char *path, bool create, bool *created_r) { struct mailbox_node **node, *parent; const char *name; string_t *str; *created_r = FALSE; if (path == NULL) return tree->nodes; if (strncasecmp(path, "INBOX", 5) == 0 && (path[5] == '\0' || path[5] == tree->separator)) path = t_strdup_printf("INBOX%s", path+5); parent = NULL; node = &tree->nodes; str = t_str_new(strlen(path)+1); for (name = path;; path++) { if (*path != tree->separator && *path != '\0') continue; str_truncate(str, 0); str_append_n(str, name, (size_t) (path - name)); name = str_c(str); /* find the node */ while (*node != NULL) { if (strcmp((*node)->name, name) == 0) break; node = &(*node)->next; } if (*node == NULL) { /* not found, create it */ if (!create) break; *node = p_new(tree->pool, struct mailbox_node, 1); (*node)->parent = parent; (*node)->name = p_strdup(tree->pool, name); if (tree->parents_nonexistent) (*node)->flags = MAILBOX_NONEXISTENT; *created_r = TRUE; } if (*path == '\0') break; name = path+1; parent = *node; node = &(*node)->children; } return *node; } struct mailbox_node * mailbox_tree_get(struct mailbox_tree_context *tree, const char *path, bool *created_r) { struct mailbox_node *node; bool created; T_BEGIN { node = mailbox_tree_traverse(tree, path, TRUE, &created); } T_END; if (created && tree->parents_nonexistent) node->flags = 0; *created_r = created; return node; } struct mailbox_node * mailbox_tree_lookup(struct mailbox_tree_context *tree, const char *path) { struct mailbox_node *node; bool created; T_BEGIN { node = mailbox_tree_traverse(tree, path, FALSE, &created); } T_END; return node; } struct mailbox_tree_iterate_context * mailbox_tree_iterate_init(struct mailbox_tree_context *tree, struct mailbox_node *root, unsigned int flags_mask) { struct mailbox_tree_iterate_context *ctx; ctx = i_new(struct mailbox_tree_iterate_context, 1); ctx->separator = tree->separator; ctx->root = root != NULL ? root : tree->nodes; ctx->flags_mask = flags_mask; ctx->path_str = str_new(default_pool, 256); i_array_init(&ctx->node_path, 16); ctx->next_node = ctx->root; return ctx; } static void mailbox_tree_iterate_set_next_node(struct mailbox_tree_iterate_context *ctx) { struct mailbox_node *node = ctx->next_node; struct mailbox_node *const *nodes; unsigned int i, count; if (node->children != NULL) { array_append(&ctx->node_path, &node, 1); ctx->parent_pos = str_len(ctx->path_str); node = node->children; ctx->first_child = TRUE; } else if (node->next != NULL) { node = node->next; } else { nodes = array_get(&ctx->node_path, &count); node = NULL; for (i = count; i != 0; i--) { unsigned int len = strlen(nodes[i-1]->name) + 1; i_assert(len <= ctx->parent_pos); ctx->parent_pos -= len; if (nodes[i-1]->next != NULL) { node = nodes[i-1]->next; ctx->first_child = TRUE; i--; if (ctx->parent_pos != 0) ctx->parent_pos--; break; } } array_delete(&ctx->node_path, i, count - i); } ctx->next_node = node; } struct mailbox_node * mailbox_tree_iterate_next(struct mailbox_tree_iterate_context *ctx, const char **path_r) { struct mailbox_node *node; do { node = ctx->next_node; if (node == NULL) return NULL; str_truncate(ctx->path_str, ctx->parent_pos); if (ctx->first_child) { ctx->first_child = FALSE; if (node->parent != NULL) { str_append_c(ctx->path_str, ctx->separator); ctx->parent_pos++; } } str_append(ctx->path_str, node->name); mailbox_tree_iterate_set_next_node(ctx); } while ((node->flags & ctx->flags_mask) != ctx->flags_mask); *path_r = str_c(ctx->path_str); return node; } void mailbox_tree_iterate_deinit(struct mailbox_tree_iterate_context **_ctx) { struct mailbox_tree_iterate_context *ctx = *_ctx; *_ctx = NULL; str_free(&ctx->path_str); array_free(&ctx->node_path); i_free(ctx); }