Am 30.06.2023 um 05:02 schrieb Pavel:
> Why to hardcode dots? Some use commas, some prefer underscores, some
> spaces...
That's just a detail. For my purpose dots are sufficient.
> Why to hardcode 3?
Because the groups will never be different.
> Why so many copies?
Because the row of / 10 calculations would be done only once.
> Why unhelpful names?
That's a matter of taste.
> Why a single function for at least two distinct jobs?
The function is for one jjob.
> Why no braces -- is this to make maintenance as error-prone as possible?
I don't make errors at this level-
> Why do I still have to read the code like this ???????
> It's no longer 1983! (cries and hits his head against his monitor)
My code is sexy for me.
This is the completed version:
#pragma once
#include <string_view>
#include <concepts>
#include <type_traits>
#include <array>
template<std::integral CharType, std::integral ValueType>
std::basic_string_view<CharType> dottifySv( ValueType value )
{
using namespace std;
static_assert(sizeof(ValueType) <= 8, "");
using uvalue_t = make_unsigned_t<ValueType>;
uvalue_t uValue;
if constexpr( signed_integral<ValueType> )
uValue = value >= 0 ? value : -value;
else
uValue = value;
using dig_arr_t = array<uint8_t, 20>; // max 20 digits for 64 bit
using dig_arr_it = dig_arr_t::iterator;
dig_arr_t reverseDigits;
dig_arr_it rDigitsEnd = reverseDigits.begin();
do
*rDigitsEnd++ = uValue % 10,
uValue /= 10;
while( uValue );
size_t groups = (rDigitsEnd - reverseDigits.begin() - 1) / 3;
using str_arr_t = array<CharType, 1 + 20 + (20 - 1) / 3>;
using str_arr_it = str_arr_t::iterator;
thread_local str_arr_t retArr;
str_arr_it wrt = retArr.end();
dig_arr_it digit = reverseDigits.begin();
auto append = [&]() { *--wrt = *digit++ + '0'; };
for( dig_arr_it groupsEnd = reverseDigits.begin() + groups * 3; digit
!= groupsEnd; wrt -= 4, digit += 3 )
append(),
append(),
append(),
*--wrt = '.';
do
append();
while( digit != rDigitsEnd );
if constexpr( signed_integral<ValueType> )
if( value < 0 )
*--wrt = '-';
return basic_string_view<CharType>( wrt, retArr.end() );
}
template<std::integral CharType, std::integral ValueType>
std::basic_string<CharType> dottify( ValueType value )
{
using namespace std;
basic_string_view<CharType> sv( dottifySv<CharType>( value ) );
return basic_string<CharType>( sv.begin(), sv.end() );
}