FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/tests/checkasm/ext/src/function.c
Date: 2026-06-05 12:34:59
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 28861 static void func_uninit(CheckasmFunc *const f)
38 {
39
2/2
✓ Branch 0 taken 14479 times.
✓ Branch 1 taken 14382 times.
28861 if (!f)
40 14479 return;
41
42 14382 CheckasmFuncVersion *v = f->versions.next;
43
2/2
✓ Branch 0 taken 15560 times.
✓ Branch 1 taken 14382 times.
29942 while (v) {
44 15560 CheckasmFuncVersion *next = v->next;
45 15560 free(v->suffix);
46 15560 free(v);
47 15560 v = next;
48 }
49
50 14382 CheckasmFunc *const left = f->child[0];
51 14382 CheckasmFunc *const right = f->child[1];
52 14382 free(f->report_name);
53 14382 free(f);
54
55 14382 func_uninit(right);
56 14382 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 1769106 static int cmp_func_names(const char *a, const char *b)
69 {
70 1769106 const char *const start = a;
71
72 int ascii_diff, digit_diff;
73
4/4
✓ Branch 0 taken 29749435 times.
✓ Branch 1 taken 1595031 times.
✓ Branch 2 taken 29575360 times.
✓ Branch 3 taken 174075 times.
31344466 for (; !(ascii_diff = *(const unsigned char *) a - *(const unsigned char *) b) && *a;
74 29575360 a++, b++)
75 ;
76
8/8
✓ Branch 0 taken 3022187 times.
✓ Branch 1 taken 276333 times.
✓ Branch 2 taken 1813175 times.
✓ Branch 3 taken 1209012 times.
✓ Branch 4 taken 1727480 times.
✓ Branch 5 taken 85695 times.
✓ Branch 6 taken 1529414 times.
✓ Branch 7 taken 198066 times.
3298520 for (; is_digit(*a) && is_digit(*b); a++, b++)
77 ;
78
79
16/16
✓ Branch 0 taken 1689893 times.
✓ Branch 1 taken 79213 times.
✓ Branch 2 taken 1686940 times.
✓ Branch 3 taken 2953 times.
✓ Branch 4 taken 1226619 times.
✓ Branch 5 taken 460321 times.
✓ Branch 6 taken 989120 times.
✓ Branch 7 taken 237499 times.
✓ Branch 8 taken 253241 times.
✓ Branch 9 taken 735879 times.
✓ Branch 10 taken 928177 times.
✓ Branch 11 taken 298442 times.
✓ Branch 12 taken 180768 times.
✓ Branch 13 taken 747409 times.
✓ Branch 14 taken 434009 times.
✓ Branch 15 taken 792610 times.
1769106 if (a > start && is_digit(a[-1]) && (digit_diff = is_digit(*a) - is_digit(*b)))
80 434009 return digit_diff;
81
82 1335097 return ascii_diff;
83 }
84
85 /* Perform a tree rotation in the specified direction and return the new root */
86 13930 static CheckasmFunc *tree_rotate(CheckasmFunc *const f, const int dir)
87 {
88 13930 CheckasmFunc *const r = f->child[dir ^ 1];
89
90 13930 f->child[dir ^ 1] = r->child[dir];
91 13930 r->child[dir] = f;
92 13930 r->color = f->color;
93 13930 f->color = 0;
94 13930 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 132285 static void tree_balance(CheckasmFunc **const root)
101 {
102 132285 CheckasmFunc *const f = *root;
103
104
8/8
✓ Branch 0 taken 125625 times.
✓ Branch 1 taken 6660 times.
✓ Branch 2 taken 53333 times.
✓ Branch 3 taken 72292 times.
✓ Branch 4 taken 47779 times.
✓ Branch 5 taken 5554 times.
✓ Branch 6 taken 10361 times.
✓ Branch 7 taken 37418 times.
132285 if (is_red(f->child[0]) && is_red(f->child[1])) {
105 10361 f->color ^= 1;
106 10361 f->child[0]->color = f->child[1]->color = 1;
107
7/8
✓ Branch 0 taken 115264 times.
✓ Branch 1 taken 6660 times.
✓ Branch 2 taken 72292 times.
✓ Branch 3 taken 42972 times.
✓ Branch 4 taken 78952 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10139 times.
✓ Branch 7 taken 68813 times.
121924 } else if (!is_red(f->child[0]) && is_red(f->child[1]))
108 10139 *root = tree_rotate(f, 0); /* Rotate left */
109
7/8
✓ Branch 0 taken 111785 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42972 times.
✓ Branch 3 taken 68813 times.
✓ Branch 4 taken 39450 times.
✓ Branch 5 taken 3522 times.
✓ Branch 6 taken 3791 times.
✓ Branch 7 taken 35659 times.
111785 else if (is_red(f->child[0]) && is_red(f->child[0]->child[0]))
110 3791 *root = tree_rotate(f, 1); /* Rotate right */
111 132285 }
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 1783488 static int func_get(CheckasmFunc **const root, const char *const name,
116 CheckasmFunc **const out_func)
117 {
118 1783488 CheckasmFunc *f = *root;
119
2/2
✓ Branch 0 taken 14382 times.
✓ Branch 1 taken 1769106 times.
1783488 if (!f) {
120 /* Allocate and insert a new node into the tree */
121 14382 const size_t name_length = strlen(name) + 1;
122 14382 f = checkasm_mallocz(offsetof(CheckasmFunc, name) + name_length);
123 14382 memcpy(f->name, name, name_length);
124 14382 *out_func = *root = f;
125 14382 return 1;
126 }
127
128 /* Search the tree for a matching node */
129 1769106 const int cmp = cmp_func_names(name, f->name);
130
2/2
✓ Branch 0 taken 174075 times.
✓ Branch 1 taken 1595031 times.
1769106 if (!cmp) {
131 174075 *out_func = f;
132 174075 return 0;
133 }
134
135 1595031 int inserted = func_get(&f->child[cmp > 0], name, out_func);
136
2/2
✓ Branch 0 taken 132285 times.
✓ Branch 1 taken 1462746 times.
1595031 if (inserted)
137 132285 tree_balance(root); /* Rebalance the tree on the way up */
138 1595031 return inserted;
139 }
140
141 188457 CheckasmFunc *checkasm_func_get(CheckasmFuncTree *tree, const char *const name)
142 {
143 188457 CheckasmFunc *func = NULL;
144 188457 int inserted = func_get(&tree->root, name, &func);
145
2/2
✓ Branch 0 taken 14382 times.
✓ Branch 1 taken 174075 times.
188457 if (inserted)
146 14382 tree->root->color = 1; /* Ensure root is black */
147 188457 return func;
148 }
149