[dovecot-cvs] dovecot/src/lib-mail message-parser.c, 1.84, 1.85 message-parser.h, 1.36, 1.37

tss at dovecot.org tss at dovecot.org
Tue Apr 3 19:22:43 EEST 2007


Update of /var/lib/cvs/dovecot/src/lib-mail
In directory talvi:/tmp/cvs-serv2553/lib-mail

Modified Files:
	message-parser.c message-parser.h 
Log Message:
Removed message_parse_from_parts(). Added message_parser_init_from_parts()
instead. Searching code now uses it whenever possible.



Index: message-parser.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-mail/message-parser.c,v
retrieving revision 1.84
retrieving revision 1.85
diff -u -d -r1.84 -r1.85
--- message-parser.c	27 Mar 2007 21:56:53 -0000	1.84
+++ message-parser.c	3 Apr 2007 16:22:40 -0000	1.85
@@ -37,6 +37,7 @@
 	int (*parse_next_block)(struct message_parser_ctx *ctx,
 				struct message_block *block_r);
 
+	unsigned int return_body_blocks:1;
 	unsigned int part_seen_content_type:1;
 };
 
@@ -48,6 +49,8 @@
 				       struct message_block *block_r);
 static int parse_next_body_to_eof(struct message_parser_ctx *ctx,
 				  struct message_block *block_r);
+static int preparsed_parse_next_header_init(struct message_parser_ctx *ctx,
+					    struct message_block *block_r);
 
 static struct message_boundary *
 boundary_find(struct message_boundary *boundaries,
@@ -538,6 +541,123 @@
 	return parse_next_header(ctx, block_r);
 }
 
+static int preparsed_parse_eof(struct message_parser_ctx *ctx __attr_unused__,
+			       struct message_block *block_r __attr_unused__)
+{
+	return -1;
+}
+
+static void preparsed_skip_to_next(struct message_parser_ctx *ctx)
+{
+	ctx->parse_next_block = preparsed_parse_next_header_init;
+	while (ctx->part != NULL) {
+		if (ctx->part->next != NULL) {
+			ctx->part = ctx->part->next;
+			break;
+		}
+		ctx->part = ctx->part->parent;
+	}
+	if (ctx->part == NULL)
+		ctx->parse_next_block = preparsed_parse_eof;
+}
+
+static int preparsed_parse_body_finish(struct message_parser_ctx *ctx,
+				       struct message_block *block_r)
+{
+	i_stream_skip(ctx->input, ctx->skip);
+	ctx->skip = 0;
+
+	preparsed_skip_to_next(ctx);
+	return ctx->parse_next_block(ctx, block_r);
+}
+
+static int preparsed_parse_body_more(struct message_parser_ctx *ctx,
+				     struct message_block *block_r)
+{
+	uoff_t end_offset = ctx->part->physical_pos +
+		ctx->part->header_size.physical_size +
+		ctx->part->body_size.physical_size;
+	int ret;
+
+	ret = message_parser_read_more(ctx, block_r);
+	if (ret <= 0)
+		return ret;
+
+	if (ctx->input->v_offset + block_r->size >= end_offset) {
+		block_r->size = end_offset - ctx->input->v_offset;
+		ctx->parse_next_block = preparsed_parse_body_finish;
+	}
+	ctx->skip = block_r->size;
+	return 1;
+}
+
+static int preparsed_parse_body_init(struct message_parser_ctx *ctx,
+				     struct message_block *block_r)
+{
+	uoff_t offset = ctx->part->physical_pos +
+		ctx->part->header_size.physical_size;
+
+	i_assert(offset >= ctx->input->v_offset);
+	i_stream_skip(ctx->input, offset - ctx->input->v_offset);
+
+	ctx->parse_next_block = preparsed_parse_body_more;
+	return preparsed_parse_body_more(ctx, block_r);
+}
+
+static int preparsed_parse_finish_header(struct message_parser_ctx *ctx,
+					 struct message_block *block_r)
+{
+	if (ctx->part->children != NULL) {
+		ctx->parse_next_block = preparsed_parse_next_header_init;
+		ctx->part = ctx->part->children;
+	} else if (ctx->return_body_blocks) {
+		ctx->parse_next_block = preparsed_parse_body_init;
+	} else {
+		preparsed_skip_to_next(ctx);
+	}
+	return ctx->parse_next_block(ctx, block_r);
+}
+
+static int preparsed_parse_next_header(struct message_parser_ctx *ctx,
+				       struct message_block *block_r)
+{
+	struct message_header_line *hdr;
+	int ret;
+
+	ret = message_parse_header_next(ctx->hdr_parser_ctx, &hdr);
+	if (ret == 0 || (ret < 0 && ctx->input->stream_errno != 0))
+		return ret;
+
+	if (hdr != NULL) {
+		block_r->hdr = hdr;
+		block_r->size = 0;
+		return 1;
+	}
+	message_parse_header_deinit(&ctx->hdr_parser_ctx);
+
+	ctx->parse_next_block = preparsed_parse_finish_header;
+
+	/* return empty block as end of headers */
+	block_r->hdr = NULL;
+	block_r->size = 0;
+	return 1;
+}
+
+static int preparsed_parse_next_header_init(struct message_parser_ctx *ctx,
+					    struct message_block *block_r)
+{
+	i_assert(ctx->hdr_parser_ctx == NULL);
+
+	i_assert(ctx->part->physical_pos >= ctx->input->v_offset);
+	i_stream_skip(ctx->input, ctx->part->physical_pos -
+		      ctx->input->v_offset);
+
+	ctx->hdr_parser_ctx = message_parse_header_init(ctx->input, NULL, TRUE);
+
+	ctx->parse_next_block = preparsed_parse_next_header;
+	return preparsed_parse_next_header(ctx, block_r);
+}
+
 struct message_parser_ctx *
 message_parser_init(pool_t part_pool, struct istream *input)
 {
@@ -549,11 +669,25 @@
 	ctx->parser_pool = pool;
 	ctx->part_pool = part_pool;
 	ctx->input = input;
-	ctx->parts = ctx->part = p_new(part_pool, struct message_part, 1);
+	ctx->parts = ctx->part = part_pool == NULL ? NULL :
+		p_new(part_pool, struct message_part, 1);
 	ctx->parse_next_block = parse_next_header_init;
 	return ctx;
 }
 
+struct message_parser_ctx *
+message_parser_init_from_parts(struct message_part *parts,
+			       struct istream *input, bool return_body_blocks)
+{
+	struct message_parser_ctx *ctx;
+
+	ctx = message_parser_init(NULL, input);
+	ctx->return_body_blocks = return_body_blocks;
+	ctx->parts = ctx->part = parts;
+	ctx->parse_next_block = preparsed_parse_next_header_init;
+	return ctx;
+}
+
 struct message_part *message_parser_deinit(struct message_parser_ctx **_ctx)
 {
         struct message_parser_ctx *ctx = *_ctx;
@@ -588,7 +722,7 @@
 
 	block_r->part = ctx->part;
 
-	if (ret < 0) {
+	if (ret < 0 && ctx->part != NULL) {
 		i_assert(ctx->input->eof);
 		while (ctx->part->parent != NULL) {
 			message_size_add(&ctx->part->parent->body_size,
@@ -642,46 +776,6 @@
 	i_assert(ret != 0);
 }
 
-static void part_parse_headers(struct message_part *part, struct istream *input,
-			       message_part_header_callback_t *callback,
-			       void *context)
-{
-	struct message_header_parser_ctx *hdr_ctx;
-	struct message_header_line *hdr;
-	int ret;
-
-	while (part != NULL) {
-		/* note that we want to parse the header of all
-		   the message parts, multiparts too. */
-		i_assert(part->physical_pos >= input->v_offset);
-		i_stream_skip(input, part->physical_pos - input->v_offset);
-
-		hdr_ctx = message_parse_header_init(input, NULL, TRUE);
-		while ((ret = message_parse_header_next(hdr_ctx, &hdr)) > 0)
-			callback(part, hdr, context);
-		i_assert(ret != 0);
-		message_parse_header_deinit(&hdr_ctx);
-
-		/* call after the final skipping */
-		callback(part, NULL, context);
-
-		if (part->children != NULL) {
-			part_parse_headers(part->children, input,
-					   callback, context);
-		}
-
-		part = part->next;
-	}
-}
-
-#undef message_parse_from_parts
-void message_parse_from_parts(struct message_part *part, struct istream *input,
-			      message_part_header_callback_t *callback,
-			      void *context)
-{
-	part_parse_headers(part, input, callback, context);
-}
-
 static void
 message_parser_set_crlfs_diff(struct message_part *parts, bool use_crlf,
 			      off_t diff)

Index: message-parser.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-mail/message-parser.h,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -d -r1.36 -r1.37
--- message-parser.h	15 Dec 2006 18:10:57 -0000	1.36
+++ message-parser.h	3 Apr 2007 16:22:40 -0000	1.37
@@ -61,6 +61,10 @@
    are allocated from. */
 struct message_parser_ctx *
 message_parser_init(pool_t part_pool, struct istream *input);
+/* Use preparsed parts to speed up parsing. */
+struct message_parser_ctx *
+message_parser_init_from_parts(struct message_part *parts,
+			       struct istream *input, bool return_body_blocks);
 struct message_part *message_parser_deinit(struct message_parser_ctx **ctx);
 
 /* Read the next block of a message. Returns 1 if block is returned, 0 if
@@ -104,22 +108,6 @@
 		(message_part_header_callback_t *)callback, context)
 #endif
 
-/* callback is called for each field in message header. */
-void message_parse_from_parts(struct message_part *part, struct istream *input,
-			      message_part_header_callback_t *callback,
-			      void *context);
-#ifdef CONTEXT_TYPE_SAFETY
-#  define message_parse_from_parts(part, input, callback, context) \
-	({(void)(1 ? 0 : callback((struct message_part *)0, \
-				  (struct message_header_line *)0, context)); \
-	  message_parse_from_parts(part, input, \
-		(message_part_header_callback_t *)callback, context); })
-#else
-#  define message_parse_from_parts(part, input, callback, context) \
-	  message_parse_from_parts(part, input, \
-		(message_part_header_callback_t *)callback, context)
-#endif
-
 /* Update the physical_size of all parts. If use_crlf is TRUE, they're set
    to same as virtual_size. If use_crlf is FALSE, they're set to
    virtual_size - lines. physical_pos fields are also updated. */



More information about the dovecot-cvs mailing list