FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/tests/checkasm/ext/src/function.c
Date: 2026-07-19 12:25:31
Exec Total Coverage
Lines: 66 66 100.0%
Functions: 7 7 100.0%
Branches: 62 64 96.9%

Line Branch Exec Source
1 /*
2 * Copyright © 2025, Niklas Haas
3 * Copyright © 2018, VideoLAN and dav1d authors
4 * Copyright © 2018, Two Orioles, LLC
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32
33 #include "function.h"
34 #include "internal.h"
35
36 /* Deallocate a tree */
37 26805 static void func_uninit(CheckasmFunc *const f)
38 {
39
2/2
✓ Branch 0 taken 13451 times.
✓ Branch 1 taken 13354 times.
26805 if (!f)
40 13451 return;
41
42 13354 CheckasmFuncVersion *v = f->versions.next;
43
2/2
✓ Branch 0 taken 15364 times.
✓ Branch 1 taken 13354 times.
28718 while (v) {
44 15364 CheckasmFuncVersion *next = v->next;
45 15364 free(v->suffix);
46 15364 free(v);
47 15364 v = next;
48 }
49
50 13354 CheckasmFunc *const left = f->child[0];
51 13354 CheckasmFunc *const right = f->child[1];
52 13354 free(f->report_name);
53 13354 free(f);
54
55 13354 func_uninit(right);
56 13354 func_uninit(left);
57 }
58
59 97 void checkasm_func_tree_uninit(CheckasmFuncTree *tree)
60 {
61 97 func_uninit(tree->root);
62 97 memset(tree, 0, sizeof(*tree));
63 97 }
64
65 #define is_digit(x) ((x) >= '0' && (x) <= '9')
66
67 /* ASCIIbetical sort except preserving natural order for numbers */
68 1816298 static int cmp_func_names(const char *a, const char *b)
69 {
70 1816298 const char *const start = a;
71
72 int ascii_diff, digit_diff;
73
4/4
✓ Branch 0 taken 30617746 times.
✓ Branch 1 taken 1634936 times.
✓ Branch 2 taken 30436384 times.
✓ Branch 3 taken 181362 times.
32252682 for (; !(ascii_diff = *(const unsigned char *) a - *(const unsigned char *) b) && *a;
74 30436384 a++, b++)
75 ;
76
8/8
✓ Branch 0 taken 3043735 times.
✓ Branch 1 taken 288119 times.
✓ Branch 2 taken 1804514 times.
✓ Branch 3 taken 1239221 times.
✓ Branch 4 taken 1718971 times.
✓ Branch 5 taken 85543 times.
✓ Branch 6 taken 1515556 times.
✓ Branch 7 taken 203415 times.
3331854 for (; is_digit(*a) && is_digit(*b); a++, b++)
77 ;
78
79
16/16
✓ Branch 0 taken 1742646 times.
✓ Branch 1 taken 73652 times.
✓ Branch 2 taken 1740743 times.
✓ Branch 3 taken 1903 times.
✓ Branch 4 taken 1234599 times.
✓ Branch 5 taken 506144 times.
✓ Branch 6 taken 988249 times.
✓ Branch 7 taken 246350 times.
✓ Branch 8 taken 258007 times.
✓ Branch 9 taken 730242 times.
✓ Branch 10 taken 928715 times.
✓ Branch 11 taken 305884 times.
✓ Branch 12 taken 185694 times.
✓ Branch 13 taken 743021 times.
✓ Branch 14 taken 443701 times.
✓ Branch 15 taken 790898 times.
1816298 if (a > start && is_digit(a[-1]) && (digit_diff = is_digit(*a) - is_digit(*b)))
80 443701 return digit_diff;
81
82 1372597 return ascii_diff;
83 }
84
85 /* Perform a tree rotation in the specified direction and return the new root */
86 12861 static CheckasmFunc *tree_rotate(CheckasmFunc *const f, const int dir)
87 {
88 12861 CheckasmFunc *const r = f->child[dir ^ 1];
89
90 12861 f->child[dir ^ 1] = r->child[dir];
91 12861 r->child[dir] = f;
92 12861 r->color = f->color;
93 12861 f->color = 0;
94 12861 return r;
95 }
96
97 #define is_red(f) ((f) && !(f)->color)
98
99 /* Balance a left-leaning red-black tree at the specified node */
100 121313 static void tree_balance(CheckasmFunc **const root)
101 {
102 121313 CheckasmFunc *const f = *root;
103
104
8/8
✓ Branch 0 taken 115185 times.
✓ Branch 1 taken 6128 times.
✓ Branch 2 taken 48726 times.
✓ Branch 3 taken 66459 times.
✓ Branch 4 taken 43625 times.
✓ Branch 5 taken 5101 times.
✓ Branch 6 taken 9606 times.
✓ Branch 7 taken 34019 times.
121313 if (is_red(f->child[0]) && is_red(f->child[1])) {
105 9606 f->color ^= 1;
106 9606 f->child[0]->color = f->child[1]->color = 1;
107
7/8
✓ Branch 0 taken 105579 times.
✓ Branch 1 taken 6128 times.
✓ Branch 2 taken 66459 times.
✓ Branch 3 taken 39120 times.
✓ Branch 4 taken 72587 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9342 times.
✓ Branch 7 taken 63245 times.
111707 } else if (!is_red(f->child[0]) && is_red(f->child[1]))
108 9342 *root = tree_rotate(f, 0); /* Rotate left */
109
7/8
✓ Branch 0 taken 102365 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39120 times.
✓ Branch 3 taken 63245 times.
✓ Branch 4 taken 35806 times.
✓ Branch 5 taken 3314 times.
✓ Branch 6 taken 3519 times.
✓ Branch 7 taken 32287 times.
102365 else if (is_red(f->child[0]) && is_red(f->child[0]->child[0]))
110 3519 *root = tree_rotate(f, 1); /* Rotate right */
111 121313 }
112
113 /* Get a node with the specified name, creating it if it doesn't exist; returns
114 * 1 if a new node was inserted, 0 otherwise. */
115 1829652 static int func_get(CheckasmFunc **const root, const char *const name,
116 CheckasmFunc **const out_func)
117 {
118 1829652 CheckasmFunc *f = *root;
119
2/2
✓ Branch 0 taken 13354 times.
✓ Branch 1 taken 1816298 times.
1829652 if (!f) {
120 /* Allocate and insert a new node into the tree */
121 13354 const size_t name_length = strlen(name) + 1;
122 13354 f = checkasm_mallocz(offsetof(CheckasmFunc, name) + name_length);
123 13354 memcpy(f->name, name, name_length);
124 13354 *out_func = *root = f;
125 13354 return 1;
126 }
127
128 /* Search the tree for a matching node */
129 1816298 const int cmp = cmp_func_names(name, f->name);
130
2/2
✓ Branch 0 taken 181362 times.
✓ Branch 1 taken 1634936 times.
1816298 if (!cmp) {
131 181362 *out_func = f;
132 181362 return 0;
133 }
134
135 1634936 int inserted = func_get(&f->child[cmp > 0], name, out_func);
136
2/2
✓ Branch 0 taken 121313 times.
✓ Branch 1 taken 1513623 times.
1634936 if (inserted)
137 121313 tree_balance(root); /* Rebalance the tree on the way up */
138 1634936 return inserted;
139 }
140
141 194716 CheckasmFunc *checkasm_func_get(CheckasmFuncTree *tree, const char *const name)
142 {
143 194716 CheckasmFunc *func = NULL;
144 194716 int inserted = func_get(&tree->root, name, &func);
145
2/2
✓ Branch 0 taken 13354 times.
✓ Branch 1 taken 181362 times.
194716 if (inserted)
146 13354 tree->root->color = 1; /* Ensure root is black */
147 194716 return func;
148 }
149