Coverage Report

Created: 2025-09-04 06:50

/src/mupdf/source/fitz/tree.c
Line
Count
Source (jump to first uncovered line)
1
// Copyright (C) 2004-2021 Artifex Software, Inc.
2
//
3
// This file is part of MuPDF.
4
//
5
// MuPDF is free software: you can redistribute it and/or modify it under the
6
// terms of the GNU Affero General Public License as published by the Free
7
// Software Foundation, either version 3 of the License, or (at your option)
8
// any later version.
9
//
10
// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13
// details.
14
//
15
// You should have received a copy of the GNU Affero General Public License
16
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17
//
18
// Alternative licensing terms are available from the licensor.
19
// For commercial licensing, see <https://www.artifex.com/> or contact
20
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21
// CA 94129, USA, for further information.
22
23
#include "mupdf/fitz.h"
24
25
#include <string.h>
26
27
/* AA-tree */
28
29
struct fz_tree
30
{
31
  char *key;
32
  void *value;
33
  fz_tree *left, *right;
34
  int level;
35
};
36
37
static fz_tree tree_sentinel = { "", NULL, &tree_sentinel, &tree_sentinel, 0 };
38
39
static fz_tree *fz_tree_new_node(fz_context *ctx, const char *key, void *value)
40
0
{
41
0
  fz_tree *node = fz_malloc_struct(ctx, fz_tree);
42
0
  fz_try(ctx)
43
0
  {
44
0
    node->key = fz_strdup(ctx, key);
45
0
    node->value = value;
46
0
    node->left = node->right = &tree_sentinel;
47
0
    node->level = 1;
48
0
  }
49
0
  fz_catch(ctx)
50
0
  {
51
0
    fz_free(ctx, node);
52
0
    fz_rethrow(ctx);
53
0
  }
54
0
  return node;
55
0
}
56
57
void *fz_tree_lookup(fz_context *ctx, fz_tree *node, const char *key)
58
0
{
59
0
  if (node)
60
0
  {
61
0
    while (node != &tree_sentinel)
62
0
    {
63
0
      int c = strcmp(key, node->key);
64
0
      if (c == 0)
65
0
        return node->value;
66
0
      else if (c < 0)
67
0
        node = node->left;
68
0
      else
69
0
        node = node->right;
70
0
    }
71
0
  }
72
0
  return NULL;
73
0
}
74
75
static fz_tree *fz_tree_skew(fz_tree *node)
76
0
{
77
0
  if (node->level != 0)
78
0
  {
79
0
    if (node->left->level == node->level)
80
0
    {
81
0
      fz_tree *save = node;
82
0
      node = node->left;
83
0
      save->left = node->right;
84
0
      node->right = save;
85
0
    }
86
0
    node->right = fz_tree_skew(node->right);
87
0
  }
88
0
  return node;
89
0
}
90
91
static fz_tree *fz_tree_split(fz_tree *node)
92
0
{
93
0
  if (node->level != 0 && node->right->right->level == node->level)
94
0
  {
95
0
    fz_tree *save = node;
96
0
    node = node->right;
97
0
    save->right = node->left;
98
0
    node->left = save;
99
0
    node->level++;
100
0
    node->right = fz_tree_split(node->right);
101
0
  }
102
0
  return node;
103
0
}
104
105
fz_tree *fz_tree_insert(fz_context *ctx, fz_tree *node, const char *key, void *value)
106
0
{
107
0
  if (node && node != &tree_sentinel)
108
0
  {
109
0
    int c = strcmp(key, node->key);
110
0
    if (c < 0)
111
0
      node->left = fz_tree_insert(ctx, node->left, key, value);
112
0
    else
113
0
      node->right = fz_tree_insert(ctx, node->right, key, value);
114
0
    node = fz_tree_skew(node);
115
0
    node = fz_tree_split(node);
116
0
    return node;
117
0
  }
118
0
  else
119
0
  {
120
0
    return fz_tree_new_node(ctx, key, value);
121
0
  }
122
0
}
123
124
void fz_drop_tree(fz_context *ctx, fz_tree *node, void (*dropfunc)(fz_context *ctx, void *value))
125
0
{
126
0
  if (node)
127
0
  {
128
0
    if (node->left != &tree_sentinel)
129
0
      fz_drop_tree(ctx, node->left, dropfunc);
130
0
    if (node->right != &tree_sentinel)
131
0
      fz_drop_tree(ctx, node->right, dropfunc);
132
0
    fz_free(ctx, node->key);
133
0
    if (dropfunc)
134
0
      dropfunc(ctx, node->value);
135
0
    fz_free(ctx, node);
136
0
  }
137
0
}