Coverage Report

Created: 2026-10-24 08:16

/work/toxcore/util.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: GPL-3.0-or-later
2
 * Copyright © 2016-2026 The TokTok team.
3
 * Copyright © 2013 Tox project.
4
 * Copyright © 2013 plutooo
5
 */
6
7
/**
8
 * Utilities.
9
 */
10
#ifndef _XOPEN_SOURCE
11
#define _XOPEN_SOURCE 600
12
#endif /* _XOPEN_SOURCE */
13
14
#include "util.h"
15
16
#include <stdio.h>
17
#include <string.h>
18
19
#include "ccompat.h"
20
#include "mem.h"
21
22
bool is_power_of_2(uint64_t x)
23
15
{
24
15
    return x != 0 && (x & (~x + 1)) == x;
25
15
}
26
27
void free_uint8_t_pointer_array(const Memory *mem, uint8_t **ary, size_t n_items)
28
7.69k
{
29
7.69k
    if (ary == nullptr) {
30
7.46k
        return;
31
7.46k
    }
32
33
3.89k
    for (size_t i = 0; i < n_items; ++i) {
34
3.65k
        if (ary[i] != nullptr) {
35
3.65k
            mem_delete(mem, ary[i]);
36
3.65k
        }
37
3.65k
    }
38
39
231
    mem_delete(mem, ary);
40
231
}
41
42
uint16_t data_checksum(const uint8_t *data, uint32_t length)
43
113k
{
44
113k
    uint8_t checksum[2] = {0};
45
113k
    uint16_t check;
46
47
4.19M
    for (uint32_t i = 0; i < length; ++i) {
48
4.08M
        checksum[i % 2] ^= data[i];
49
4.08M
    }
50
51
113k
    memcpy(&check, checksum, sizeof(check));
52
113k
    return check;
53
113k
}
54
55
int create_recursive_mutex(pthread_mutex_t *mutex)
56
108
{
57
108
    pthread_mutexattr_t attr;
58
59
108
    if (pthread_mutexattr_init(&attr) != 0) {
60
0
        return -1;
61
0
    }
62
63
108
    if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) {
64
0
        pthread_mutexattr_destroy(&attr);
65
0
        return -1;
66
0
    }
67
68
    /* Create queue mutex */
69
108
    if (pthread_mutex_init(mutex, &attr) != 0) {
70
0
        pthread_mutexattr_destroy(&attr);
71
0
        return -1;
72
0
    }
73
74
108
    pthread_mutexattr_destroy(&attr);
75
76
108
    return 0;
77
108
}
78
79
bool memeq(const uint8_t *a, size_t a_size, const uint8_t *b, size_t b_size)
80
48.1k
{
81
48.1k
    return a_size == b_size && memcmp(a, b, a_size) == 0;
82
48.1k
}
83
84
uint8_t *memdup(const Memory *mem, const uint8_t *data, size_t data_size)
85
5
{
86
5
    if (data == nullptr || data_size == 0) {
87
3
        return nullptr;
88
3
    }
89
90
2
    uint8_t *copy = (uint8_t *)mem_balloc(mem, data_size);
91
92
2
    if (copy != nullptr) {
93
2
        memcpy(copy, data, data_size);
94
2
    }
95
96
2
    return copy;
97
5
}
98
99
void memzero(uint8_t *data, size_t data_size)
100
2.79M
{
101
2.79M
    if (data == nullptr || data_size == 0) {
102
2.75k
        return;
103
2.75k
    }
104
105
2.79M
    memset(data, 0, data_size);
106
2.79M
}
107
108
int16_t max_s16(int16_t a, int16_t b)
109
0
{
110
0
    return a > b ? a : b;
111
0
}
112
int32_t max_s32(int32_t a, int32_t b)
113
77.2k
{
114
77.2k
    return a > b ? a : b;
115
77.2k
}
116
int64_t max_s64(int64_t a, int64_t b)
117
0
{
118
0
    return a > b ? a : b;
119
0
}
120
121
int16_t min_s16(int16_t a, int16_t b)
122
0
{
123
0
    return a < b ? a : b;
124
0
}
125
int32_t min_s32(int32_t a, int32_t b)
126
77.4k
{
127
77.4k
    return a < b ? a : b;
128
77.4k
}
129
int64_t min_s64(int64_t a, int64_t b)
130
0
{
131
0
    return a < b ? a : b;
132
0
}
133
134
uint8_t max_u08(uint8_t a, uint8_t b)
135
0
{
136
0
    return a > b ? a : b;
137
0
}
138
uint16_t max_u16(uint16_t a, uint16_t b)
139
0
{
140
0
    return a > b ? a : b;
141
0
}
142
uint32_t max_u32(uint32_t a, uint32_t b)
143
0
{
144
0
    return a > b ? a : b;
145
0
}
146
uint64_t max_u64(uint64_t a, uint64_t b)
147
691
{
148
691
    return a > b ? a : b;
149
691
}
150
151
uint16_t min_u16(uint16_t a, uint16_t b)
152
1.16M
{
153
1.16M
    return a < b ? a : b;
154
1.16M
}
155
uint32_t min_u32(uint32_t a, uint32_t b)
156
2.12M
{
157
2.12M
    return a < b ? a : b;
158
2.12M
}
159
uint64_t min_u64(uint64_t a, uint64_t b)
160
1.14k
{
161
1.14k
    return a < b ? a : b;
162
1.14k
}
163
164
int cmp_uint(uint64_t a, uint64_t b)
165
421k
{
166
421k
    return (a > b ? 1 : 0) - (a < b ? 1 : 0);
167
421k
}
168
169
uint32_t jenkins_one_at_a_time_hash(const uint8_t *key, size_t len)
170
347
{
171
347
    uint32_t hash = 0;
172
173
11.4k
    for (uint32_t i = 0; i < len; ++i) {
174
11.1k
        hash += key[i];
175
11.1k
        hash += (uint32_t)((uint64_t)hash << 10);
176
11.1k
        hash ^= hash >> 6;
177
11.1k
    }
178
179
347
    hash += (uint32_t)((uint64_t)hash << 3);
180
347
    hash ^= hash >> 11;
181
347
    hash += (uint32_t)((uint64_t)hash << 15);
182
347
    return hash;
183
347
}
184
185
void bytes_to_string(const uint8_t *bytes, size_t bytes_length, char *str, size_t str_length)
186
1.14M
{
187
1.14M
    if (str_length == 0) {
188
1
        return;
189
1
    }
190
191
1.14M
    if (bytes_length * 2 + 1 <= str_length) {
192
35.0k
        for (size_t i = 0; i < bytes_length; ++i) {
193
17.8k
            snprintf(&str[i * 2], str_length - i * 2, "%02X", bytes[i]);
194
17.8k
        }
195
17.1k
        str[bytes_length * 2] = '\0';
196
17.1k
        return;
197
17.1k
    }
198
199
1.12M
    if (str_length < 6) {
200
2
        snprintf(str, str_length, "...");
201
2
        return;
202
2
    }
203
204
1.12M
    const size_t start_chars = str_length - 6;
205
1.12M
    const size_t start_bytes = start_chars / 2;
206
207
1.12M
    size_t current_pos = 0;
208
11.2M
    for (size_t i = 0; i < start_bytes; ++i) {
209
10.1M
        snprintf(str + current_pos, str_length - current_pos, "%02X", bytes[i]);
210
10.1M
        current_pos += 2;
211
10.1M
    }
212
213
1.12M
    snprintf(str + current_pos, str_length - current_pos, "...");
214
1.12M
    current_pos += 3;
215
216
1.12M
    snprintf(str + current_pos, str_length - current_pos, "%02X", bytes[bytes_length - 1]);
217
1.12M
}