mirror of
https://github.com/KingDuckZ/dindexer.git
synced 2025-02-19 12:04:54 +00:00
Add bin tag to lexical_cast.
This also fixes a subtle bug: the size passed to MaxSizedArray in int_to_string() was calculated on the max value of type F, but when F was a signed type the max would only be for example 31 bits. Conversion of negative numbers would then fail with an assertion.
This commit is contained in:
parent
691bdd1d1e
commit
53a42fa7c0
2 changed files with 52 additions and 5 deletions
|
@ -24,7 +24,7 @@
|
|||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
@ -75,8 +75,8 @@ namespace dinhelp {
|
|||
};
|
||||
|
||||
template <template <typename> class Tag, typename T, typename F>
|
||||
inline auto int_to_string (const F parFrom) -> MaxSizedArray<uint8_t, Tag<F>::count_digits_bt(std::numeric_limits<F>::max())> {
|
||||
using ArrayRetType = MaxSizedArray<uint8_t, Tag<F>::count_digits_bt(std::numeric_limits<F>::max())>;
|
||||
inline auto int_to_string (const F parFrom) -> MaxSizedArray<uint8_t, Tag<F>::count_digits_bt(std::numeric_limits<typename std::make_unsigned<F>::type>::max())> {
|
||||
using ArrayRetType = MaxSizedArray<uint8_t, Tag<F>::count_digits_bt(std::numeric_limits<typename std::make_unsigned<F>::type>::max())>;
|
||||
|
||||
ArrayRetType retval;
|
||||
F div = 1;
|
||||
|
@ -116,7 +116,7 @@ namespace dinhelp {
|
|||
|
||||
static typename std::make_unsigned<T>::type make_unsigned ( T parValue ) a_pure;
|
||||
static constexpr std::size_t count_digits_bt (std::size_t parNum) {
|
||||
return (parNum == 0 ? 0 : static_cast<std::size_t>(::log10(parNum))) + 1 + (std::numeric_limits<T>::is_signed ? 1 : 0);
|
||||
return (parNum == 0 ? 0 : static_cast<std::size_t>(std::log10(static_cast<double>(parNum)))) + 1 + (std::numeric_limits<T>::is_signed ? 1 : 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -130,7 +130,21 @@ namespace dinhelp {
|
|||
static std::size_t count_digits ( T parValue ) a_pure;
|
||||
static typename std::make_unsigned<T>::type make_unsigned ( T parValue ) a_pure;
|
||||
static constexpr std::size_t count_digits_bt (std::size_t parNum) {
|
||||
return (parNum == 0 ? 0 : static_cast<std::size_t>(::log10(parNum) / ::log10(base))) + 1;
|
||||
return (parNum == 0 ? 0 : static_cast<std::size_t>(std::log10(static_cast<double>(parNum)) / std::log10(static_cast<double>(base)))) + 1;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct bin {
|
||||
enum {
|
||||
base = 2,
|
||||
sign_allowed = 0
|
||||
};
|
||||
|
||||
static std::size_t count_digits ( T parValue ) a_pure;
|
||||
static typename std::make_unsigned<T>::type make_unsigned ( T parValue ) a_pure;
|
||||
static constexpr std::size_t count_digits_bt (std::size_t parNum) {
|
||||
return (parNum == 0 ? 0 : static_cast<std::size_t>(std::log2(static_cast<double>(parNum)))) + 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -167,6 +181,16 @@ namespace dinhelp {
|
|||
typename std::make_unsigned<T>::type hex<T>::make_unsigned (T parValue) {
|
||||
return static_cast<typename std::make_unsigned<T>::type>(parValue);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::size_t bin<T>::count_digits (T parValue) {
|
||||
return std::max<std::size_t>((sizeof(parValue) * CHAR_BIT - dinhelp::implem::count_leading_zeroes<typename std::make_unsigned<T>::type>(make_unsigned(parValue))), 1);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename std::make_unsigned<T>::type bin<T>::make_unsigned (T parValue) {
|
||||
return static_cast<typename std::make_unsigned<T>::type>(parValue);
|
||||
}
|
||||
} //namespace tags
|
||||
|
||||
namespace implem {
|
||||
|
|
|
@ -25,6 +25,7 @@ TEST(helpers, lexical_cast) {
|
|||
using dinhelp::lexical_cast;
|
||||
using dinhelp::tags::hex;
|
||||
using dinhelp::tags::dec;
|
||||
using dinhelp::tags::bin;
|
||||
|
||||
{
|
||||
const uint8_t value = 0x34;
|
||||
|
@ -32,6 +33,8 @@ TEST(helpers, lexical_cast) {
|
|||
EXPECT_EQ("34", hex_str);
|
||||
const auto dec_str = lexical_cast<std::string, dec>(value);
|
||||
EXPECT_EQ("52", dec_str);
|
||||
const auto bin_str = lexical_cast<std::string, bin>(value);
|
||||
EXPECT_EQ("110100", bin_str);
|
||||
}
|
||||
{
|
||||
const uint16_t value = 0xFFFF;
|
||||
|
@ -39,6 +42,8 @@ TEST(helpers, lexical_cast) {
|
|||
EXPECT_EQ("FFFF", hex_str);
|
||||
const auto dec_str = lexical_cast<std::string, dec>(value);
|
||||
EXPECT_EQ("65535", dec_str);
|
||||
const auto bin_str = lexical_cast<std::string, bin>(value);
|
||||
EXPECT_EQ("1111111111111111", bin_str);
|
||||
}
|
||||
{
|
||||
const uint16_t value = 0xFF;
|
||||
|
@ -46,6 +51,8 @@ TEST(helpers, lexical_cast) {
|
|||
EXPECT_EQ("FF", hex_str);
|
||||
const auto dec_str = lexical_cast<std::string, dec>(value);
|
||||
EXPECT_EQ("255", dec_str);
|
||||
const auto bin_str = lexical_cast<std::string, bin>(value);
|
||||
EXPECT_EQ("11111111", bin_str);
|
||||
}
|
||||
{
|
||||
const uint16_t value = 0x100;
|
||||
|
@ -53,6 +60,8 @@ TEST(helpers, lexical_cast) {
|
|||
EXPECT_EQ("100", hex_str);
|
||||
const auto dec_str = lexical_cast<std::string, dec>(value);
|
||||
EXPECT_EQ("256", dec_str);
|
||||
const auto bin_str = lexical_cast<std::string, bin>(value);
|
||||
EXPECT_EQ("100000000", bin_str);
|
||||
}
|
||||
{
|
||||
const uint32_t value = 0x1ABC;
|
||||
|
@ -60,6 +69,8 @@ TEST(helpers, lexical_cast) {
|
|||
EXPECT_EQ("1ABC", hex_str);
|
||||
const auto dec_str = lexical_cast<std::string, dec>(value);
|
||||
EXPECT_EQ("6844", dec_str);
|
||||
const auto bin_str = lexical_cast<std::string, bin>(value);
|
||||
EXPECT_EQ("1101010111100", bin_str);
|
||||
}
|
||||
{
|
||||
const uint32_t value = 0xffffffff;
|
||||
|
@ -67,6 +78,8 @@ TEST(helpers, lexical_cast) {
|
|||
EXPECT_EQ("FFFFFFFF", hex_str);
|
||||
const auto dec_str = lexical_cast<std::string, dec>(value);
|
||||
EXPECT_EQ("4294967295", dec_str);
|
||||
const auto bin_str = lexical_cast<std::string, bin>(value);
|
||||
EXPECT_EQ("11111111111111111111111111111111", bin_str);
|
||||
}
|
||||
{
|
||||
const uint32_t value = 1;
|
||||
|
@ -74,6 +87,8 @@ TEST(helpers, lexical_cast) {
|
|||
EXPECT_EQ("1", hex_str);
|
||||
const auto dec_str = lexical_cast<std::string, dec>(value);
|
||||
EXPECT_EQ("1", dec_str);
|
||||
const auto bin_str = lexical_cast<std::string, bin>(value);
|
||||
EXPECT_EQ("1", bin_str);
|
||||
}
|
||||
{
|
||||
const uint32_t value = 0;
|
||||
|
@ -81,6 +96,8 @@ TEST(helpers, lexical_cast) {
|
|||
EXPECT_EQ("0", hex_str);
|
||||
const auto dec_str = lexical_cast<std::string, dec>(value);
|
||||
EXPECT_EQ("0", dec_str);
|
||||
const auto bin_str = lexical_cast<std::string, bin>(value);
|
||||
EXPECT_EQ("0", bin_str);
|
||||
}
|
||||
{
|
||||
const uint64_t value = 0x12abcd34;
|
||||
|
@ -88,6 +105,8 @@ TEST(helpers, lexical_cast) {
|
|||
EXPECT_EQ("12ABCD34", hex_str);
|
||||
const auto dec_str = lexical_cast<std::string, dec>(value);
|
||||
EXPECT_EQ("313249076", dec_str);
|
||||
const auto bin_str = lexical_cast<std::string, bin>(value);
|
||||
EXPECT_EQ("10010101010111100110100110100", bin_str);
|
||||
}
|
||||
{
|
||||
const int32_t value = 0x7800;
|
||||
|
@ -95,6 +114,8 @@ TEST(helpers, lexical_cast) {
|
|||
EXPECT_EQ("7800", hex_str);
|
||||
const auto dec_str = lexical_cast<std::string, dec>(value);
|
||||
EXPECT_EQ("30720", dec_str);
|
||||
const auto bin_str = lexical_cast<std::string, bin>(value);
|
||||
EXPECT_EQ("111100000000000", bin_str);
|
||||
}
|
||||
{
|
||||
const int32_t value = -1400;
|
||||
|
@ -102,5 +123,7 @@ TEST(helpers, lexical_cast) {
|
|||
EXPECT_EQ("FFFFFA88", hex_str);
|
||||
const auto dec_str = lexical_cast<std::string, dec>(value);
|
||||
EXPECT_EQ("-1400", dec_str);
|
||||
const auto bin_str = lexical_cast<std::string, bin>(value);
|
||||
EXPECT_EQ("11111111111111111111101010001000", bin_str);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue