1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
/* Copyright (c) 2014-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "message-part.h"
static const struct message_part *
message_part_root(const struct message_part *part)
{
while (part->parent != NULL)
part = part->parent;
return part;
}
static bool message_part_find(const struct message_part *siblings,
const struct message_part *part,
unsigned int *n)
{
const struct message_part *p;
for (p = siblings; p != NULL; p = p->next) {
if (p == part)
return TRUE;
*n += 1;
if (message_part_find(p->children, part, n))
return TRUE;
}
return FALSE;
}
unsigned int message_part_to_idx(const struct message_part *part)
{
const struct message_part *root;
unsigned int n = 0;
root = message_part_root(part);
if (!message_part_find(root, part, &n))
i_unreached();
return n;
}
static struct message_part *
message_sub_part_by_idx(struct message_part *parts,
unsigned int idx)
{
struct message_part *part = parts;
for (; part != NULL && idx > 0; part = part->next) {
if (part->children_count >= idx)
return message_sub_part_by_idx(part->children, idx-1);
idx -= part->children_count + 1;
}
return part;
}
struct message_part *
message_part_by_idx(struct message_part *parts, unsigned int idx)
{
i_assert(parts->parent == NULL);
return message_sub_part_by_idx(parts, idx);
}
bool message_part_is_equal(const struct message_part *p1,
const struct message_part *p2)
{
/* This cannot be p1 && p2, because then we would return
TRUE when either part is NULL, and we should return FALSE */
while (p1 != NULL || p2 != NULL) {
/* If either part is NULL, return false */
if ((p1 != NULL) != (p2 != NULL))
return FALSE;
/* Expect that both either have children, or both
do not have children */
if ((p1->children != NULL) != (p2->children != NULL))
return FALSE;
/* If there are children, ensure they are equal */
if (p1->children != NULL) {
if (!message_part_is_equal(p1->children, p2->children))
return FALSE;
}
/* If any of these properties differ, then parts are not equal */
if (p1->physical_pos != p2->physical_pos ||
p1->header_size.physical_size != p2->header_size.physical_size ||
p1->header_size.virtual_size != p2->header_size.virtual_size ||
p1->header_size.lines != p2->header_size.lines ||
p1->body_size.physical_size != p2->body_size.physical_size ||
p1->body_size.virtual_size != p2->body_size.virtual_size ||
p1->body_size.lines != p2->body_size.lines ||
p1->children_count != p2->children_count ||
p1->flags != p2->flags)
return FALSE;
/* Move forward */
p1 = p1->next;
p2 = p2->next;
}
/* Parts are equal */
return TRUE;
}
|