]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-mail: message-parser - Optimize appending new part to linked list
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 23 Apr 2020 09:00:38 +0000 (12:00 +0300)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Wed, 27 May 2020 05:28:17 +0000 (08:28 +0300)
src/lib-mail/message-parser-private.h
src/lib-mail/message-parser.c

index 98a576eda4ac0e768daf1ecfe684236048c4627c..fd92a487768abd45fcc3b816a5e3a9c74858f140 100644 (file)
@@ -29,6 +29,9 @@ struct message_parser_ctx {
        const char *last_boundary;
        struct message_boundary *boundaries;
 
+       struct message_part **next_part;
+       ARRAY(struct message_part **) next_part_stack;
+
        size_t skip;
        char last_chr;
        unsigned int want_count;
index f19759c2579173c88427d81b629ce05d60588f7d..0f690ab689639a6e194a6b0404db9e59db9d1088 100644 (file)
@@ -1,7 +1,7 @@
 /* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
-#include "buffer.h"
+#include "array.h"
 #include "str.h"
 #include "istream.h"
 #include "rfc822-parser.h"
@@ -126,7 +126,7 @@ static void
 message_part_append(struct message_parser_ctx *ctx)
 {
        struct message_part *parent = ctx->part;
-       struct message_part *part, **list;
+       struct message_part *part;
 
        i_assert(parent != NULL);
        i_assert((parent->flags & (MESSAGE_PART_FLAG_MULTIPART |
@@ -141,16 +141,26 @@ message_part_append(struct message_parser_ctx *ctx)
                parent->body_size.physical_size +
                parent->header_size.physical_size;
 
-       list = &part->parent->children;
-       while (*list != NULL)
-               list = &(*list)->next;
+       /* add to parent's linked list */
+       *ctx->next_part = part;
+       /* update the parent's end-of-linked-list pointer */
+       struct message_part **next_part = &part->next;
+       array_push_back(&ctx->next_part_stack, &next_part);
+       /* This part is now the new parent for the next message_part_append()
+          call. Its linked list begins with the children pointer. */
+       ctx->next_part = &part->children;
 
-       *list = part;
        ctx->part = part;
 }
 
 static void message_part_finish(struct message_parser_ctx *ctx)
 {
+       struct message_part **const *parent_next_partp;
+
+       parent_next_partp = array_back(&ctx->next_part_stack);
+       array_pop_back(&ctx->next_part_stack);
+       ctx->next_part = *parent_next_partp;
+
        message_size_add(&ctx->part->parent->body_size, &ctx->part->body_size);
        message_size_add(&ctx->part->parent->body_size, &ctx->part->header_size);
        ctx->part->parent->children_count += 1 + ctx->part->children_count;
@@ -678,7 +688,9 @@ message_parser_init(pool_t part_pool, struct istream *input,
        ctx = message_parser_init_int(input, hdr_flags, flags);
        ctx->part_pool = part_pool;
        ctx->parts = ctx->part = p_new(part_pool, struct message_part, 1);
+       ctx->next_part = &ctx->part->children;
        ctx->parse_next_block = parse_next_header_init;
+       p_array_init(&ctx->next_part_stack, ctx->parser_pool, 4);
        return ctx;
 }