FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/tests/checkasm/ext/src/function.c
Date: 2026-09-05 04:28:30
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 26866 static void func_uninit(CheckasmFunc *const f)
38 {
39
2/2
✓ Branch 0 taken 13482 times.
✓ Branch 1 taken 13384 times.
26866 if (!f)
40 13482 return;
41
42 13384 CheckasmFuncVersion *v = f->versions.next;
43
2/2
✓ Branch 0 taken 15398 times.
✓ Branch 1 taken 13384 times.
28782 while (v) {
44 15398 CheckasmFuncVersion *next = v->next;
45 15398 free(v->suffix);
46 15398 free(v);
47 15398 v = next;
48 }
49
50 13384 CheckasmFunc *const left = f->child[0];
51 13384 CheckasmFunc *const right = f->child[1];
52 13384 free(f->report_name);
53 13384 free(f);
54
55 13384 func_uninit(right);
56 13384 func_uninit(left);
57 }
58
59 98 void checkasm_func_tree_uninit(CheckasmFuncTree *tree)
60 {
61 98 func_uninit(tree->root);
62 98 memset(tree, 0, sizeof(*tree));
63 98 }
64
65 #define is_digit(x) ((x) >= '0' && (x) <= '9')
66
67 /* ASCIIbetical sort except preserving natural order for numbers */
68 1819731 static int cmp_func_names(const char *a, const char *b)
69 {
70 1819731 const char *const start = a;
71
72 int ascii_diff, digit_diff;
73
4/4
✓ Branch 0 taken 30637524 times.
✓ Branch 1 taken 1637960 times.
✓ Branch 2 taken 30455753 times.
✓ Branch 3 taken 181771 times.
32275484 for (; !(ascii_diff = *(const unsigned char *) a - *(const unsigned char *) b) && *a;
74 30455753 a++, b++)
75 ;
76
8/8
✓ Branch 0 taken 3047171 times.
✓ Branch 1 taken 288554 times.
✓ Branch 2 taken 1805139 times.
✓ Branch 3 taken 1242032 times.
✓ Branch 4 taken 1719497 times.
✓ Branch 5 taken 85642 times.
✓ Branch 6 taken 1515994 times.
✓ Branch 7 taken 203503 times.
3335725 for (; is_digit(*a) && is_digit(*b); a++, b++)
77 ;
78
79
16/16
✓ Branch 0 taken 1744874 times.
✓ Branch 1 taken 74857 times.
✓ Branch 2 taken 1742971 times.
✓ Branch 3 taken 1903 times.
✓ Branch 4 taken 1235274 times.
✓ Branch 5 taken 507697 times.
✓ Branch 6 taken 988689 times.
✓ Branch 7 taken 246585 times.
✓ Branch 8 taken 258137 times.
✓ Branch 9 taken 730552 times.
✓ Branch 10 taken 929069 times.
✓ Branch 11 taken 306205 times.
✓ Branch 12 taken 185845 times.
✓ Branch 13 taken 743224 times.
✓ Branch 14 taken 443982 times.
✓ Branch 15 taken 791292 times.
1819731 if (a > start && is_digit(a[-1]) && (digit_diff = is_digit(*a) - is_digit(*b)))
80 443982 return digit_diff;
81
82 1375749 return ascii_diff;
83 }
84
85 /* Perform a tree rotation in the specified direction and return the new root */
86 12894 static CheckasmFunc *tree_rotate(CheckasmFunc *const f, const int dir)
87 {
88 12894 CheckasmFunc *const r = f->child[dir ^ 1];
89
90 12894 f->child[dir ^ 1] = r->child[dir];
91 12894 r->child[dir] = f;
92 12894 r->color = f->color;
93 12894 f->color = 0;
94 12894 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 121545 static void tree_balance(CheckasmFunc **const root)
101 {
102 121545 CheckasmFunc *const f = *root;
103
104
8/8
✓ Branch 0 taken 115402 times.
✓ Branch 1 taken 6143 times.
✓ Branch 2 taken 48848 times.
✓ Branch 3 taken 66554 times.
✓ Branch 4 taken 43720 times.
✓ Branch 5 taken 5128 times.
✓ Branch 6 taken 9619 times.
✓ Branch 7 taken 34101 times.
121545 if (is_red(f->child[0]) && is_red(f->child[1])) {
105 9619 f->color ^= 1;
106 9619 f->child[0]->color = f->child[1]->color = 1;
107
7/8
✓ Branch 0 taken 105783 times.
✓ Branch 1 taken 6143 times.
✓ Branch 2 taken 66554 times.
✓ Branch 3 taken 39229 times.
✓ Branch 4 taken 72697 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9358 times.
✓ Branch 7 taken 63339 times.
111926 } else if (!is_red(f->child[0]) && is_red(f->child[1]))
108 9358 *root = tree_rotate(f, 0); /* Rotate left */
109
7/8
✓ Branch 0 taken 102568 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39229 times.
✓ Branch 3 taken 63339 times.
✓ Branch 4 taken 35900 times.
✓ Branch 5 taken 3329 times.
✓ Branch 6 taken 3536 times.
✓ Branch 7 taken 32364 times.
102568 else if (is_red(f->child[0]) && is_red(f->child[0]->child[0]))
110 3536 *root = tree_rotate(f, 1); /* Rotate right */
111 121545 }
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 1833115 static int func_get(CheckasmFunc **const root, const char *const name,
116 CheckasmFunc **const out_func)
117 {
118 1833115 CheckasmFunc *f = *root;
119
2/2
✓ Branch 0 taken 13384 times.
✓ Branch 1 taken 1819731 times.
1833115 if (!f) {
120 /* Allocate and insert a new node into the tree */
121 13384 const size_t name_length = strlen(name) + 1;
122 13384 f = checkasm_mallocz(offsetof(CheckasmFunc, name) + name_length);
123 13384 memcpy(f->name, name, name_length);
124 13384 *out_func = *root = f;
125 13384 return 1;
126 }
127
128 /* Search the tree for a matching node */
129 1819731 const int cmp = cmp_func_names(name, f->name);
130
2/2
✓ Branch 0 taken 181771 times.
✓ Branch 1 taken 1637960 times.
1819731 if (!cmp) {
131 181771 *out_func = f;
132 181771 return 0;
133 }
134
135 1637960 int inserted = func_get(&f->child[cmp > 0], name, out_func);
136
2/2
✓ Branch 0 taken 121545 times.
✓ Branch 1 taken 1516415 times.
1637960 if (inserted)
137 121545 tree_balance(root); /* Rebalance the tree on the way up */
138 1637960 return inserted;
139 }
140
141 195155 CheckasmFunc *checkasm_func_get(CheckasmFuncTree *tree, const char *const name)
142 {
143 195155 CheckasmFunc *func = NULL;
144 195155 int inserted = func_get(&tree->root, name, &func);
145
2/2
✓ Branch 0 taken 13384 times.
✓ Branch 1 taken 181771 times.
195155 if (inserted)
146 13384 tree->root->color = 1; /* Ensure root is black */
147 195155 return func;
148 }
149