FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/tests/checkasm/ext/src/function.c
Date: 2026-09-26 05:01:43
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 26968 static void func_uninit(CheckasmFunc *const f)
38 {
39
2/2
✓ Branch 0 taken 13534 times.
✓ Branch 1 taken 13434 times.
26968 if (!f)
40 13534 return;
41
42 13434 CheckasmFuncVersion *v = f->versions.next;
43
2/2
✓ Branch 0 taken 15450 times.
✓ Branch 1 taken 13434 times.
28884 while (v) {
44 15450 CheckasmFuncVersion *next = v->next;
45 15450 free(v->suffix);
46 15450 free(v);
47 15450 v = next;
48 }
49
50 13434 CheckasmFunc *const left = f->child[0];
51 13434 CheckasmFunc *const right = f->child[1];
52 13434 free(f->report_name);
53 13434 free(f);
54
55 13434 func_uninit(right);
56 13434 func_uninit(left);
57 }
58
59 100 void checkasm_func_tree_uninit(CheckasmFuncTree *tree)
60 {
61 100 func_uninit(tree->root);
62 100 memset(tree, 0, sizeof(*tree));
63 100 }
64
65 #define is_digit(x) ((x) >= '0' && (x) <= '9')
66
67 /* ASCIIbetical sort except preserving natural order for numbers */
68 1829013 static int cmp_func_names(const char *a, const char *b)
69 {
70 1829013 const char *const start = a;
71
72 int ascii_diff, digit_diff;
73
4/4
✓ Branch 0 taken 30744105 times.
✓ Branch 1 taken 1646592 times.
✓ Branch 2 taken 30561684 times.
✓ Branch 3 taken 182421 times.
32390697 for (; !(ascii_diff = *(const unsigned char *) a - *(const unsigned char *) b) && *a;
74 30561684 a++, b++)
75 ;
76
8/8
✓ Branch 0 taken 3066529 times.
✓ Branch 1 taken 289204 times.
✓ Branch 2 taken 1818339 times.
✓ Branch 3 taken 1248190 times.
✓ Branch 4 taken 1732697 times.
✓ Branch 5 taken 85642 times.
✓ Branch 6 taken 1526720 times.
✓ Branch 7 taken 205977 times.
3355733 for (; is_digit(*a) && is_digit(*b); a++, b++)
77 ;
78
79
16/16
✓ Branch 0 taken 1754614 times.
✓ Branch 1 taken 74399 times.
✓ Branch 2 taken 1752711 times.
✓ Branch 3 taken 1903 times.
✓ Branch 4 taken 1239232 times.
✓ Branch 5 taken 513479 times.
✓ Branch 6 taken 992634 times.
✓ Branch 7 taken 246598 times.
✓ Branch 8 taken 260403 times.
✓ Branch 9 taken 732231 times.
✓ Branch 10 taken 933014 times.
✓ Branch 11 taken 306218 times.
✓ Branch 12 taken 187903 times.
✓ Branch 13 taken 745111 times.
✓ Branch 14 taken 448306 times.
✓ Branch 15 taken 790926 times.
1829013 if (a > start && is_digit(a[-1]) && (digit_diff = is_digit(*a) - is_digit(*b)))
80 448306 return digit_diff;
81
82 1380707 return ascii_diff;
83 }
84
85 /* Perform a tree rotation in the specified direction and return the new root */
86 12914 static CheckasmFunc *tree_rotate(CheckasmFunc *const f, const int dir)
87 {
88 12914 CheckasmFunc *const r = f->child[dir ^ 1];
89
90 12914 f->child[dir ^ 1] = r->child[dir];
91 12914 r->child[dir] = f;
92 12914 r->color = f->color;
93 12914 f->color = 0;
94 12914 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 122195 static void tree_balance(CheckasmFunc **const root)
101 {
102 122195 CheckasmFunc *const f = *root;
103
104
8/8
✓ Branch 0 taken 116040 times.
✓ Branch 1 taken 6155 times.
✓ Branch 2 taken 48787 times.
✓ Branch 3 taken 67253 times.
✓ Branch 4 taken 43647 times.
✓ Branch 5 taken 5140 times.
✓ Branch 6 taken 9666 times.
✓ Branch 7 taken 33981 times.
122195 if (is_red(f->child[0]) && is_red(f->child[1])) {
105 9666 f->color ^= 1;
106 9666 f->child[0]->color = f->child[1]->color = 1;
107
7/8
✓ Branch 0 taken 106374 times.
✓ Branch 1 taken 6155 times.
✓ Branch 2 taken 67253 times.
✓ Branch 3 taken 39121 times.
✓ Branch 4 taken 73408 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9377 times.
✓ Branch 7 taken 64031 times.
112529 } else if (!is_red(f->child[0]) && is_red(f->child[1]))
108 9377 *root = tree_rotate(f, 0); /* Rotate left */
109
7/8
✓ Branch 0 taken 103152 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39121 times.
✓ Branch 3 taken 64031 times.
✓ Branch 4 taken 35780 times.
✓ Branch 5 taken 3341 times.
✓ Branch 6 taken 3537 times.
✓ Branch 7 taken 32243 times.
103152 else if (is_red(f->child[0]) && is_red(f->child[0]->child[0]))
110 3537 *root = tree_rotate(f, 1); /* Rotate right */
111 122195 }
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 1842447 static int func_get(CheckasmFunc **const root, const char *const name,
116 CheckasmFunc **const out_func)
117 {
118 1842447 CheckasmFunc *f = *root;
119
2/2
✓ Branch 0 taken 13434 times.
✓ Branch 1 taken 1829013 times.
1842447 if (!f) {
120 /* Allocate and insert a new node into the tree */
121 13434 const size_t name_length = strlen(name) + 1;
122 13434 f = checkasm_mallocz(offsetof(CheckasmFunc, name) + name_length);
123 13434 memcpy(f->name, name, name_length);
124 13434 *out_func = *root = f;
125 13434 return 1;
126 }
127
128 /* Search the tree for a matching node */
129 1829013 const int cmp = cmp_func_names(name, f->name);
130
2/2
✓ Branch 0 taken 182421 times.
✓ Branch 1 taken 1646592 times.
1829013 if (!cmp) {
131 182421 *out_func = f;
132 182421 return 0;
133 }
134
135 1646592 int inserted = func_get(&f->child[cmp > 0], name, out_func);
136
2/2
✓ Branch 0 taken 122195 times.
✓ Branch 1 taken 1524397 times.
1646592 if (inserted)
137 122195 tree_balance(root); /* Rebalance the tree on the way up */
138 1646592 return inserted;
139 }
140
141 195855 CheckasmFunc *checkasm_func_get(CheckasmFuncTree *tree, const char *const name)
142 {
143 195855 CheckasmFunc *func = NULL;
144 195855 int inserted = func_get(&tree->root, name, &func);
145
2/2
✓ Branch 0 taken 13434 times.
✓ Branch 1 taken 182421 times.
195855 if (inserted)
146 13434 tree->root->color = 1; /* Ensure root is black */
147 195855 return func;
148 }
149