Files
test2/source/blender/blenlib/BLI_fixed_width_int_str.hh
2025-03-29 15:18:50 +11:00

80 lines
2.0 KiB
C++

/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bli
*/
#pragma once
/** Conversions to and from strings use GMP internally currently. */
#ifdef WITH_GMP
# include <gmpxx.h>
# include "BLI_array.hh"
# include "BLI_fixed_width_int.hh"
namespace blender::fixed_width_int {
template<typename T, int S>
inline void UIntF<T, S>::set_from_str(const StringRefNull str, const int base)
{
mpz_t x;
mpz_init(x);
mpz_set_str(x, str.c_str(), base);
for (int i = 0; i < S; i++) {
static_assert(sizeof(T) <= sizeof(decltype(mpz_get_ui(x))));
this->v[i] = T(mpz_get_ui(x));
mpz_div_2exp(x, x, 8 * sizeof(T));
}
mpz_clear(x);
}
template<typename T, int S>
inline void IntF<T, S>::set_from_str(const StringRefNull str, const int base)
{
if (str[0] == '-') {
const UIntF<T, S> unsigned_value(str.c_str() + 1, base);
this->v = unsigned_value.v;
*this = -*this;
}
else {
const UIntF<T, S> unsigned_value(str.c_str(), base);
this->v = unsigned_value.v;
}
}
template<typename T, int S> inline std::string UIntF<T, S>::to_string(const int base) const
{
mpz_t x;
mpz_init(x);
for (int i = S - 1; i >= 0; i--) {
static_assert(sizeof(T) <= sizeof(decltype(mpz_get_ui(x))));
mpz_mul_2exp(x, x, 8 * sizeof(T));
mpz_add_ui(x, x, this->v[i]);
}
/* Add 2 because of possible +/- sign and null terminator. */
/* Also see https://gmplib.org/manual/Converting-Integers. */
const int str_size = mpz_sizeinbase(x, base) + 2;
Array<char, 1024> str(str_size);
mpz_get_str(str.data(), base, x);
mpz_clear(x);
return std::string(str.data());
}
template<typename T, int S> inline std::string IntF<T, S>::to_string(const int base) const
{
if (is_negative(*this)) {
std::string str = UIntF<T, S>(-*this).to_string(base);
str.insert(str.begin(), '-');
return str;
}
return UIntF<T, S>(*this).to_string();
}
} // namespace blender::fixed_width_int
#endif /* WITH_GMP */