toxcore/util.c
Rama master · réplica de lectura del repositorio original.
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2016-2026 The TokTok team.
* Copyright © 2013 Tox project.
* Copyright © 2013 plutooo
*/
/**
* Utilities.
*/
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600
#endif /* _XOPEN_SOURCE */
#include "util.h"
#include <stdio.h>
#include <string.h>
#include "ccompat.h"
#include "mem.h"
bool is_power_of_2(uint64_t x)
{
return x != 0 && (x & (~x + 1)) == x;
}
void free_uint8_t_pointer_array(const Memory *mem, uint8_t **ary, size_t n_items)
{
if (ary == nullptr) {
return;
}
for (size_t i = 0; i < n_items; ++i) {
if (ary[i] != nullptr) {
mem_delete(mem, ary[i]);
}
}
mem_delete(mem, ary);
}
uint16_t data_checksum(const uint8_t *data, uint32_t length)
{
uint8_t checksum[2] = {0};
uint16_t check;
for (uint32_t i = 0; i < length; ++i) {
checksum[i % 2] ^= data[i];
}
memcpy(&check, checksum, sizeof(check));
return check;
}
int create_recursive_mutex(pthread_mutex_t *mutex)
{
pthread_mutexattr_t attr;
if (pthread_mutexattr_init(&attr) != 0) {
return -1;
}
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) {
pthread_mutexattr_destroy(&attr);
return -1;
}
/* Create queue mutex */
if (pthread_mutex_init(mutex, &attr) != 0) {
pthread_mutexattr_destroy(&attr);
return -1;
}
pthread_mutexattr_destroy(&attr);
return 0;
}
bool memeq(const uint8_t *a, size_t a_size, const uint8_t *b, size_t b_size)
{
return a_size == b_size && memcmp(a, b, a_size) == 0;
}
uint8_t *memdup(const Memory *mem, const uint8_t *data, size_t data_size)
{
if (data == nullptr || data_size == 0) {
return nullptr;
}
uint8_t *copy = (uint8_t *)mem_balloc(mem, data_size);
if (copy != nullptr) {
memcpy(copy, data, data_size);
}
return copy;
}
void memzero(uint8_t *data, size_t data_size)
{
if (data == nullptr || data_size == 0) {
return;
}
memset(data, 0, data_size);
}
int16_t max_s16(int16_t a, int16_t b)
{
return a > b ? a : b;
}
int32_t max_s32(int32_t a, int32_t b)
{
return a > b ? a : b;
}
int64_t max_s64(int64_t a, int64_t b)
{
return a > b ? a : b;
}
int16_t min_s16(int16_t a, int16_t b)
{
return a < b ? a : b;
}
int32_t min_s32(int32_t a, int32_t b)
{
return a < b ? a : b;
}
int64_t min_s64(int64_t a, int64_t b)
{
return a < b ? a : b;
}
uint8_t max_u08(uint8_t a, uint8_t b)
{
return a > b ? a : b;
}
uint16_t max_u16(uint16_t a, uint16_t b)
{
return a > b ? a : b;
}
uint32_t max_u32(uint32_t a, uint32_t b)
{
return a > b ? a : b;
}
uint64_t max_u64(uint64_t a, uint64_t b)
{
return a > b ? a : b;
}
uint16_t min_u16(uint16_t a, uint16_t b)
{
return a < b ? a : b;
}
uint32_t min_u32(uint32_t a, uint32_t b)
{
return a < b ? a : b;
}
uint64_t min_u64(uint64_t a, uint64_t b)
{
return a < b ? a : b;
}
int cmp_uint(uint64_t a, uint64_t b)
{
return (a > b ? 1 : 0) - (a < b ? 1 : 0);
}
uint32_t jenkins_one_at_a_time_hash(const uint8_t *key, size_t len)
{
uint32_t hash = 0;
for (uint32_t i = 0; i < len; ++i) {
hash += key[i];
hash += (uint32_t)((uint64_t)hash << 10);
hash ^= hash >> 6;
}
hash += (uint32_t)((uint64_t)hash << 3);
hash ^= hash >> 11;
hash += (uint32_t)((uint64_t)hash << 15);
return hash;
}
void bytes_to_string(const uint8_t *bytes, size_t bytes_length, char *str, size_t str_length)
{
if (str_length == 0) {
return;
}
if (bytes_length * 2 + 1 <= str_length) {
for (size_t i = 0; i < bytes_length; ++i) {
snprintf(&str[i * 2], str_length - i * 2, "%02X", bytes[i]);
}
str[bytes_length * 2] = '\0';
return;
}
if (str_length < 6) {
snprintf(str, str_length, "...");
return;
}
const size_t start_chars = str_length - 6;
const size_t start_bytes = start_chars / 2;
size_t current_pos = 0;
for (size_t i = 0; i < start_bytes; ++i) {
snprintf(str + current_pos, str_length - current_pos, "%02X", bytes[i]);
current_pos += 2;
}
snprintf(str + current_pos, str_length - current_pos, "...");
current_pos += 3;
snprintf(str + current_pos, str_length - current_pos, "%02X", bytes[bytes_length - 1]);
}